summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/msm/sde.txt55
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt27
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-pll.txt3
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.txt4
-rw-r--r--Documentation/devicetree/bindings/platform/msm/ipa.txt2
-rw-r--r--Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt16
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt3
-rw-r--r--Documentation/devicetree/bindings/usb/msm-ssusb.txt4
-rw-r--r--Documentation/sysctl/kernel.txt15
-rw-r--r--arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts30
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi56
-rw-r--r--arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi30
-rw-r--r--arch/arm/boot/dts/qcom/fg-gen3-batterydata-itech-3000mah.dtsi50
-rw-r--r--arch/arm/boot/dts/qcom/fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi44
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi35
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660a.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi55
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-gpu.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-mtp.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi26
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-qrd.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dts44
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dtsi52
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi50
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi50
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-rumi.dts49
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi11
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-audio.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-blsp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-bus.dtsi55
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera-sensor-qrd.dtsi100
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi15
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-cdp.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-common.dtsi94
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-gpu.dtsi80
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec-cdp.dts6
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec-mtp.dts1
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-cdp.dts6
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-rcm.dts6
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec-rcm.dts6
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-internal-codec.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-lpi.dtsi22
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi88
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dtsi22
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi150
-rw-r--r--arch/arm/configs/msmcortex_defconfig6
-rw-r--r--arch/arm/configs/sdm660-perf_defconfig5
-rw-r--r--arch/arm/configs/sdm660_defconfig3
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig4
-rw-r--r--arch/arm64/configs/sdm660_defconfig8
-rw-r--r--arch/arm64/kernel/entry.S3
-rw-r--r--arch/arm64/mm/fault.c3
-rw-r--r--block/Kconfig9
-rw-r--r--block/bio.c6
-rw-r--r--block/blk-core.c468
-rw-r--r--block/blk.h9
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/adsprpc.c227
-rw-r--r--drivers/char/diag/diagchar.h4
-rw-r--r--drivers/char/diag/diagchar_core.c5
-rw-r--r--drivers/char/diag/diagfwd_peripheral.c6
-rw-r--r--drivers/char/diag/diagfwd_socket.c16
-rw-r--r--drivers/clk/clk.c45
-rw-r--r--drivers/clk/msm/clock-debug.c5
-rw-r--r--drivers/clk/msm/clock-gcc-8998.c1
-rw-r--r--drivers/clk/msm/clock-mmss-8998.c1
-rw-r--r--drivers/clk/qcom/clk-branch.c4
-rw-r--r--drivers/clk/qcom/clk-cpu-osm.c21
-rw-r--r--drivers/clk/qcom/gcc-sdm660.c2
-rw-r--r--drivers/clk/qcom/mdss/Makefile2
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c624
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c234
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h193
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll.h35
-rw-r--r--drivers/clk/qcom/mdss/mdss-pll.c10
-rw-r--r--drivers/clk/qcom/mdss/mdss-pll.h3
-rw-r--r--drivers/clk/qcom/mmcc-sdm660.c34
-rw-r--r--drivers/clk/qcom/vdd-level-660.h10
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/crypto/msm/qcedev.c15
-rw-r--r--drivers/gpu/drm/msm/Kconfig2
-rw-r--r--drivers/gpu/drm/msm/Makefile24
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c167
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h125
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h558
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c1321
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h192
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_defs.h357
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_hw.h39
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h164
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c858
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c5
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c21
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h17
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c24
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h3
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h1
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h18
-rw-r--r--drivers/gpu/drm/msm/msm_smmu.c432
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c676
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.h79
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c569
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h93
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c25
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c559
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c37
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.h479
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c303
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.c296
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.h115
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_dspp.c105
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_dspp.h127
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_interrupts.c969
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_interrupts.h245
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_intf.c389
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_intf.h107
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_lm.c192
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_lm.h96
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.c364
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h138
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_hwio.h0
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c110
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h66
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c73
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_util.h56
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdss.h358
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_pingpong.c159
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_pingpong.h115
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.c589
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.h282
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_wb.c120
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_wb.h85
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hwio.h59
-rw-r--r--drivers/gpu/drm/msm/sde/sde_irq.c350
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c499
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h304
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms_utils.c173
-rw-r--r--drivers/gpu/drm/msm/sde/sde_mdp_formats.c134
-rw-r--r--drivers/gpu/drm/msm/sde/sde_mdp_formats.h104
-rw-r--r--drivers/gpu/drm/msm/sde/sde_plane.c767
-rw-r--r--drivers/gpu/msm/adreno_a5xx_snapshot.c14
-rw-r--r--drivers/gpu/msm/kgsl_pool.c47
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c107
-rw-r--r--drivers/iommu/arm-smmu.c56
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c24
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c2
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_base.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c168
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.h10
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c22
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c12
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c12
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h6
-rw-r--r--drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c4
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c8
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_debug.h3
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c24
-rw-r--r--drivers/mfd/qcom-i2c-pmic.c21
-rw-r--r--drivers/mfd/wcd9xxx-core.c17
-rw-r--r--drivers/mfd/wcd9xxx-irq.c3
-rw-r--r--drivers/misc/hdcp.c49
-rw-r--r--drivers/misc/qcom/qdsp6v2/aac_in.c11
-rw-r--r--drivers/misc/qseecom.c1
-rw-r--r--drivers/mmc/card/block.c2
-rw-r--r--drivers/mmc/card/queue.c18
-rw-r--r--drivers/mmc/core/Kconfig11
-rw-r--r--drivers/mmc/core/Makefile1
-rw-r--r--drivers/mmc/core/debugfs.c25
-rw-r--r--drivers/mmc/core/host.c3
-rw-r--r--drivers/mmc/core/mmc.c5
-rw-r--r--drivers/mmc/core/ring_buffer.c123
-rw-r--r--drivers/mmc/core/sd.c4
-rw-r--r--drivers/mmc/core/sdio.c5
-rw-r--r--drivers/mmc/host/cmdq_hci.c33
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.c11
-rw-r--r--drivers/mmc/host/sdhci-msm.c7
-rw-r--r--drivers/mmc/host/sdhci.c35
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c159
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h206
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c14
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h9
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/hif.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c35
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h15
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c83
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c14
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h61
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c95
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h187
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c8
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c8
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c16
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h5
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c8
-rw-r--r--drivers/net/wireless/cw1200/sta.h4
-rw-r--r--drivers/net/wireless/iwlegacy/4965.h4
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c8
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/main.c8
-rw-r--r--drivers/net/wireless/mwl8k.c10
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c8
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c19
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c8
-rw-r--r--drivers/platform/msm/gsi/gsi.c29
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa.c11
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h4
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c94
-rw-r--r--drivers/platform/msm/msm_11ad/msm_11ad.c102
-rw-r--r--drivers/power/supply/qcom/smb-lib.c44
-rw-r--r--drivers/power/supply/qcom/smb138x-charger.c16
-rw-r--r--drivers/regulator/cpr3-mmss-regulator.c257
-rw-r--r--drivers/regulator/cpr3-regulator.h10
-rw-r--r--drivers/regulator/cpr3-util.c256
-rw-r--r--drivers/regulator/cpr4-mmss-ldo-regulator.c48
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c74
-rw-r--r--drivers/regulator/qpnp-oledb-regulator.c30
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c80
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c4
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h3
-rw-r--r--drivers/scsi/ufs/ufshcd.c11
-rw-r--r--drivers/soc/qcom/Kconfig8
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c12
-rw-r--r--drivers/soc/qcom/icnss.c10
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c16
-rw-r--r--drivers/soc/qcom/msm_smem.c18
-rw-r--r--drivers/soc/qcom/qdsp6v2/Makefile1
-rw-r--r--drivers/soc/qcom/qdsp6v2/cdsp-loader.c273
-rw-r--r--drivers/soc/qcom/service-notifier.c4
-rw-r--r--drivers/soc/qcom/wcd-dsp-glink.c51
-rw-r--r--drivers/spi/spi_qsd.c195
-rw-r--r--drivers/spi/spi_qsd.h14
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c91
-rw-r--r--drivers/usb/gadget/function/f_diag.c23
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c33
-rw-r--r--drivers/usb/gadget/function/f_qc_rndis.c1
-rw-r--r--drivers/usb/gadget/function/u_ctrl_qti.c2
-rw-r--r--drivers/usb/gadget/function/u_data_ipa.c8
-rw-r--r--drivers/usb/phy/phy-msm-usb.c2
-rw-r--r--drivers/video/fbdev/msm/mdss.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c1227
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h373
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c825
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c106
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h15
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c66
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c92
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h9
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp_1x.c44
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c70
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h18
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c55
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c72
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h12
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c57
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c207
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c154
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c38
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c12
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c12
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h16
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c87
-rw-r--r--fs/fuse/file.c2
-rw-r--r--include/dt-bindings/clock/mdss-pll-clk.h9
-rw-r--r--include/linux/blk_types.h13
-rw-r--r--include/linux/cpumask.h2
-rw-r--r--include/linux/ipa.h4
-rw-r--r--include/linux/irq.h11
-rw-r--r--include/linux/mfd/wcd9xxx/core.h3
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/mmc/ring_buffer.h55
-rw-r--r--include/linux/msm_ext_display.h10
-rw-r--r--include/linux/usb/composite.h2
-rw-r--r--include/net/cfg80211.h50
-rw-r--r--include/net/mac80211.h44
-rw-r--r--include/sound/apr_audio-v2.h82
-rw-r--r--include/sound/q6afe-v2.h4
-rw-r--r--include/sound/q6asm-v2.h12
-rw-r--r--include/uapi/linux/msm_audio_calibration.h27
-rw-r--r--include/uapi/linux/msm_mdp_ext.h12
-rw-r--r--include/uapi/linux/nl80211.h83
-rw-r--r--include/uapi/sound/compress_params.h10
-rw-r--r--include/uapi/video/msm_hdmi_modes.h13
-rw-r--r--kernel/irq/chip.c5
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c21
-rw-r--r--kernel/irq/proc.c2
-rw-r--r--kernel/irq/settings.h12
-rw-r--r--kernel/sched/hmp.c1
-rw-r--r--kernel/sysctl.c2
-rw-r--r--mm/page_alloc.c30
-rw-r--r--net/mac80211/agg-rx.c25
-rw-r--r--net/mac80211/agg-tx.c53
-rw-r--r--net/mac80211/driver-ops.c10
-rw-r--r--net/mac80211/driver-ops.h4
-rw-r--r--net/mac80211/trace.h43
-rw-r--r--net/rmnet_data/rmnet_data_vnd.c14
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/mlme.c21
-rw-r--r--net/wireless/nl80211.c155
-rw-r--r--security/pfe/pfk_kc.c50
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c21
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c41
-rw-r--r--sound/soc/codecs/wcd-mbhc-v2.c16
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c15
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.h9
-rw-r--r--sound/soc/msm/msm-dai-fe.c43
-rw-r--r--sound/soc/msm/msm8998.c23
-rw-r--r--sound/soc/msm/qdsp6v2/audio_cal_utils.c8
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c40
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c15
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c4
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c113
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c32
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c270
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c122
-rw-r--r--sound/soc/msm/qdsp6v2/q6voice.c47
-rw-r--r--sound/soc/msm/qdsp6v2/q6voice.h5
-rw-r--r--sound/soc/msm/sdm660-common.c4
-rw-r--r--sound/soc/msm/sdm660-common.h9
-rw-r--r--sound/soc/msm/sdm660-external.c64
-rw-r--r--sound/soc/msm/sdm660-external.h2
-rw-r--r--sound/soc/msm/sdm660-internal.c9
353 files changed, 10311 insertions, 17193 deletions
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
deleted file mode 100644
index 8ec9f78346d8..000000000000
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-Qualcomm Technologies, Inc. SDE KMS
-
-Snapdragon Display Engine implements Linux DRM/KMS APIs to drive user
-interface to different panel interfaces. SDE driver is the core of
-display subsystem which manage all data paths to different panel interfaces.
-
-Required properties
-- compatible: Must be "qcom,sde-kms"
-- reg: Offset and length of the register set for the device.
-- reg-names : Names to refer to register sets related to this device
-- clocks: List of Phandles for clock device nodes
- needed by the device.
-- clock-names: List of clock names needed by the device.
-- mmagic-supply: Phandle for mmagic mdss supply regulator device node.
-- vdd-supply: Phandle for vdd regulator device node.
-- interrupt-parent: Must be core interrupt controller.
-- interrupts: Interrupt associated with MDSS.
-- interrupt-controller: Mark the device node as an interrupt controller.
-- #interrupt-cells: Should be one. The first cell is interrupt number.
-- iommus: Specifies the SID's used by this context bank.
-
-Please refer to ../../interrupt-controller/interrupts.txt for a general
-description of interrupt bindings.
-
-Example:
- mdss_mdp: qcom,mdss_mdp@900000 {
- compatible = "qcom,sde-kms";
- reg = <0x00900000 0x90000>,
- <0x009b0000 0x1040>,
- <0x009b8000 0x1040>;
- reg-names = "mdp_phys",
- "vbif_phys",
- "vbif_nrt_phys";
- clocks = <&clock_mmss clk_mdss_ahb_clk>,
- <&clock_mmss clk_mdss_axi_clk>,
- <&clock_mmss clk_mdp_clk_src>,
- <&clock_mmss clk_mdss_mdp_vote_clk>,
- <&clock_mmss clk_smmu_mdp_axi_clk>,
- <&clock_mmss clk_mmagic_mdss_axi_clk>,
- <&clock_mmss clk_mdss_vsync_clk>;
- clock-names = "iface_clk",
- "bus_clk",
- "core_clk_src",
- "core_clk",
- "iommu_clk",
- "mmagic_clk",
- "vsync_clk";
- mmagic-supply = <&gdsc_mmagic_mdss>;
- vdd-supply = <&gdsc_mdss>;
- interrupt-parent = <&intc>;
- interrupts = <0 83 0>;
- interrupt-controller;
- #interrupt-cells = <1>;
- iommus = <&mdp_smmu 0>;
- };
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 52ffbe5c7207..b676efe97b8b 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -61,6 +61,30 @@ Required properties:
transmitted
byte 5, 6: 16 bits length in network byte order
byte 7 and beyond: number byte of payload
+- qcom,mdss-dsi-lp-mode-on: This is used to enable display low persistence mode.
+ A byte stream formed by multiple dcs packets base on
+ qcom dsi controller protocol.
+ byte 0: dcs data type
+ byte 1: set to indicate this is an individual packet
+ (no chain)
+ byte 2: virtual channel number
+ byte 3: expect ack from client (dcs read command)
+ byte 4: wait number of specified ms after dcs command
+ transmitted
+ byte 5, 6: 16 bits length in network byte order
+ byte 7 and beyond: number byte of payload
+- qcom,mdss-dsi-lp-mode-off: This is used to disable display low persistence mode.
+ A byte stream formed by multiple dcs packets base on
+ qcom dsi controller protocol.
+ byte 0: dcs data type
+ byte 1: set to indicate this is an individual packet
+ (no chain)
+ byte 2: virtual channel number
+ byte 3: expect ack from client (dcs read command)
+ byte 4: wait number of specified ms after dcs command
+ transmitted
+ byte 5, 6: 16 bits length in network byte order
+ byte 7 and beyond: number byte of payload
- qcom,mdss-dsi-post-panel-on-command: same as "qcom,mdss-dsi-on-command" except commands are
sent after displaying an image.
@@ -648,6 +672,9 @@ Example:
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command = [22 01 00 00 00 00 00];
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-lp-mode-on = [32 01 00 00 00 00 02 00 00
+ 29 01 00 00 10 00 02 FF 99];
+ qcom,mdss-dsi-lp-mode-off = [22 01 00 00 00 00 00];
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
diff --git a/Documentation/devicetree/bindings/fb/mdss-pll.txt b/Documentation/devicetree/bindings/fb/mdss-pll.txt
index 5d9a703c4823..b9d4ebfb79e3 100644
--- a/Documentation/devicetree/bindings/fb/mdss-pll.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-pll.txt
@@ -15,7 +15,8 @@ Required properties:
"qcom,mdss_hdmi_pll_8996_v2", "qcom,mdss_dsi_pll_8996_v2",
"qcom,mdss_hdmi_pll_8996_v3", "qcom,mdss_hdmi_pll_8996_v3_1p8",
"qcom,mdss_dsi_pll_8998", "qcom,mdss_dp_pll_8998",
- "qcom,mdss_hdmi_pll_8998", "qcom,mdss_dsi_pll_sdm660"
+ "qcom,mdss_hdmi_pll_8998", "qcom,mdss_dsi_pll_sdm660",
+ "qcom,mdss_dp_pll_sdm660"
- cell-index: Specifies the controller used
- reg: offset and length of the register set for the device.
- reg-names : names to refer to register sets related to this device
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index d00a5c1ce502..9e512d1ea763 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -139,8 +139,8 @@ conditions.
time. This should be a list of 2-tuples of the format:
<offset reg_value>.
-- qcom,bus-master-id : The master ID of the bus, if a bus vote is needed.
- See include/dt-bindings/msm/msm-bus-ids.h.
+Optional bus bindings as defined in
+Documentation/devicetree/bindings/arm/msm/msm_bus.txt may also be present.
Example:
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index 80f2d8f43e35..ed784f7f58a5 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -81,6 +81,8 @@ memory allocation over a PCIe bridge
- qcom,ipa-polling-iteration: IPA Polling Iteration Count,default is 40.
- qcom,ipa-tz-unlock-reg: Register start addresses and ranges which
need to be unlocked by TZ.
+- qcom,ipa-uc-monitor-holb: Boolean context flag to indicate whether
+ monitoring of holb via IPA uc is required.
IPA pipe sub nodes (A2 static pipes configurations):
diff --git a/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt b/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt
new file mode 100644
index 000000000000..33adc661448a
--- /dev/null
+++ b/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt
@@ -0,0 +1,16 @@
+Qualcomm Technologies, Inc. CDSP Loader Driver
+
+msm-cdsp-loader driver implements the mechanism that allows to load CDSP firmware images.
+
+Required properties:
+
+ - compatible: This must be "qcom,msm-cdsp-loader".
+ - qcom,proc-img-to-load: CDSP firmware name, must be "cdsp".
+
+Example:
+ The following for sdm660.
+
+ qcom,msm-cdsp-loader {
+ compatible = "qcom,cdsp-loader";
+ qcom,proc-img-to-load = "cdsp";
+ };
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
index 3e22f178aa82..d08ca957c954 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
@@ -203,10 +203,11 @@ IBB subnode required properties:
- qcom,qpnp-ibb-init-lcd-voltage: The default output voltage when IBB regulator
is configured in lcd mode.
+IBB subnode optional properties:
+
- qcom,qpnp-ibb-discharge-resistor: The discharge resistor in Kilo Ohms which
controls the soft start time. Supported values
are 300, 64, 32 and 16.
-IBB subnode optional properties:
- qcom,qpnp-ibb-slew-rate: The time (in us) taken by the regulator to change
voltage value in one step. This property is not
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index fa6ee8969946..47fad8aa4a1a 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -19,6 +19,7 @@ Required properties :
and reset lines used by this controller.
- reset-names: reset signal name strings sorted in the same order as the resets
property.
+- qcom,core-clk-rate: clock frequency to be set for USB master clock.
Optional properties :
- reg: Additional registers
@@ -54,7 +55,8 @@ Optional properties :
- qcom,disable-dev-mode-pm: If present, it disables PM runtime functionality for device mode.
- qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB
host mode is used.
-- qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock.
+- qcom,core-clk-rate-hs: If present, indicates min core clock frequency required to support
+ hs speed.
- extcon: phandles to external connector devices. First phandle should point to
external connector, which provide "USB" cable events, the second
should point to external connector device, which provide "USB-HOST"
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 2c5137a6fef6..6475fa234065 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -850,14 +850,13 @@ via the /proc/sys interface:
Each write syscall must fully contain the sysctl value to be
written, and multiple writes on the same sysctl file descriptor
will rewrite the sysctl value, regardless of file position.
- 0 - (default) Same behavior as above, but warn about processes that
- perform writes to a sysctl file descriptor when the file position
- is not 0.
- 1 - Respect file position when writing sysctl strings. Multiple writes
- will append to the sysctl value buffer. Anything past the max length
- of the sysctl value buffer will be ignored. Writes to numeric sysctl
- entries must always be at file position 0 and the value must be
- fully contained in the buffer sent in the write syscall.
+ 0 - Same behavior as above, but warn about processes that perform writes
+ to a sysctl file descriptor when the file position is not 0.
+ 1 - (default) Respect file position when writing sysctl strings. Multiple
+ writes will append to the sysctl value buffer. Anything past the max
+ length of the sysctl value buffer will be ignored. Writes to numeric
+ sysctl entries must always be at file position 0 and the value must
+ be fully contained in the buffer sent in the write syscall.
==============================================================
diff --git a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
index 03fa038d9413..bc18fb54400f 100644
--- a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
+++ b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -46,3 +46,31 @@
};
};
};
+
+&mdss_dsi {
+ status = "disabled";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm8998_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm8998_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_cd_on_mediabox>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_cd_off_mediabox>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ cd-gpios = <&tlmm 86 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi
index 7bd844ae6770..6d91e72851ec 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -57,6 +57,60 @@
05 01 00 00 b4 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-lp-mode-on = [39 00 00 00 05 00 03 f0 5a 5a
+ 39 00 00 00 05 00 03 f1 5a 5a
+ 39 00 00 00 05 00 03 fc 5a 5a
+ 39 00 00 00 05 00 02 b0 17
+ 39 00 00 00 05 00 02 cb 10
+ 39 00 00 00 05 00 02 b0 2d
+ 39 00 00 00 05 00 02 cb cd
+ 39 00 00 00 05 00 02 b0 0e
+ 39 00 00 00 05 00 02 cb 02
+ 39 00 00 00 05 00 02 b0 0f
+ 39 00 00 00 05 00 02 cb 09
+ 39 00 00 00 05 00 02 b0 02
+ 39 00 00 00 05 00 02 f2 c9
+ 39 00 00 00 05 00 02 b0 03
+ 39 00 00 00 05 00 02 f2 c0
+ 39 00 00 00 05 00 02 b0 03
+ 39 00 00 00 05 00 02 f4 aa
+ 39 00 00 00 05 00 02 b0 08
+ 39 00 00 00 05 00 02 b1 30
+ 39 00 00 00 05 00 02 b0 09
+ 39 00 00 00 05 00 02 b1 0a
+ 39 00 00 00 05 00 02 b0 0d
+ 39 00 00 00 05 00 02 b1 10
+ 39 00 00 00 05 00 02 b0 00
+ 39 00 00 00 05 00 02 f7 03
+ 39 00 00 00 05 00 02 fe 30
+ 39 01 00 00 05 00 02 fe b0];
+ qcom,mdss-dsi-lp-mode-off = [39 00 00 00 05 00 03 f0 5a 5a
+ 39 00 00 00 05 00 03 f1 5a 5a
+ 39 00 00 00 05 00 03 fc 5a 5a
+ 39 00 00 00 05 00 02 b0 2d
+ 39 00 00 00 05 00 02 cb 4d
+ 39 00 00 00 05 00 02 b0 17
+ 39 00 00 00 05 00 02 cb 04
+ 39 00 00 00 05 00 02 b0 0e
+ 39 00 00 00 05 00 02 cb 06
+ 39 00 00 00 05 00 02 b0 0f
+ 39 00 00 00 05 00 02 cb 05
+ 39 00 00 00 05 00 02 b0 02
+ 39 00 00 00 05 00 02 f2 b8
+ 39 00 00 00 05 00 02 b0 03
+ 39 00 00 00 05 00 02 f2 80
+ 39 00 00 00 05 00 02 b0 03
+ 39 00 00 00 05 00 02 f4 8a
+ 39 00 00 00 05 00 02 b0 08
+ 39 00 00 00 05 00 02 b1 10
+ 39 00 00 00 05 00 02 b0 09
+ 39 00 00 00 05 00 02 b1 0a
+ 39 00 00 00 05 00 02 b0 0d
+ 39 00 00 00 05 00 02 b1 80
+ 39 00 00 00 05 00 02 b0 00
+ 39 00 00 00 05 00 02 f7 03
+ 39 00 00 00 05 00 02 fe 30
+ 39 01 00 00 05 00 02 fe b0];
qcom,mdss-dsi-h-sync-pulse = <0>;
qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
qcom,mdss-dsi-lane-map = "lane_map_0123";
diff --git a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
index 76f7c498d2cd..c7cecbca3929 100644
--- a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
+++ b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,36 +11,36 @@
*/
qcom,ascent_3450mah {
- /* Ascent_with_connector_3450mAh_averaged_MasterSlave_Nov28th2016 */
+ /* Ascent_with_connector_3450mAh_averaged_MasterSlave_Jan6th2017 */
qcom,max-voltage-uv = <4350000>;
qcom,fg-cc-cv-threshold-mv = <4340>;
qcom,fastchg-current-ma = <3450>;
qcom,batt-id-kohm = <60>;
qcom,battery-beta = <3435>;
- qcom,battery-type = "ascent_3450mah_averaged_masterslave_nov28th2016";
- qcom,checksum = <0x2232>;
- qcom,gui-version = "PMI8998GUI - 2.0.0.52";
+ qcom,battery-type = "ascent_3450mah_averaged_masterslave_jan6th2017";
+ qcom,checksum = <0x96AC>;
+ qcom,gui-version = "PMI8998GUI - 2.0.0.54";
qcom,fg-profile-data = [
9C 1F 85 05
82 0A 73 FC
- 2B 1D 6A EA
- F2 03 63 0C
- C8 17 F3 22
+ 2B 1D 72 EA
+ EE 03 66 0C
+ C8 17 F4 22
E0 45 1F 52
5C 00 00 00
10 00 00 00
00 00 4A C4
C7 BC 48 C2
0F 00 08 00
- 92 00 5D ED
- 8D FD B1 F3
- 27 00 A6 12
- 77 F4 0F 3B
+ E1 DA 5D ED
+ 8D FD B2 F3
+ 96 E2 A7 12
+ 7E F4 0E 3B
24 06 09 20
27 00 14 00
83 1F EE 05
1F 0A 45 FD
- 6B 1D 52 E5
+ 6B 1D 53 E5
EC 0B 31 14
44 18 49 23
18 45 A6 53
@@ -50,9 +50,9 @@ qcom,ascent_3450mah {
B7 C3 0F BC
0F 00 00 00
92 00 5D ED
- E3 06 81 F3
+ E3 06 E0 00
75 FD 9C 03
- 43 DB B3 22
+ 47 DB B3 22
CB 33 CC FF
07 10 00 00
99 0D 99 45
diff --git a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-itech-3000mah.dtsi b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-itech-3000mah.dtsi
index d196a8074d8a..03801ee90589 100644
--- a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-itech-3000mah.dtsi
+++ b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-itech-3000mah.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,37 +11,37 @@
*/
qcom,itech_3000mah {
- /* #Itech_B00826LF_3000mAh_ver1660_averaged_MasterSlave_Jul20th2016*/
+ /* #Itech_B00826LF_3000mAh_ver1660_averaged_MasterSlave_Jan10th2017*/
qcom,max-voltage-uv = <4350000>;
qcom,fg-cc-cv-threshold-mv = <4340>;
qcom,fastchg-current-ma = <3000>;
qcom,batt-id-kohm = <100>;
- qcom,battery-beta = <3450>;
- qcom,battery-type = "itech_b00826lf_3000mah_ver1660";
- qcom,checksum = <0xE06B>;
- qcom,gui-version = "PMI8998GUI - 0.0.0.82";
+ qcom,battery-beta = <3435>;
+ qcom,battery-type = "itech_b00826lf_3000mah_ver1660_jan10th2017";
+ qcom,checksum = <0xFB8F>;
+ qcom,gui-version = "PMI8998GUI - 2.0.0.54";
qcom,fg-profile-data = [
A4 1F 6E 05
- 9C 0A 16 06
- 32 1D 24 E5
- 61 0B 1B 15
+ 9C 0A 2B FC
+ 32 1D 23 E5
+ 60 0B 1B 15
AD 17 8C 22
- EB 3C 87 4A
+ EA 3C 89 4A
5B 00 00 00
12 00 00 00
00 00 62 C2
0C CD D8 C2
- 19 00 0C 00
- 7E 00 C7 EC
- E3 05 5D FA
- 97 F5 12 12
- C2 05 90 3B
- 22 09 40 40
- 07 00 05 00
- 7D 1F DE 05
- 3F 0A 73 06
- 72 1D E2 F5
- 6F 12 BF 1D
+ 19 00 08 00
+ 85 EA C7 EC
+ E2 05 2F 01
+ 9B F5 12 12
+ 5E 05 88 3B
+ 22 06 09 20
+ 27 00 14 00
+ 7D 1F DD 05
+ 3F 0A E5 FC
+ 72 1D E3 F5
+ 6F 12 C0 1D
88 18 FB 22
8D 45 C6 52
54 00 00 00
@@ -51,12 +51,12 @@ qcom,itech_3000mah {
14 00 00 00
7E 00 C7 EC
60 06 BB 00
- B3 FC 61 03
- 6A 06 78 1B
- B3 33 08 33
+ 59 06 61 03
+ D9 FC 75 1B
+ B3 33 CC FF
07 10 00 00
3E 0B 99 45
- 14 00 19 00
+ 14 00 40 00
AE 01 0A FA
FF 00 00 00
00 00 00 00
diff --git a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi
index e023a7700437..8cbb29aac927 100644
--- a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi
+++ b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,34 +11,36 @@
*/
qcom,qrd_msm8998_skuk_3000mah {
+ /* QRD8997_ST1031GA_3000mAh_averaged_MasterSlave_Jan10th2017 */
qcom,max-voltage-uv = <4400000>;
qcom,fastchg-current-ma = <3000>;
qcom,batt-id-kohm = <68>;
qcom,battery-beta = <3380>;
- qcom,battery-type = "qrd_msm8998_skuk_300mah";
- qcom,checksum = <0x0F19>;
+ qcom,battery-type = "qrd8997_st1031ga_3000mah";
+ qcom,checksum = <0xD299>;
+ qcom,gui-version = "PMI8998GUI - 2.0.0.54";
qcom,fg-profile-data = [
- 6F 1F B2 05
- 6E 0A A3 FC
- 8C 1D DB FD
- C2 12 AE 1D
- 7E 18 00 23
- 8D 45 B4 52
+ 70 1F B1 05
+ 6F 0A A1 FC
+ 8C 1D D7 FD
+ C4 12 AC 1D
+ 7E 18 01 23
+ 8C 45 B6 52
55 00 00 00
0F 00 00 00
00 00 92 C5
95 CD A0 CA
- 1F 00 0C 00
- 56 F2 C3 EC
- 7B 06 27 F3
+ 1F 00 08 00
+ 9F E3 C3 EC
+ F7 FC 25 F3
02 01 FF 12
- 1C DA 21 3A
- 1C 09 40 40
- 07 00 05 00
+ 29 DC 1D 3A
+ 1C 06 09 20
+ 27 00 14 00
AC 1F B4 05
57 0A EF FC
- 6A 1D 2E 00
- 12 0B BA 14
+ 6A 1D E9 E2
+ 11 0B BB 14
40 19 DC 22
79 45 03 53
53 00 00 00
@@ -48,12 +50,12 @@ qcom,qrd_msm8998_skuk_3000mah {
1C 00 00 00
56 F2 C3 EC
A6 06 A2 F2
- 96 06 C7 01
- 8B EA CF 1A
- BA 33 08 33
+ 9A 06 CC 01
+ 8C EA CF 1A
+ BA 33 CC FF
07 10 00 00
3A 0C 66 46
- 1C 00 19 00
+ 1C 00 40 00
98 01 0A FA
FF 00 00 00
00 00 00 00
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
index 0ba86e81887f..ecfff13f9355 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,9 +29,14 @@
<GIC_SPI 367 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 368 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clock_gcc clk_aggre1_noc_clk>;
- clock-names = "smmu_aggre1_noc_clk";
- #clock-cells = <1>;
+ qcom,msm-bus,name = "smmu-bus-client-anoc1";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,num-paths = <1>;
+ /* aggre1_noc_clk */
+ qcom,msm-bus,vectors-KBps =
+ <84 10062 0 0>,
+ <84 10062 0 1000>;
};
anoc2_smmu: arm,smmu-anoc2@16c0000 {
@@ -52,9 +57,14 @@
<GIC_SPI 463 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 465 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clock_gcc clk_aggre2_noc_clk>;
- clock-names = "smmu_aggre2_noc_clk";
- #clock-cells = <1>;
+ qcom,msm-bus,name = "smmu-bus-client-anoc2";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,num-paths = <1>;
+ /* aggre2_noc_clk */
+ qcom,msm-bus,vectors-KBps =
+ <117 10065 0 0>,
+ <117 10065 0 1000>;
};
lpass_q6_smmu: arm,smmu-lpass_q6@5100000 {
@@ -116,15 +126,20 @@
<GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
vdd-supply = <&gdsc_bimc_smmu>;
clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>,
- <&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
<&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
clock-names = "mmss_mnoc_ahb_clk",
- "mmssnoc_axi_clk",
"mmss_bimc_smmu_ahb_clk",
"mmss_bimc_smmu_axi_clk";
#clock-cells = <1>;
- qcom,bus-master-id = <MSM_BUS_MNOC_BIMC_MAS>;
+ qcom,msm-bus,name = "smmu-bus-client-mmss";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,num-paths = <2>;
+ /* ahb_clk_src, mmssnoc_axi_clk */
+ qcom,msm-bus,vectors-KBps =
+ <102 722 0 0>, <29 512 0 0>,
+ <102 722 0 1000>, <29 512 0 1000>;
};
kgsl_smmu: arm,smmu-kgsl@5040000 {
diff --git a/arch/arm/boot/dts/qcom/msm-audio.dtsi b/arch/arm/boot/dts/qcom/msm-audio.dtsi
index e4903a821bc1..bc960093fcea 100644
--- a/arch/arm/boot/dts/qcom/msm-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-audio.dtsi
@@ -827,6 +827,7 @@
qcom,msm-mclk-freq = <9600000>;
qcom,msm-mbhc-hphl-swh = <1>;
qcom,msm-mbhc-gnd-swh = <1>;
+ qcom,msm-micbias2-ext-cap;
qcom,msm-hs-micbias-type = "external";
qcom,us-euro-gpios = <&us_euro_gpio>;
qcom,cdc-pdm-gpios = <&cdc_pdm_gpios>;
@@ -928,7 +929,6 @@
};
clock_audio: audio_ext_clk {
- status = "disabled";
compatible = "qcom,audio-ref-clk";
qcom,audio-ref-clk-gpio = <&pm660_gpios 3 0>;
clock-names = "osr_clk";
diff --git a/arch/arm/boot/dts/qcom/msm-pm660a.dtsi b/arch/arm/boot/dts/qcom/msm-pm660a.dtsi
index c43aa5425aae..bfe1b5aa831b 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660a.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660a.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,3 +19,11 @@
&pm660l_lcdb {
status = "disabled";
};
+
+&pm660a_oledb {
+ status = "okay";
+};
+
+&pm660a_labibb {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
index 3ac4c851f5ba..cdb3662a1a56 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -404,5 +404,60 @@
regulator-max-microvolt = <6000000>;
};
};
+
+ pm660a_oledb: qpnp-oledb@e000 {
+ compatible = "qcom,qpnp-oledb-regulator";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xe000 0x100>;
+
+ label = "oledb";
+ regulator-name = "regulator-oledb";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <8100000>;
+
+ qcom,swire-control;
+ qcom,ext-pin-control;
+ status = "disabled";
+ };
+
+ pm660a_labibb: qpnp-labibb-regulator {
+ compatible = "qcom,qpnp-labibb-regulator";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,pmic-revid = <&pm660l_revid>;
+ qcom,swire-control;
+ status = "disabled";
+
+ ibb_regulator: qcom,ibb@dc00 {
+ reg = <0xdc00 0x100>;
+ reg-names = "ibb_reg";
+ regulator-name = "ibb_reg";
+
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6300000>;
+
+ qcom,qpnp-ibb-min-voltage = <1400000>;
+ qcom,qpnp-ibb-step-size = <100000>;
+ qcom,qpnp-ibb-slew-rate = <2000000>;
+ qcom,qpnp-ibb-init-voltage = <4000000>;
+ qcom,qpnp-ibb-init-amoled-voltage = <4000000>;
+ };
+
+ lab_regulator: qcom,lab@de00 {
+ reg = <0xde00 0x100>;
+ reg-names = "lab";
+ regulator-name = "lab_reg";
+
+ regulator-min-microvolt = <4600000>;
+ regulator-max-microvolt = <6100000>;
+
+ qcom,qpnp-lab-min-voltage = <4600000>;
+ qcom,qpnp-lab-step-size = <100000>;
+ qcom,qpnp-lab-slew-rate = <5000>;
+ qcom,qpnp-lab-init-voltage = <4600000>;
+ qcom,qpnp-lab-init-amoled-voltage = <4600000>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index b1880c076e1c..be47b6483288 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -534,7 +534,6 @@
qcom,qpnp-ibb-soft-start = <1000>;
- qcom,qpnp-ibb-discharge-resistor = <32>;
qcom,qpnp-ibb-lab-pwrup-delay = <8000>;
qcom,qpnp-ibb-lab-pwrdn-delay = <8000>;
qcom,qpnp-ibb-en-discharge;
diff --git a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
index 9a497a473a56..45ab53ccc2c2 100644
--- a/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -98,6 +98,7 @@
qcom,gpubw-dev = <&gpubw>;
qcom,bus-control;
qcom,msm-bus,name = "grp3d";
+ qcom,bus-width = <32>;
qcom,msm-bus,num-cases = <13>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
index 9bab7c037d40..bfe29ff56413 100644
--- a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
#include "dsi-panel-sim-dualmipi-video.dtsi"
#include "dsi-panel-sim-dualmipi-cmd.dtsi"
#include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi"
+#include "dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -196,3 +197,9 @@
qcom,mdss-dsi-t-clk-post = <0x07>;
qcom,mdss-dsi-t-clk-pre = <0x2a>;
};
+
+&dsi_dual_nt36850_truly_cmd {
+ qcom,mdss-dsi-panel-timings = [00 1c 06 06 0b 11 06 07 05 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x34>;
+ qcom,mdss-dsi-t-clk-pre = <0x2a>;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi
index c1d550a4bbff..a0e56f630eb7 100644
--- a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -564,3 +564,7 @@
#include "fg-gen3-batterydata-demo-6000mah.dtsi"
};
};
+
+&pmi8998_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
index ce3604f4dc3b..19b227f1b60f 100644
--- a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
@@ -3143,5 +3143,31 @@
};
};
};
+
+ sdc2_cd_on_mediabox: sdc2_cd_on_mediabox {
+ mux {
+ pins = "gpio86";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio86";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc2_cd_off_mediabox: sdc2_cd_off_mediabox {
+ mux {
+ pins = "gpio86";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio86";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi
index 150194a0e86f..af533bbfbc83 100644
--- a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -510,13 +510,17 @@
};
/{
- mtp_batterydata: qcom,battery-data {
+ qrd_batterydata: qcom,battery-data {
qcom,batt-id-range-pct = <15>;
#include "fg-gen3-batterydata-itech-3000mah.dtsi"
#include "fg-gen3-batterydata-ascent-3450mah.dtsi"
};
};
+&pmi8998_fg {
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dts b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dts
index d48516381e29..180cc9128f53 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dts
+++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dts
@@ -146,6 +146,50 @@
qcom,battery-data = <&qrd_batterydata>;
};
+&mdss_dsi {
+ hw-config = "split_dsi";
+ vdda-1p2-supply = <&pm660_l1>;
+ vdda-0p9-supply = <&pm660l_l1>;
+
+ qcom,ctrl-supply-entries {
+ qcom,ctrl-supply-entry@0 {
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1250000>;
+ };
+ };
+
+ qcom,phy-supply-entries {
+ qcom,phy-supply-entry@0 {
+ qcom,supply-min-voltage = <880000>;
+ qcom,supply-max-voltage = <925000>;
+ };
+ };
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt36850_truly_cmd>;
+ wqhd-vddio-supply = <&pm660_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt36850_truly_cmd>;
+ wqhd-vddio-supply = <&pm660_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
&pm660l_wled {
qcom,led-strings-list = [00 01];
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dtsi
index 5a882c7eb27f..c92872648709 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-sdm660-qrd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -123,3 +123,53 @@
synaptics,button-map = <139 172 158>;
};
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_fb0 {
+ qcom,mdss-mixer-swap;
+};
+
+&mdss_dsi {
+ hw-config = "split_dsi";
+ vdda-1p2-supply = <&pm660_l1>;
+ vdda-0p9-supply = <&pm660l_l1>;
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt36850_truly_cmd>;
+ wqhd-vddio-supply = <&pm660_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt36850_truly_cmd>;
+ wqhd-vddio-supply = <&pm660_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "lcd";
+};
+
+&dsi_dual_nt36850_truly_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index cfdbf98af76e..30679791006b 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -1286,8 +1286,7 @@
compatible = "qcom,glink_ssr";
label = "modem";
qcom,edge = "mpss";
- qcom,notify-edges = <&glink_lpass>, <&glink_dsps>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_lpass>, <&glink_dsps>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1295,8 +1294,7 @@
compatible = "qcom,glink_ssr";
label = "adsp";
qcom,edge = "lpass";
- qcom,notify-edges = <&glink_mpss>, <&glink_dsps>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_mpss>, <&glink_dsps>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1304,8 +1302,7 @@
compatible = "qcom,glink_ssr";
label = "slpi";
qcom,edge = "dsps";
- qcom,notify-edges = <&glink_mpss>, <&glink_lpass>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_mpss>, <&glink_lpass>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1739,6 +1736,7 @@
"utmi_clk", "sleep_clk", "xo";
qcom,core-clk-rate = <120000000>;
+ qcom,core-clk-rate-hs = <60000000>;
resets = <&clock_gcc USB_30_BCR>;
reset-names = "core_reset";
@@ -2243,7 +2241,7 @@
};
sensor_information22: qcom,sensor-information-22 {
qcom,sensor-type = "alarm";
- qcom,sensor-name = "pm8994_tz";
+ qcom,sensor-name = "pm8998_tz";
qcom,scaling-factor = <1000>;
};
sensor_information23: qcom,sensor-information-23 {
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index c22926510f94..e2344063ce16 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -11,6 +11,7 @@
*/
#include "sdm660-pinctrl.dtsi"
+#include "sdm660-camera-sensor-cdp.dtsi"
/ {
};
@@ -26,3 +27,52 @@
&pm660_charger {
qcom,batteryless-platform;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <110 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index b4b22d31402e..7a4e36ddda9e 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -11,6 +11,7 @@
*/
#include "sdm660-pinctrl.dtsi"
+#include "sdm660-camera-sensor-mtp.dtsi"
/ {
mtp_batterydata: qcom,battery-data {
qcom,batt-id-range-pct = <15>;
@@ -35,3 +36,52 @@
&pm660_fg {
qcom,battery-data = <&mtp_batterydata>;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <110 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-rumi.dts b/arch/arm/boot/dts/qcom/sdm630-rumi.dts
index ddf954f9f6ff..2ea1af4da90c 100644
--- a/arch/arm/boot/dts/qcom/sdm630-rumi.dts
+++ b/arch/arm/boot/dts/qcom/sdm630-rumi.dts
@@ -86,3 +86,52 @@
compatible = "qcom,dummycc";
clock-output-names = "debug_clocks";
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <110 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index 5002a11652ae..dbff3394ce76 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -26,6 +26,8 @@
aliases {
serial0 = &uartblsp1dm1;
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+ sdhc2 = &sdhc_2; /* SDC2 for SD card */
};
chosen {
@@ -908,6 +910,13 @@
};
};
+ qcom,rmtfs_sharedmem@0 {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x0 0x200000>;
+ reg-names = "rmtfs";
+ qcom,client-id = <0x00000001>;
+ };
+
qcom,rmnet-ipa {
compatible = "qcom,rmnet-ipa";
qcom,rmnet-ipa-ssr;
@@ -1101,7 +1110,6 @@
compatible = "qcom,rpm-glink";
qcom,glink-edge = "rpm";
rpm-channel-name = "rpm_requests";
- rpm-standalone;
};
qcom,ipc_router {
@@ -1387,6 +1395,7 @@
#include "msm-gdsc-660.dtsi"
#include "sdm660-common.dtsi"
#include "msm-arm-smmu-630.dtsi"
+#include "sdm660-camera.dtsi"
&gdsc_usb30 {
status = "ok";
diff --git a/arch/arm/boot/dts/qcom/sdm660-audio.dtsi b/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
index 766642dced6a..6f9a6f9ee946 100644
--- a/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
@@ -167,8 +167,8 @@
cdc_pdm_gpios: cdc_pdm_pinctrl {
compatible = "qcom,msm-cdc-pinctrl";
pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&cdc_pdm_gpios_active>;
- pinctrl-1 = <&cdc_pdm_gpios_sleep>;
+ pinctrl-0 = <&cdc_pdm_gpios_active &cdc_pdm_2_gpios_active>;
+ pinctrl-1 = <&cdc_pdm_gpios_sleep &cdc_pdm_2_gpios_sleep>;
qcom,lpi-gpios;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi b/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
index 023c34d65680..555d9a285102 100644
--- a/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -518,9 +518,10 @@
clocks = <&clock_gcc GCC_BLSP2_UART1_APPS_CLK>,
<&clock_gcc GCC_BLSP2_AHB_CLK>;
pinctrl-names = "sleep", "default";
- pinctrl-0 = <&blsp2_uart1_sleep>;
- pinctrl-1 = <&blsp2_uart1_active>;
-
+ pinctrl-0 = <&blsp2_uart1_tx_sleep>,
+ <&blsp2_uart1_rxcts_sleep>, <&blsp2_uart1_rfr_sleep>;
+ pinctrl-1 = <&blsp2_uart1_tx_active>,
+ <&blsp2_uart1_rxcts_active>, <&blsp2_uart1_rfr_active>;
qcom,msm-bus,name = "buart3";
qcom,msm-bus,num-cases = <2>;
qcom,msm-bus,num-paths = <1>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
index 93c615639be9..68ff96829d4f 100644
--- a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,7 +34,6 @@
label = "fab-a2noc";
qcom,fab-dev;
qcom,base-name = "a2noc-base";
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
qcom,qos-off = <4096>;
qcom,base-offset = <16384>;
@@ -44,16 +43,16 @@
qcom,node-qos-clks {
clock-names =
"clk-ipa-clk",
- "clk-sdcc1-ahb-no-rate",
- "clk-sdcc2-ahb-no-rate",
- "clk-blsp1-ahb-no-rate",
- "clk-blsp2-ahb-no-rate";
+ "clk-ufs-axi-clk",
+ "clk-aggre2-ufs-axi-no-rate",
+ "clk-aggre2-usb3-axi-cfg-no-rate",
+ "clk-cfg-noc-usb2-axi-no-rate";
clocks =
<&clock_rpmcc RPM_IPA_CLK>,
- <&clock_gcc GCC_SDCC1_AHB_CLK>,
- <&clock_gcc GCC_SDCC2_AHB_CLK>,
- <&clock_gcc GCC_BLSP1_AHB_CLK>,
- <&clock_gcc GCC_BLSP2_AHB_CLK>;
+ <&clock_gcc GCC_UFS_AXI_CLK>,
+ <&clock_gcc GCC_AGGRE2_UFS_AXI_CLK>,
+ <&clock_gcc GCC_AGGRE2_USB3_AXI_CLK>,
+ <&clock_gcc GCC_CFG_NOC_USB2_AXI_CLK>;
};
};
@@ -63,7 +62,6 @@
qcom,fab-dev;
qcom,base-name = "bimc-base";
qcom,bus-type = <2>;
- qcom,bypass-qos-prg;
qcom,util-fact = <153>;
clock-names = "bus_clk", "bus_a_clk";
clocks = <&clock_rpmcc BIMC_MSMBUS_CLK>,
@@ -75,7 +73,6 @@
label = "fab-cnoc";
qcom,fab-dev;
qcom,base-name = "cnoc-base";
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clock-names = "bus_clk", "bus_a_clk";
clocks = <&clock_rpmcc CNOC_MSMBUS_CLK>,
@@ -87,7 +84,6 @@
label = "fab-gnoc";
qcom,virt-dev;
qcom,base-name = "gnoc-base";
- qcom,bypass-qos-prg;
};
fab_mnoc: fab-mnoc {
@@ -95,7 +91,6 @@
label = "fab-mnoc";
qcom,fab-dev;
qcom,base-name = "mnoc-base";
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
qcom,qos-off = <4096>;
qcom,base-offset = <20480>;
@@ -103,27 +98,13 @@
clock-names = "bus_clk", "bus_a_clk";
clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
<&clock_rpmcc MMSSNOC_AXI_A_CLK>;
- clk-camss-ahb-no-rate-supply =
- <&gdsc_camss_top>;
- clk-video-ahb-no-rate-supply =
- <&gdsc_venus>;
- clk-video-axi-no-rate-supply =
- <&gdsc_venus>;
qcom,node-qos-clks {
clock-names =
"clk-mmssnoc-axi-no-rate",
- "clk-noc-cfg-ahb-no-rate",
- "clk-mnoc-ahb-no-rate",
- "clk-camss-ahb-no-rate",
- "clk-video-ahb-no-rate",
- "clk-video-axi-no-rate";
+ "clk-mmss-noc-cfg-ahb-no-rate";
clocks =
<&clock_rpmcc MMSSNOC_AXI_CLK>,
- <&clock_gcc GCC_MMSS_NOC_CFG_AHB_CLK>,
- <&clock_mmss MMSS_MNOC_AHB_CLK>,
- <&clock_mmss MMSS_CAMSS_AHB_CLK>,
- <&clock_mmss MMSS_VIDEO_AHB_CLK>,
- <&clock_mmss MMSS_VIDEO_AXI_CLK>;
+ <&clock_gcc GCC_MMSS_NOC_CFG_AHB_CLK>;
};
};
@@ -132,7 +113,6 @@
label = "fab-snoc";
qcom,fab-dev;
qcom,base-name = "snoc-base";
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
qcom,qos-off = <4096>;
qcom,base-offset = <24576>;
@@ -146,7 +126,6 @@
label = "fab-mnoc-ahb";
qcom,fab-dev;
qcom,base-name = "mmnoc-ahb-base";
- qcom,bypass-qos-prg;
qcom,setrate-only-clk;
qcom,bus-type = <1>;
clock-names = "bus_clk", "bus_a_clk";
@@ -483,18 +462,6 @@
qcom,bus-dev = <&fab_mnoc>;
qcom,vrail-comp = <50>;
qcom,mas-rpm-id = <ICBID_MASTER_MDP0>;
- clk-mdss-axi-no-rate-supply =
- <&gdsc_mdss>;
- clk-mdss-ahb-no-rate-supply =
- <&gdsc_mdss>;
- qcom,node-qos-clks {
- clock-names =
- "clk-mdss-ahb-no-rate",
- "clk-mdss-axi-no-rate";
- clocks =
- <&clock_mmss MMSS_MDSS_AHB_CLK>,
- <&clock_mmss MMSS_MDSS_AXI_CLK>;
- };
};
mas_mdp_p1: mas-mdp-p1 {
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-qrd.dtsi
index ae8da056d12b..f44d59e021d2 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-qrd.dtsi
@@ -21,7 +21,7 @@
status = "ok";
};
- cam_avdd_gpio_regulator:fixed_regulator@1 {
+ cam_avdd_gpio_regulator:cam_avdd_fixed_regulator {
compatible = "regulator-fixed";
regulator-name = "cam_vadd_gpio_regulator";
regulator-min-microvolt = <2800000>;
@@ -31,17 +31,7 @@
vin-supply = <&pm660l_bob>;
};
- cam_dvdd_gpio_regulator:fixed_regulator@1 {
- compatible = "regulator-fixed";
- regulator-name = "cam_vadd_gpio_regulator";
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- enable-active-high;
- gpio = <&pm660l_gpios 4>;
- vin-supply = <&pm660_s5>;
- };
-
- cam_vaf_gpio_regulator:fixed_regulator@2 {
+ cam_vaf_gpio_regulator:cam_vaf_fixed_regulator {
compatible = "regulator-fixed";
regulator-name = "cam_vaf_gpio_regulator";
regulator-min-microvolt = <2800000>;
@@ -182,11 +172,11 @@
compatible = "qcom,eeprom";
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
- cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
+ cam_vdig-supply = <&pm660_s5>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1750000 0 0>;
- qcom,cam-vreg-max-voltage = <1980000 0 0>;
- qcom,cam-vreg-op-mode = <105000 0 0>;
+ qcom,cam-vreg-min-voltage = <1780000 0 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 0 1350000>;
+ qcom,cam-vreg-op-mode = <105000 0 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -194,12 +184,15 @@
pinctrl-1 = <&cam_sensor_mclk0_suspend
&cam_sensor_rear_suspend>;
gpios = <&tlmm 32 0>,
- <&tlmm 46 0>;
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
- qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
- "CAM_RESET0";
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 1>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET0",
+ "CAM_VDIG";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
@@ -216,11 +209,11 @@
compatible = "qcom,eeprom";
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
- cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
+ cam_vdig-supply = <&pm660_s5>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1750000 0 0>;
- qcom,cam-vreg-max-voltage = <1980000 0 0>;
- qcom,cam-vreg-op-mode = <105000 0 0>;
+ qcom,cam-vreg-min-voltage = <1780000 0 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 0 1350000>;
+ qcom,cam-vreg-op-mode = <105000 0 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -228,15 +221,18 @@
pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 34 0>,
- <&tlmm 48 0>;
+ <&tlmm 48 0>,
+ <&pm660l_gpios 4 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 1>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
- "CAM_RESET1";
+ "CAM_RESET1",
+ "CAM_VDIG";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
status = "ok";
clocks = <&clock_mmss MCLK2_CLK_SRC>,
<&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
@@ -287,18 +283,18 @@
reg = <0x0>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
- qcom,mount-angle = <90>;
+ qcom,mount-angle = <270>;
qcom,led-flash-src = <&led_flash0>;
qcom,actuator-src = <&actuator0>;
qcom,ois-src = <&ois0>;
qcom,eeprom-src = <&eeprom0>;
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
- cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
+ cam_vdig-supply = <&pm660_s5>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 0 0>;
- qcom,cam-vreg-max-voltage = <1950000 0 0>;
- qcom,cam-vreg-op-mode = <105000 0 0>;
+ qcom,cam-vreg-min-voltage = <1780000 0 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 0 1350000>;
+ qcom,cam-vreg-op-mode = <105000 0 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -306,12 +302,15 @@
pinctrl-1 = <&cam_sensor_mclk0_suspend
&cam_sensor_rear_suspend>;
gpios = <&tlmm 32 0>,
- <&tlmm 46 0>;
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 1>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
- "CAM_RESET0";
+ "CAM_RESET0",
+ "CAM_VDIG";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
@@ -328,16 +327,16 @@
reg = <0x1>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
- qcom,mount-angle = <90>;
+ qcom,mount-angle = <270>;
qcom,actuator-src = <&actuator1>;
qcom,eeprom-src = <&eeprom1>;
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
- cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
+ cam_vdig-supply = <&pm660_s5>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 0 0>;
- qcom,cam-vreg-max-voltage = <1950000 0 0>;
- qcom,cam-vreg-op-mode = <105000 0 0>;
+ qcom,cam-vreg-min-voltage = <1780000 0 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 0 1350000>;
+ qcom,cam-vreg-op-mode = <105000 0 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -345,15 +344,18 @@
pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 34 0>,
- <&tlmm 48 0>;
+ <&tlmm 48 0>,
+ <&pm660l_gpios 4 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 1>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
- "CAM_RESET1";
+ "CAM_RESET1",
+ "CAM_VDIG";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
status = "ok";
clocks = <&clock_mmss MCLK2_CLK_SRC>,
<&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
index 150c759496bf..de2a44640972 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -24,8 +24,9 @@
qcom,csiphy@c824000 {
cell-index = <0>;
compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
- reg = <0xc824000 0x1000>;
- reg-names = "csiphy";
+ reg = <0xc824000 0x1000>,
+ <0xca00120 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
interrupts = <0 78 0>;
interrupt-names = "csiphy";
gdscr-supply = <&gdsc_camss_top>;
@@ -61,8 +62,9 @@
qcom,csiphy@c825000 {
cell-index = <1>;
compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
- reg = <0xc825000 0x1000>;
- reg-names = "csiphy";
+ reg = <0xc825000 0x1000>,
+ <0xca00124 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
interrupts = <0 79 0>;
interrupt-names = "csiphy";
gdscr-supply = <&gdsc_camss_top>;
@@ -98,8 +100,9 @@
qcom,csiphy@c826000 {
cell-index = <2>;
compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
- reg = <0xc826000 0x1000>;
- reg-names = "csiphy";
+ reg = <0xc826000 0x1000>,
+ <0xca00128 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
interrupts = <0 80 0>;
interrupt-names = "csiphy";
gdscr-supply = <&gdsc_camss_top>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
index 729e55ec9d6c..676e970a7e73 100644
--- a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
@@ -109,6 +109,22 @@
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
};
+&dsi_dual_nt35597_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,partial-update-enabled = "single_roi";
+ qcom,panel-roi-alignment = <720 128 720 128 1440 128>;
+};
+
&sdhc_1 {
/* device core power supply */
vdd-supply = <&pm660l_l4>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
index f9915fbf3f58..a5e66f38df3c 100644
--- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
@@ -321,4 +321,98 @@
reg = <0xa8f8000 0x300>;
qcom,reset-ep-after-lpm-resume;
};
+
+ sdhc_1: sdhci@c0c4000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0xc0c4000 0x1000>, <0xc0c5000 0x1000>;
+ reg-names = "hc_mem", "cmdq_mem";
+
+ interrupts = <0 110 0>, <0 112 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <8>;
+ qcom,large-address-bus;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <26 81>;
+ qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+ qcom,pm-qos-cmdq-latency-us = <26 81>, <26 81>;
+ qcom,pm-qos-legacy-latency-us = <26 81>, <26 81>;
+
+ qcom,msm-bus,name = "sdhc1";
+ qcom,msm-bus,num-cases = <9>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+ <78 512 1046 3200>, /* 400 KB/s*/
+ <78 512 52286 160000>, /* 20 MB/s */
+ <78 512 65360 200000>, /* 25 MB/s */
+ <78 512 130718 400000>, /* 50 MB/s */
+ <78 512 130718 400000>, /* 100 MB/s */
+ <78 512 261438 800000>, /* 200 MB/s */
+ <78 512 261438 800000>, /* 400 MB/s */
+ <78 512 1338562 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 400000000 4294967295>;
+
+ clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
+ <&clock_gcc GCC_SDCC1_APPS_CLK>,
+ <&clock_gcc GCC_SDCC1_ICE_CORE_CLK>;
+ clock-names = "iface_clk", "core_clk", "ice_core_clk";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 192000000 384000000>;
+
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,ice-clk-rates = <300000000 150000000>;
+
+ status = "disabled";
+ };
+
+ sdhc_2: sdhci@c084000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0xc084000 0x1000>;
+ reg-names = "hc_mem";
+
+ interrupts = <0 125 0>, <0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <4>;
+ qcom,large-address-bus;
+
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+ <81 512 1046 3200>, /* 400 KB/s */
+ <81 512 52286 160000>, /* 20 MB/s */
+ <81 512 65360 200000>, /* 25 MB/s */
+ <81 512 130718 400000>, /* 50 MB/s */
+ <81 512 261438 800000>, /* 100 MB/s */
+ <81 512 261438 800000>, /* 200 MB/s */
+ <81 512 1338562 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <26 81>;
+ qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+ qcom,pm-qos-legacy-latency-us = <26 81>, <26 81>;
+
+ clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
+ <&clock_gcc GCC_SDCC2_APPS_CLK>;
+ clock-names = "iface_clk", "core_clk";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50",
+ "SDR104";
+
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
index d347f033b12d..1e62a2423e38 100644
--- a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi
@@ -32,21 +32,26 @@
* subsystem is inactive
*/
qcom,active-only;
+ /*
+ * IB votes in MBPS, derived using below formula
+ * IB = (DDR frequency * DDR bus width in Bytes * Dual rate)
+ * Note: IB vote is per DDR channel vote
+ */
qcom,bw-tbl =
< 0 /* off */ >,
- < 762 /* 100 MHz */ >,
- < 1144 /* 150 MHz */ >,
- < 1525 /* 200 MHz */ >,
- < 2288 /* 300 MHz */ >,
- < 3143 /* 412 MHz */ >,
- < 4173 /* 547 MHz */ >,
- < 5195 /* 681 MHz */ >,
- < 5859 /* 768 MHz */ >,
- < 7759 /* 1017 MHz */ >,
- < 9887 /* 1296 MHz */ >,
- < 10327 /* 1353 MHz */ >,
- < 11863 /* 1555 MHz */ >,
- < 13763 /* 1804 MHz */ >;
+ < 381 /* 100 MHz */ >,
+ < 572 /* 150 MHz */ >,
+ < 762 /* 200 MHz */ >,
+ < 1144 /* 300 MHz */ >,
+ < 1571 /* 412 MHz */ >,
+ < 2086 /* 547 MHz */ >,
+ < 2597 /* 681 MHz */ >,
+ < 2929 /* 768 MHz */ >,
+ < 3879 /* 1017 MHz */ >,
+ < 4943 /* 1296 MHz */ >,
+ < 5161 /* 1353 MHz */ >,
+ < 5931 /* 1555 MHz */ >,
+ < 6881 /* 1804 MHz */ >;
};
msm_gpu: qcom,kgsl-3d0@5000000 {
@@ -85,26 +90,27 @@
/* Bus Scale Settings */
qcom,gpubw-dev = <&gpubw>;
qcom,bus-control;
- qcom,bus-width = <16>;
+ /* GPU to BIMC bus width, VBIF data transfer in 1 cycle */
+ qcom,bus-width = <32>;
qcom,msm-bus,name = "grp3d";
qcom,msm-bus,num-cases = <14>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>,
- <26 512 0 800000>, /* 1 bus=100 */
- <26 512 0 1200000>, /* 2 bus=150 */
- <26 512 0 1600000>, /* 3 bus=200 */
- <26 512 0 2400000>, /* 4 bus=300 */
- <26 512 0 3296000>, /* 5 bus=412 */
- <26 512 0 4376000>, /* 6 bus=547 */
- <26 512 0 5448000>, /* 7 bus=681 */
- <26 512 0 6144000>, /* 8 bus=768 */
- <26 512 0 8136000>, /* 9 bus=1017 */
- <26 512 0 10368000>, /* 10 bus=1296 */
- <26 512 0 10824000>, /* 11 bus=1353 */
- <26 512 0 12440000>, /* 12 bus=1555 */
- <26 512 0 14432000>; /* 13 bus=1804 */
+ <26 512 0 400000>, /* 1 bus=100 */
+ <26 512 0 600000>, /* 2 bus=150 */
+ <26 512 0 800000>, /* 3 bus=200 */
+ <26 512 0 1200000>, /* 4 bus=300 */
+ <26 512 0 1648000>, /* 5 bus=412 */
+ <26 512 0 2188000>, /* 6 bus=547 */
+ <26 512 0 2724000>, /* 7 bus=681 */
+ <26 512 0 3072000>, /* 8 bus=768 */
+ <26 512 0 4068000>, /* 9 bus=1017 */
+ <26 512 0 5184000>, /* 10 bus=1296 */
+ <26 512 0 5412000>, /* 11 bus=1353 */
+ <26 512 0 6220000>, /* 12 bus=1555 */
+ <26 512 0 7216000>; /* 13 bus=1804 */
/* GDSC regulator names */
regulator-names = "vddcx", "vdd";
@@ -161,8 +167,8 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
qcom,gpu-freq = <750000000>;
- qcom,bus-freq = <12>;
- qcom,bus-min = <11>;
+ qcom,bus-freq = <13>;
+ qcom,bus-min = <12>;
qcom,bus-max = <13>;
};
@@ -171,7 +177,7 @@
reg = <1>;
qcom,gpu-freq = <700000000>;
qcom,bus-freq = <11>;
- qcom,bus-min = <10>;
+ qcom,bus-min = <11>;
qcom,bus-max = <13>;
};
@@ -179,7 +185,7 @@
qcom,gpu-pwrlevel@2 {
reg = <2>;
qcom,gpu-freq = <647000000>;
- qcom,bus-freq = <10>;
+ qcom,bus-freq = <11>;
qcom,bus-min = <10>;
qcom,bus-max = <12>;
};
@@ -188,9 +194,9 @@
qcom,gpu-pwrlevel@3 {
reg = <3>;
qcom,gpu-freq = <588000000>;
- qcom,bus-freq = <9>;
+ qcom,bus-freq = <10>;
qcom,bus-min = <9>;
- qcom,bus-max = <11>;
+ qcom,bus-max = <12>;
};
/* SVS_L1 */
@@ -198,7 +204,7 @@
reg = <4>;
qcom,gpu-freq = <465000000>;
qcom,bus-freq = <9>;
- qcom,bus-min = <7>;
+ qcom,bus-min = <8>;
qcom,bus-max = <11>;
};
@@ -206,8 +212,8 @@
qcom,gpu-pwrlevel@5 {
reg = <5>;
qcom,gpu-freq = <370000000>;
- qcom,bus-freq = <7>;
- qcom,bus-min = <5>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <6>;
qcom,bus-max = <9>;
};
@@ -225,7 +231,7 @@
reg = <7>;
qcom,gpu-freq = <160000000>;
qcom,bus-freq = <3>;
- qcom,bus-min = <2>;
+ qcom,bus-min = <3>;
qcom,bus-max = <5>;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec-cdp.dts b/arch/arm/boot/dts/qcom/sdm660-internal-codec-cdp.dts
index c5d4504fd97e..6755385313b1 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec-cdp.dts
@@ -24,9 +24,3 @@
qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
-
-&int_codec {
- status = "okay";
- qcom,msm-hs-micbias-type = "internal";
- qcom,msm-micbias2-ext-cap;
-};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec-mtp.dts b/arch/arm/boot/dts/qcom/sdm660-internal-codec-mtp.dts
index 9d5453240ef9..39da13e7565b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec-mtp.dts
@@ -27,5 +27,4 @@
&int_codec {
qcom,model = "sdm660-snd-card-mtp";
- status = "okay";
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-cdp.dts b/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-cdp.dts
index 6990c299d4e2..caf8af514237 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-cdp.dts
@@ -24,9 +24,3 @@
qcom,board-id = <1 1>;
qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
};
-
-&int_codec {
- status = "okay";
- qcom,msm-hs-micbias-type = "internal";
- qcom,msm-micbias2-ext-cap;
-};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-rcm.dts b/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-rcm.dts
index 03b0e029a569..462362211f5b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-rcm.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec-pm660a-rcm.dts
@@ -24,9 +24,3 @@
qcom,board-id = <21 1>;
qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
};
-
-&int_codec {
- status = "okay";
- qcom,msm-hs-micbias-type = "internal";
- qcom,msm-micbias2-ext-cap;
-};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec-rcm.dts b/arch/arm/boot/dts/qcom/sdm660-internal-codec-rcm.dts
index fc79dc9a36ee..8d95f8c422f9 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec-rcm.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec-rcm.dts
@@ -24,9 +24,3 @@
qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
-
-&int_codec {
- status = "okay";
- qcom,msm-hs-micbias-type = "internal";
- qcom,msm-micbias2-ext-cap;
-};
diff --git a/arch/arm/boot/dts/qcom/sdm660-internal-codec.dtsi b/arch/arm/boot/dts/qcom/sdm660-internal-codec.dtsi
index 512918966f6d..5f36e76c910d 100644
--- a/arch/arm/boot/dts/qcom/sdm660-internal-codec.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-internal-codec.dtsi
@@ -70,6 +70,10 @@
status = "disabled";
};
+&int_codec {
+ status = "okay";
+};
+
&pmic_analog_codec {
status = "okay";
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-lpi.dtsi b/arch/arm/boot/dts/qcom/sdm660-lpi.dtsi
index 195128f3ad43..1fcf0993c4b3 100644
--- a/arch/arm/boot/dts/qcom/sdm660-lpi.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-lpi.dtsi
@@ -157,51 +157,55 @@
cdc_dmic12_gpios_active: dmic12_gpios_active {
mux {
- pins = "gpio26", "gpio27";
+ pins = "gpio26", "gpio28";
function = "func1";
};
config {
- pins = "gpio26", "gpio27";
+ pins = "gpio26", "gpio28";
drive-strength = <8>;
+ output-high;
};
};
cdc_dmic12_gpios_sleep: dmic12_gpios_sleep {
mux {
- pins = "gpio26", "gpio27";
+ pins = "gpio26", "gpio28";
function = "func1";
};
config {
- pins = "gpio26", "gpio27";
+ pins = "gpio26", "gpio28";
drive-strength = <2>;
bias-disable;
+ output-low;
};
};
cdc_dmic34_gpios_active: dmic34_gpios_active {
mux {
- pins = "gpio28", "gpio29";
+ pins = "gpio27", "gpio29";
function = "func1";
};
config {
- pins = "gpio28", "gpio29";
+ pins = "gpio27", "gpio29";
drive-strength = <8>;
+ input-enable;
};
};
cdc_dmic34_gpios_sleep: dmic34_gpios_sleep {
mux {
- pins = "gpio28", "gpio29";
+ pins = "gpio27", "gpio29";
function = "func1";
};
config {
- pins = "gpio28", "gpio29";
+ pins = "gpio27", "gpio29";
drive-strength = <2>;
- bias-disable;
+ pull-down;
+ input-enable;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index f4290d1aef0b..a25343981ace 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -18,6 +18,8 @@
#include "dsi-panel-sharp-dualmipi-wqxga-video.dtsi"
#include "dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi"
#include "dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi"
+#include "dsi-panel-nt35597-dualmipi-wqxga-video.dtsi"
+#include "dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -121,3 +123,19 @@
20 12 05 06 03 13 04 a0];
qcom,config-select = <&dsi_nt35597_truly_dsc_cmd_config2>;
};
+
+&dsi_dual_nt35597_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 18 07 08 04 03 04 a0];
+};
+
+&dsi_dual_nt35597_cmd {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 18 07 08 04 03 04 a0];
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
index ec14815a4be6..1e7f5ea6efc5 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -245,6 +245,9 @@
mdss_fb0: qcom,mdss_fb_primary {
cell-index = <0>;
compatible = "qcom,mdss-fb";
+ qcom,cont-splash-memory {
+ linux,contiguous-region = <&cont_splash_mem>;
+ };
};
mdss_fb1: qcom,mdss_fb_wfd {
@@ -367,6 +370,7 @@
"byte_clk_rcg", "pixel_clk_rcg",
"byte_intf_clk";
+ qcom,null-insertion-enabled;
qcom,platform-strength-ctrl = [ff 06
ff 06
ff 06
@@ -407,6 +411,7 @@
"byte_clk_rcg", "pixel_clk_rcg",
"byte_intf_clk";
+ qcom,null-insertion-enabled;
qcom,platform-strength-ctrl = [ff 06
ff 06
ff 06
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index 0c933807cdd8..2c207873aa0b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -1190,29 +1190,83 @@
};
};
- blsp2_uart1_active: blsp2_uart1_active {
- mux {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- function = "blsp_uart5";
+ blsp2_uart1: blsp2_uart1 {
+ blsp2_uart1_tx_active: blsp2_uart1_tx_active {
+ mux {
+ pins = "gpio16";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio16";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- drive-strength = <2>;
- bias-disable;
+ blsp2_uart1_tx_sleep: blsp2_uart1_tx_sleep {
+ mux {
+ pins = "gpio16";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio16";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
- };
- blsp2_uart1_sleep: blsp2_uart1_sleep {
- mux {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- function = "gpio";
+ blsp2_uart1_rxcts_active: blsp2_uart1_rxcts_active {
+ mux {
+ pins = "gpio17", "gpio18";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio17", "gpio18";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- drive-strength = <2>;
- bias-disable;
+ blsp2_uart1_rxcts_sleep: blsp2_uart1_rxcts_sleep {
+ mux {
+ pins = "gpio17", "gpio18";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio17", "gpio18";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
+ };
+
+ blsp2_uart1_rfr_active: blsp2_uart1_rfr_active {
+ mux {
+ pins = "gpio19";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart1_rfr_sleep: blsp2_uart1_rfr_sleep {
+ mux {
+ pins = "gpio19";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio19";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
index c09ab4c50692..57e547085cf9 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
@@ -108,6 +108,18 @@
&soc {
};
+&pm660_gpios {
+ /* GPIO 11 for home key */
+ gpio@ca00 {
+ status = "ok";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+};
+
&pm660l_gpios {
/* GPIO 7 for VOL_UP */
gpio@c600 {
@@ -166,6 +178,16 @@
gpio-key,wakeup;
debounce-interval = <15>;
};
+
+ home {
+ label = "home";
+ gpios = <&pm660_gpios 11 0x1>;
+ linux,input-type = <1>;
+ linux,code = <102>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
};
hbtp {
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index 42db8c60f681..cd87a20e9780 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -343,6 +343,11 @@
size = <0 0x2000000>;
linux,cma-default;
};
+
+ cont_splash_mem: splash_region@9d400000 {
+ reg = <0x0 0x9d400000 0x0 0x02400000>;
+ label = "cont_splash_mem";
+ };
};
bluetooth: bt_wcn3990 {
@@ -436,7 +441,6 @@
interrupt-controller;
#interrupt-cells = <4>;
cell-index = <0>;
- qcom,not-wakeup; /* Needed until Full-boot-chain enabled */
status = "ok";
};
@@ -1011,19 +1015,19 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 100 MHz */ >,
- < 1144 /* 150 MHz */ >,
- < 1525 /* 200 MHz */ >,
- < 2288 /* 300 MHz */ >,
- < 3143 /* 412 MHz */ >,
- < 4173 /* 547 MHz */ >,
- < 5195 /* 681 MHz */ >,
- < 5859 /* 768 MHz */ >,
- < 7759 /* 1017 MHz */ >,
- < 9887 /* 1296 MHz */ >,
- < 10327 /* 1353 MHz */ >,
- < 11863 /* 1555 MHz */ >,
- < 13763 /* 1804 MHz */ >;
+ < 381 /* 100 MHz */ >,
+ < 572 /* 150 MHz */ >,
+ < 762 /* 200 MHz */ >,
+ < 1144 /* 300 MHz */ >,
+ < 1571 /* 412 MHz */ >,
+ < 2086 /* 547 MHz */ >,
+ < 2597 /* 681 MHz */ >,
+ < 2929 /* 768 MHz */ >,
+ < 3879 /* 1017 MHz */ >,
+ < 4943 /* 1296 MHz */ >,
+ < 5163 /* 1353 MHz */ >,
+ < 5931 /* 1555 MHz */ >,
+ < 6881 /* 1804 MHz */ >;
};
bwmon: qcom,cpu-bwmon {
@@ -1042,19 +1046,19 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 100 MHz */ >,
- < 1144 /* 150 MHz */ >,
- < 1525 /* 200 MHz */ >,
- < 2288 /* 300 MHz */ >,
- < 3143 /* 412 MHz */ >,
- < 4173 /* 547 MHz */ >,
- < 5195 /* 681 MHz */ >,
- < 5859 /* 768 MHz */ >,
- < 7759 /* 1017 MHz */ >,
- < 9887 /* 1296 MHz */ >,
- < 10327 /* 1353 MHz */ >,
- < 11863 /* 1555 MHz */ >,
- < 13763 /* 1804 MHz */ >;
+ < 381 /* 100 MHz */ >,
+ < 572 /* 150 MHz */ >,
+ < 762 /* 200 MHz */ >,
+ < 1144 /* 300 MHz */ >,
+ < 1571 /* 412 MHz */ >,
+ < 2086 /* 547 MHz */ >,
+ < 2597 /* 681 MHz */ >,
+ < 2929 /* 768 MHz */ >,
+ < 3879 /* 1017 MHz */ >,
+ < 4943 /* 1296 MHz */ >,
+ < 5163 /* 1353 MHz */ >,
+ < 5931 /* 1555 MHz */ >,
+ < 6881 /* 1804 MHz */ >;
};
memlat_cpu0: qcom,memlat-cpu0 {
@@ -1063,19 +1067,19 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 100 MHz */ >,
- < 1144 /* 150 MHz */ >,
- < 1525 /* 200 MHz */ >,
- < 2288 /* 300 MHz */ >,
- < 3143 /* 412 MHz */ >,
- < 4173 /* 547 MHz */ >,
- < 5195 /* 681 MHz */ >,
- < 5859 /* 768 MHz */ >,
- < 7759 /* 1017 MHz */ >,
- < 9887 /* 1296 MHz */ >,
- < 10327 /* 1353 MHz */ >,
- < 11863 /* 1555 MHz */ >,
- < 13763 /* 1804 MHz */ >;
+ < 381 /* 100 MHz */ >,
+ < 572 /* 150 MHz */ >,
+ < 762 /* 200 MHz */ >,
+ < 1144 /* 300 MHz */ >,
+ < 1571 /* 412 MHz */ >,
+ < 2086 /* 547 MHz */ >,
+ < 2597 /* 681 MHz */ >,
+ < 2929 /* 768 MHz */ >,
+ < 3879 /* 1017 MHz */ >,
+ < 4943 /* 1296 MHz */ >,
+ < 5163 /* 1353 MHz */ >,
+ < 5931 /* 1555 MHz */ >,
+ < 6881 /* 1804 MHz */ >;
};
memlat_cpu4: qcom,memlat-cpu4 {
@@ -1084,19 +1088,19 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 100 MHz */ >,
- < 1144 /* 150 MHz */ >,
- < 1525 /* 200 MHz */ >,
- < 2288 /* 300 MHz */ >,
- < 3143 /* 412 MHz */ >,
- < 4173 /* 547 MHz */ >,
- < 5195 /* 681 MHz */ >,
- < 5859 /* 768 MHz */ >,
- < 7759 /* 1017 MHz */ >,
- < 9887 /* 1296 MHz */ >,
- < 10327 /* 1353 MHz */ >,
- < 11863 /* 1555 MHz */ >,
- < 13763 /* 1804 MHz */ >;
+ < 381 /* 100 MHz */ >,
+ < 572 /* 150 MHz */ >,
+ < 762 /* 200 MHz */ >,
+ < 1144 /* 300 MHz */ >,
+ < 1571 /* 412 MHz */ >,
+ < 2086 /* 547 MHz */ >,
+ < 2597 /* 681 MHz */ >,
+ < 2929 /* 768 MHz */ >,
+ < 3879 /* 1017 MHz */ >,
+ < 4943 /* 1296 MHz */ >,
+ < 5163 /* 1353 MHz */ >,
+ < 5931 /* 1555 MHz */ >,
+ < 6881 /* 1804 MHz */ >;
};
devfreq_memlat_0: qcom,arm-memlat-mon-0 {
@@ -1104,9 +1108,9 @@
qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
qcom,target-dev = <&memlat_cpu0>;
qcom,core-dev-table =
- < 633600 1525 >,
- < 1401600 4173 >,
- < 1881600 7759 >;
+ < 633600 762 >,
+ < 1401600 2086 >,
+ < 1881600 3879 >;
};
devfreq_memlat_4: qcom,arm-memlat-mon-4 {
@@ -1114,25 +1118,25 @@
qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
qcom,target-dev = <&memlat_cpu4>;
qcom,core-dev-table =
- < 1113600 1525 >,
- < 1401600 7759 >,
- < 2150400 11863 >,
- < 2457600 13763 >;
+ < 1113600 762 >,
+ < 1401600 3879 >,
+ < 2150400 5931 >,
+ < 2457600 6881 >;
};
devfreq_cpufreq: devfreq-cpufreq {
mincpubw-cpufreq {
target-dev = <&mincpubw>;
cpu-to-dev-map-0 =
- < 633600 1525 >,
- < 1401600 3143 >,
- < 1881600 5859 >;
+ < 633600 762 >,
+ < 1401600 1571 >,
+ < 1881600 2929 >;
cpu-to-dev-map-4 =
- < 1113600 1525 >,
- < 1401600 4173 >,
- < 1747200 5859 >,
- < 2150400 7759 >,
- < 2457600 13763 >;
+ < 1113600 762 >,
+ < 1401600 2086 >,
+ < 1747200 2929 >,
+ < 2150400 3879 >,
+ < 2457600 6881 >;
};
};
@@ -1276,8 +1280,10 @@
100000000 200000000 400000000 4294967295>;
clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
- <&clock_gcc GCC_SDCC1_APPS_CLK>;
- clock-names = "iface_clk", "core_clk";
+ <&clock_gcc GCC_SDCC1_APPS_CLK>,
+ <&clock_gcc GCC_SDCC1_ICE_CORE_CLK>;
+ clock-names = "iface_clk", "core_clk", "ice_core_clk";
+ qcom,ice-clk-rates = <300000000 150000000>;
status = "disabled";
};
@@ -1406,6 +1412,10 @@
qcom,mpu-enabled;
};
+ qcom,msm-cdsp-loader {
+ compatible = "qcom,cdsp-loader";
+ qcom,proc-img-to-load = "cdsp";
+ };
qcom,msm-adsprpc-mem {
compatible = "qcom,msm-adsprpc-mem-region";
diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig
index fec429d7bd0c..2cfe647855c3 100644
--- a/arch/arm/configs/msmcortex_defconfig
+++ b/arch/arm/configs/msmcortex_defconfig
@@ -293,12 +293,13 @@ CONFIG_PINCTRL_SDM660=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_SUPPLY=y
-CONFIG_QPNP_FG_GEN3=y
+CONFIG_QPNP_SMBCHARGER=y
+CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1351_USB_CHARGER=y
CONFIG_MSM_BCL_CTL=y
CONFIG_MSM_BCL_PERIPHERAL_CTL=y
CONFIG_QPNP_SMB2=y
CONFIG_SMB138X_CHARGER=y
-CONFIG_QPNP_QNOVO=y
CONFIG_APSS_CORE_EA=y
CONFIG_MSM_APM=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
@@ -477,7 +478,6 @@ CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_QCOM_RRADC=y
-CONFIG_QCOM_TADC=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig
index a2584f6831e2..b8df922b52fc 100644
--- a/arch/arm/configs/sdm660-perf_defconfig
+++ b/arch/arm/configs/sdm660-perf_defconfig
@@ -362,6 +362,7 @@ CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
@@ -372,6 +373,8 @@ CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
CONFIG_MSM_CAMERA_DEBUG=y
CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
@@ -582,8 +585,6 @@ CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_PAGE_EXTENSION=y
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
# CONFIG_SCHED_DEBUG is not set
CONFIG_PANIC_ON_SCHED_BUG=y
diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig
index 7ba3f7b4362f..fd5340a45aa2 100644
--- a/arch/arm/configs/sdm660_defconfig
+++ b/arch/arm/configs/sdm660_defconfig
@@ -361,6 +361,7 @@ CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
@@ -374,6 +375,8 @@ CONFIG_MSM_VIDC_V4L2=m
CONFIG_MSM_VIDC_GOVERNORS=m
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index df5ce357294c..27b445e30a49 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -360,6 +360,7 @@ CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
@@ -400,6 +401,8 @@ CONFIG_MSM_VIDC_VMEM=y
CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
@@ -546,6 +549,7 @@ CONFIG_ICNSS=y
CONFIG_MSM_RUN_QUEUE_STATS=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL=y
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index c959f1864256..9dac8be9d37d 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -8,7 +8,6 @@ CONFIG_RCU_EXPERT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
-CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
@@ -16,7 +15,6 @@ CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_SCHEDTUNE=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
-CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_HMP=y
CONFIG_SCHED_HMP_CSTATE_AWARE=y
@@ -24,6 +22,7 @@ CONFIG_SCHED_CORE_CTL=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
CONFIG_SCHED_TUNE=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_XZ is not set
@@ -362,6 +361,7 @@ CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
@@ -402,6 +402,8 @@ CONFIG_MSM_VIDC_VMEM=y
CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
@@ -467,6 +469,7 @@ CONFIG_USB_CONFIGFS_F_CDEV=y
CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_RING_BUFFER=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_CLKGATE=y
CONFIG_MMC_BLOCK_MINORS=32
@@ -565,6 +568,7 @@ CONFIG_MSM_RUN_QUEUE_STATS=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_CPUSS_DUMP=y
CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL=y
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 9bcc0ad84917..cab1821db191 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -104,6 +104,7 @@
str x20, [sp, #S_ORIG_ADDR_LIMIT]
mov x20, #TASK_SIZE_64
str x20, [tsk, #TI_ADDR_LIMIT]
+ ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO)
.endif /* \el == 0 */
mrs x22, elr_el1
mrs x23, spsr_el1
@@ -139,6 +140,8 @@
/* Restore the task's original addr_limit. */
ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
str x20, [tsk, #TI_ADDR_LIMIT]
+
+ /* No need to restore UAO, it will be restored from SPSR_EL1 */
.endif
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 68cd3bb8eb89..eacaee18645b 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -291,7 +291,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
}
if (permission_fault(esr) && (addr < USER_DS)) {
- if (get_fs() == KERNEL_DS)
+ /* regs->orig_addr_limit may be 0 if we entered from EL0 */
+ if (regs->orig_addr_limit == KERNEL_DS)
die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
if (!search_exception_tables(regs->pc))
diff --git a/block/Kconfig b/block/Kconfig
index 161491d0a879..39e956942b9d 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -33,7 +33,7 @@ config LBDAF
This option is required to support the full capacity of large
(2TB+) block devices, including RAID, disk, Network Block Device,
Logical Volume Manager (LVM) and loopback.
-
+
This option also enables support for single files larger than
2TB.
@@ -111,6 +111,13 @@ config BLK_CMDLINE_PARSER
See Documentation/block/cmdline-partition.txt for more information.
+config BLOCK_PERF_FRAMEWORK
+ bool "Enable Block device performance measurement framework"
+ default n
+ ---help---
+ Enabling this option allows you to measure the performance at the
+ block layer.
+
menu "Partition Types"
source "block/partitions/Kconfig"
diff --git a/block/bio.c b/block/bio.c
index b9829b6504c8..02c4d9bf1590 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -31,6 +31,8 @@
#include <trace/events/block.h>
+#include "blk.h"
+
/*
* Test patch to inline a certain number of bi_io_vec's inside the bio
* itself, to shrink a bio data allocation from two mempool calls to one
@@ -1765,8 +1767,10 @@ void bio_endio(struct bio *bio)
bio_put(bio);
bio = parent;
} else {
- if (bio->bi_end_io)
+ if (bio->bi_end_io) {
+ blk_update_perf_stats(bio);
bio->bi_end_io(bio);
+ }
bio = NULL;
}
}
diff --git a/block/blk-core.c b/block/blk-core.c
index 450da06fa27e..4162327d8804 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -11,6 +11,12 @@
/*
* This handles all read/write requests to block devices
*/
+
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+#define DRIVER_NAME "Block"
+#define pr_fmt(fmt) DRIVER_NAME ": %s: " fmt, __func__
+#endif
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/backing-dev.h>
@@ -34,6 +40,12 @@
#include <linux/pm_runtime.h>
#include <linux/blk-cgroup.h>
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+#include <linux/ktime.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#endif
+
#define CREATE_TRACE_POINTS
#include <trace/events/block.h>
@@ -2111,6 +2123,456 @@ static inline struct task_struct *get_dirty_task(struct bio *bio)
}
#endif
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+#define BLK_PERF_SIZE (1024 * 15)
+#define BLK_PERF_HIST_SIZE (sizeof(u32) * BLK_PERF_SIZE)
+
+struct blk_perf_stats {
+ u32 *read_hist;
+ u32 *write_hist;
+ u32 *flush_hist;
+ int buffers_alloced;
+ ktime_t max_read_time;
+ ktime_t max_write_time;
+ ktime_t max_flush_time;
+ ktime_t min_write_time;
+ ktime_t min_read_time;
+ ktime_t min_flush_time;
+ ktime_t total_write_time;
+ ktime_t total_read_time;
+ u64 total_read_size;
+ u64 total_write_size;
+ spinlock_t lock;
+ int is_enabled;
+};
+
+static struct blk_perf_stats blk_perf;
+static struct dentry *blk_perf_debug_dir;
+
+static int alloc_histogram_buffers(void)
+{
+ int ret = 0;
+
+ if (!blk_perf.read_hist)
+ blk_perf.read_hist = kzalloc(BLK_PERF_HIST_SIZE, GFP_KERNEL);
+
+ if (!blk_perf.write_hist)
+ blk_perf.write_hist = kzalloc(BLK_PERF_HIST_SIZE, GFP_KERNEL);
+
+ if (!blk_perf.flush_hist)
+ blk_perf.flush_hist = kzalloc(BLK_PERF_HIST_SIZE, GFP_KERNEL);
+
+ if (!blk_perf.read_hist || !blk_perf.write_hist || !blk_perf.flush_hist)
+ ret = -ENOMEM;
+
+ if (!ret)
+ blk_perf.buffers_alloced = 1;
+ return ret;
+}
+
+static void clear_histogram_buffers(void)
+{
+ if (!blk_perf.buffers_alloced)
+ return;
+ memset(blk_perf.read_hist, 0, BLK_PERF_HIST_SIZE);
+ memset(blk_perf.write_hist, 0, BLK_PERF_HIST_SIZE);
+ memset(blk_perf.flush_hist, 0, BLK_PERF_HIST_SIZE);
+}
+
+static int enable_perf(void *data, u64 val)
+{
+ int ret;
+
+ if (!blk_perf.buffers_alloced)
+ ret = alloc_histogram_buffers();
+
+ if (ret)
+ return ret;
+
+ spin_lock(&blk_perf.lock);
+ blk_perf.is_enabled = val;
+ spin_unlock(&blk_perf.lock);
+ return 0;
+}
+
+static int is_perf_enabled(void *data, u64 *val)
+{
+ spin_lock(&blk_perf.lock);
+ *val = blk_perf.is_enabled;
+ spin_unlock(&blk_perf.lock);
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(enable_perf_fops, is_perf_enabled, enable_perf,
+ "%llu\n");
+
+static char *blk_debug_buffer;
+static u32 blk_debug_data_size;
+static DEFINE_MUTEX(blk_perf_debug_buffer_mutex);
+
+static ssize_t blk_perf_read(struct file *file, char __user *buf,
+ size_t count, loff_t *file_pos)
+{
+ ssize_t ret = 0;
+
+ mutex_lock(&blk_perf_debug_buffer_mutex);
+ ret = simple_read_from_buffer(buf, count, file_pos, blk_debug_buffer,
+ blk_debug_data_size);
+ mutex_unlock(&blk_perf_debug_buffer_mutex);
+
+ return ret;
+}
+
+static int blk_debug_buffer_alloc(u32 buffer_size)
+{
+ int ret = 0;
+
+ mutex_lock(&blk_perf_debug_buffer_mutex);
+ if (blk_debug_buffer != NULL) {
+ pr_err("blk_debug_buffer is in use\n");
+ ret = -EBUSY;
+ goto end;
+ }
+ blk_debug_buffer = kzalloc(buffer_size, GFP_KERNEL);
+ if (!blk_debug_buffer)
+ ret = -ENOMEM;
+end:
+ mutex_unlock(&blk_perf_debug_buffer_mutex);
+ return ret;
+}
+
+static int blk_perf_close(struct inode *inode, struct file *file)
+{
+ mutex_lock(&blk_perf_debug_buffer_mutex);
+ blk_debug_data_size = 0;
+ kfree(blk_debug_buffer);
+ blk_debug_buffer = NULL;
+ mutex_unlock(&blk_perf_debug_buffer_mutex);
+ return 0;
+}
+
+static u32 fill_basic_perf_info(char *buffer, u32 buffer_size)
+{
+ u32 size = 0;
+
+ size += scnprintf(buffer + size, buffer_size - size, "\n");
+
+ spin_lock(&blk_perf.lock);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "max_read_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.max_read_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "min_read_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.min_read_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "total_read_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.total_read_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "total_read_size: %llu\n\n",
+ blk_perf.total_read_size);
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "max_write_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.max_write_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "min_write_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.min_write_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "total_write_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.total_write_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "total_write_size: %llu\n\n",
+ blk_perf.total_write_size);
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "max_flush_time_ms: %llu\n",
+ ktime_to_ms(blk_perf.max_flush_time));
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "min_flush_time_ms: %llu\n\n",
+ ktime_to_ms(blk_perf.min_flush_time));
+
+ spin_unlock(&blk_perf.lock);
+
+ return size;
+}
+
+static int basic_perf_open(struct inode *inode, struct file *file)
+{
+ u32 buffer_size;
+ int ret;
+
+ buffer_size = BLK_PERF_HIST_SIZE;
+ ret = blk_debug_buffer_alloc(buffer_size);
+ if (ret)
+ return ret;
+
+ mutex_lock(&blk_perf_debug_buffer_mutex);
+ blk_debug_data_size = fill_basic_perf_info(blk_debug_buffer,
+ buffer_size);
+ mutex_unlock(&blk_perf_debug_buffer_mutex);
+ return 0;
+}
+
+
+static const struct file_operations basic_perf_ops = {
+ .read = blk_perf_read,
+ .release = blk_perf_close,
+ .open = basic_perf_open,
+};
+
+static int hist_open_helper(void *hist_buf)
+{
+ int ret;
+
+ if (!blk_perf.buffers_alloced)
+ return -EINVAL;
+
+ ret = blk_debug_buffer_alloc(BLK_PERF_HIST_SIZE);
+ if (ret)
+ return ret;
+
+ spin_lock(&blk_perf.lock);
+ memcpy(blk_debug_buffer, hist_buf, BLK_PERF_HIST_SIZE);
+ spin_unlock(&blk_perf.lock);
+
+ mutex_lock(&blk_perf_debug_buffer_mutex);
+ blk_debug_data_size = BLK_PERF_HIST_SIZE;
+ mutex_unlock(&blk_perf_debug_buffer_mutex);
+ return 0;
+}
+
+static int write_hist_open(struct inode *inode, struct file *file)
+{
+ return hist_open_helper(blk_perf.write_hist);
+}
+
+static const struct file_operations write_hist_ops = {
+ .read = blk_perf_read,
+ .release = blk_perf_close,
+ .open = write_hist_open,
+};
+
+
+static int read_hist_open(struct inode *inode, struct file *file)
+{
+ return hist_open_helper(blk_perf.read_hist);
+}
+
+static const struct file_operations read_hist_ops = {
+ .read = blk_perf_read,
+ .release = blk_perf_close,
+ .open = read_hist_open,
+};
+
+static int flush_hist_open(struct inode *inode, struct file *file)
+{
+ return hist_open_helper(blk_perf.flush_hist);
+}
+
+static const struct file_operations flush_hist_ops = {
+ .read = blk_perf_read,
+ .release = blk_perf_close,
+ .open = flush_hist_open,
+};
+
+static void clear_perf_stats_helper(void)
+{
+ spin_lock(&blk_perf.lock);
+ blk_perf.max_write_time = ktime_set(0, 0);
+ blk_perf.max_read_time = ktime_set(0, 0);
+ blk_perf.max_flush_time = ktime_set(0, 0);
+ blk_perf.min_write_time = ktime_set(KTIME_MAX, 0);
+ blk_perf.min_read_time = ktime_set(KTIME_MAX, 0);
+ blk_perf.min_flush_time = ktime_set(KTIME_MAX, 0);
+ blk_perf.total_write_time = ktime_set(0, 0);
+ blk_perf.total_read_time = ktime_set(0, 0);
+ blk_perf.total_read_size = 0;
+ blk_perf.total_write_size = 0;
+ blk_perf.is_enabled = 0;
+ clear_histogram_buffers();
+ spin_unlock(&blk_perf.lock);
+}
+
+static int clear_perf_stats(void *data, u64 val)
+{
+ clear_perf_stats_helper();
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clear_perf_stats_fops, NULL, clear_perf_stats,
+ "%llu\n");
+
+static void blk_debugfs_init(void)
+{
+ struct dentry *f_ent;
+
+ blk_perf_debug_dir = debugfs_create_dir("block_perf", NULL);
+ if (IS_ERR(blk_perf_debug_dir)) {
+ pr_err("Failed to create block_perf debug_fs directory\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("basic_perf", 0400, blk_perf_debug_dir,
+ NULL, &basic_perf_ops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs basic_perf file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("write_hist", 0400, blk_perf_debug_dir,
+ NULL, &write_hist_ops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs write_hist file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("read_hist", 0400, blk_perf_debug_dir,
+ NULL, &read_hist_ops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs read_hist file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("flush_hist", 0400, blk_perf_debug_dir,
+ NULL, &flush_hist_ops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs flush_hist file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("enable_perf", 0600, blk_perf_debug_dir,
+ NULL, &enable_perf_fops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs enable_perf file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("clear_perf_stats", 0200,
+ blk_perf_debug_dir, NULL,
+ &clear_perf_stats_fops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs clear_perf_stats file\n");
+ return;
+ }
+}
+
+static void blk_init_perf(void)
+{
+ blk_debugfs_init();
+ spin_lock_init(&blk_perf.lock);
+
+ clear_perf_stats_helper();
+}
+
+
+static void set_submit_info(struct bio *bio, unsigned int count)
+{
+ ktime_t submit_time;
+
+ if (unlikely(blk_perf.is_enabled)) {
+ submit_time = ktime_get();
+ bio->submit_time.tv64 = submit_time.tv64;
+ bio->blk_sector_count = count;
+ return;
+ }
+
+ bio->submit_time.tv64 = 0;
+ bio->blk_sector_count = 0;
+}
+
+void blk_update_perf_read_write_stats(ktime_t bio_process_time, int is_write,
+ int count)
+{
+ u32 bio_process_time_ms;
+
+ bio_process_time_ms = ktime_to_ms(bio_process_time);
+ if (bio_process_time_ms >= BLK_PERF_SIZE)
+ bio_process_time_ms = BLK_PERF_SIZE - 1;
+
+ if (is_write) {
+ if (ktime_after(bio_process_time, blk_perf.max_write_time))
+ blk_perf.max_write_time = bio_process_time;
+
+ if (ktime_before(bio_process_time, blk_perf.min_write_time))
+ blk_perf.min_write_time = bio_process_time;
+ blk_perf.total_write_time =
+ ktime_add(blk_perf.total_write_time, bio_process_time);
+ blk_perf.total_write_size += count;
+ blk_perf.write_hist[bio_process_time_ms] += count;
+
+ } else {
+ if (ktime_after(bio_process_time, blk_perf.max_read_time))
+ blk_perf.max_read_time = bio_process_time;
+
+ if (ktime_before(bio_process_time, blk_perf.min_read_time))
+ blk_perf.min_read_time = bio_process_time;
+ blk_perf.total_read_time =
+ ktime_add(blk_perf.total_read_time, bio_process_time);
+ blk_perf.total_read_size += count;
+ blk_perf.read_hist[bio_process_time_ms] += count;
+ }
+}
+void blk_update_perf_stats(struct bio *bio)
+{
+ ktime_t bio_process_time;
+ u32 bio_process_time_ms;
+ u32 count;
+
+ spin_lock(&blk_perf.lock);
+ if (likely(!blk_perf.is_enabled))
+ goto end;
+ if (!bio->submit_time.tv64)
+ goto end;
+ bio_process_time = ktime_sub(ktime_get(), bio->submit_time);
+
+ count = bio->blk_sector_count;
+
+ if (count) {
+ int is_write = 0;
+
+ if (bio->bi_rw & WRITE ||
+ unlikely(bio->bi_rw & REQ_WRITE_SAME))
+ is_write = 1;
+
+ blk_update_perf_read_write_stats(bio_process_time, is_write,
+ count);
+ } else {
+
+ bio_process_time_ms = ktime_to_ms(bio_process_time);
+ if (bio_process_time_ms >= BLK_PERF_SIZE)
+ bio_process_time_ms = BLK_PERF_SIZE - 1;
+
+ if (ktime_after(bio_process_time, blk_perf.max_flush_time))
+ blk_perf.max_flush_time = bio_process_time;
+
+ if (ktime_before(bio_process_time, blk_perf.min_flush_time))
+ blk_perf.min_flush_time = bio_process_time;
+
+ blk_perf.flush_hist[bio_process_time_ms] += 1;
+ }
+end:
+ spin_unlock(&blk_perf.lock);
+
+}
+#else
+static inline void set_submit_info(struct bio *bio, unsigned int count)
+{
+ (void) bio;
+ (void) count;
+}
+
+static inline void blk_init_perf(void)
+{
+}
+#endif /* #ifdef CONFIG_BLOCK_PERF_FRAMEWORK */
+
/**
* submit_bio - submit a bio to the block device layer for I/O
* @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
@@ -2123,6 +2585,7 @@ static inline struct task_struct *get_dirty_task(struct bio *bio)
*/
blk_qc_t submit_bio(int rw, struct bio *bio)
{
+ unsigned int count = 0;
bio->bi_rw |= rw;
/*
@@ -2130,8 +2593,6 @@ blk_qc_t submit_bio(int rw, struct bio *bio)
* go through the normal accounting stuff before submission.
*/
if (bio_has_data(bio)) {
- unsigned int count;
-
if (unlikely(rw & REQ_WRITE_SAME))
count = bdev_logical_block_size(bio->bi_bdev) >> 9;
else
@@ -2158,6 +2619,7 @@ blk_qc_t submit_bio(int rw, struct bio *bio)
}
}
+ set_submit_info(bio, count);
return generic_make_request(bio);
}
EXPORT_SYMBOL(submit_bio);
@@ -3578,7 +4040,7 @@ int __init blk_dev_init(void)
blk_requestq_cachep = kmem_cache_create("blkdev_queue",
sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
-
+ blk_init_perf();
return 0;
}
diff --git a/block/blk.h b/block/blk.h
index ce2287639ab3..6ceebbd61afd 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -112,6 +112,15 @@ void blk_account_io_start(struct request *req, bool new_io);
void blk_account_io_completion(struct request *req, unsigned int bytes);
void blk_account_io_done(struct request *req);
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+void blk_update_perf_stats(struct bio *bio);
+#else
+static inline void blk_update_perf_stats(struct bio *bio)
+{
+ (void) bio;
+}
+#endif
+
/*
* Internal atomic flags for request handling
*/
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 8e3bff9c7fe9..ebbe31fee7ae 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -607,7 +607,7 @@ source "drivers/char/xillybus/Kconfig"
config MSM_ADSPRPC
tristate "QTI ADSP RPC driver"
- depends on MSM_SMD
+ depends on MSM_GLINK
help
Provides a communication mechanism that allows for clients to
make remote method invocations across processor boundary to
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 03429b18825b..95dca75efde9 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -25,7 +25,6 @@
#include <linux/hash.h>
#include <linux/msm_ion.h>
#include <soc/qcom/secure_buffer.h>
-#include <soc/qcom/smd.h>
#include <soc/qcom/glink.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
@@ -48,6 +47,7 @@
#include "adsprpc_compat.h"
#include "adsprpc_shared.h"
#include <soc/qcom/ramdump.h>
+#include <linux/debugfs.h>
#define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
#define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
@@ -55,6 +55,7 @@
#define ADSP_MMAP_HEAP_ADDR 4
#define FASTRPC_ENOSUCH 39
#define VMID_SSC_Q6 5
+#define DEBUGFS_SIZE 1024
#define RPC_TIMEOUT (5 * HZ)
#define BALIGN 128
@@ -90,6 +91,8 @@
static int fastrpc_glink_open(int cid);
static void fastrpc_glink_close(void *chan, int cid);
+static struct dentry *debugfs_root;
+static struct dentry *debugfs_global_file;
static inline uint64_t buf_page_start(uint64_t buf)
{
@@ -207,7 +210,6 @@ struct fastrpc_channel_ctx {
struct completion work;
struct notifier_block nb;
struct kref kref;
- int channel;
int sesscount;
int ssrcount;
void *handle;
@@ -231,7 +233,6 @@ struct fastrpc_apps {
spinlock_t hlock;
struct ion_client *client;
struct device *dev;
- bool glink;
};
struct fastrpc_mmap {
@@ -283,6 +284,7 @@ struct fastrpc_file {
int pd;
struct fastrpc_apps *apps;
struct fastrpc_perf perf;
+ struct dentry *debugfs_file;
};
static struct fastrpc_apps gfa;
@@ -291,21 +293,18 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
{
.name = "adsprpc-smd",
.subsys = "adsp",
- .channel = SMD_APPS_QDSP,
.link.link_info.edge = "lpass",
.link.link_info.transport = "smem",
},
{
.name = "mdsprpc-smd",
.subsys = "modem",
- .channel = SMD_APPS_MODEM,
.link.link_info.edge = "mpss",
.link.link_info.transport = "smem",
},
{
.name = "sdsprpc-smd",
.subsys = "slpi",
- .channel = SMD_APPS_DSPS,
.link.link_info.edge = "dsps",
.link.link_info.transport = "smem",
.vmid = VMID_SSC_Q6,
@@ -1348,7 +1347,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
struct smq_msg *msg = &ctx->msg;
struct fastrpc_file *fl = ctx->fl;
struct fastrpc_channel_ctx *channel_ctx = &fl->apps->channel[fl->cid];
- int err = 0, len;
+ int err = 0;
VERIFY(err, 0 != channel_ctx->chan);
if (err)
@@ -1363,64 +1362,21 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0;
msg->invoke.page.size = buf_page_size(ctx->used);
- if (fl->apps->glink) {
- if (fl->ssrcount != channel_ctx->ssrcount) {
- err = -ECONNRESET;
- goto bail;
- }
- VERIFY(err, channel_ctx->link.port_state ==
- FASTRPC_LINK_CONNECTED);
- if (err)
- goto bail;
- err = glink_tx(channel_ctx->chan,
- (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg),
- GLINK_TX_REQ_INTENT);
- } else {
- spin_lock(&fl->apps->hlock);
- len = smd_write((smd_channel_t *)
- channel_ctx->chan,
- msg, sizeof(*msg));
- spin_unlock(&fl->apps->hlock);
- VERIFY(err, len == sizeof(*msg));
+ if (fl->ssrcount != channel_ctx->ssrcount) {
+ err = -ECONNRESET;
+ goto bail;
}
+ VERIFY(err, channel_ctx->link.port_state ==
+ FASTRPC_LINK_CONNECTED);
+ if (err)
+ goto bail;
+ err = glink_tx(channel_ctx->chan,
+ (void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg),
+ GLINK_TX_REQ_INTENT);
bail:
return err;
}
-static void fastrpc_smd_read_handler(int cid)
-{
- struct fastrpc_apps *me = &gfa;
- struct smq_invoke_rsp rsp = {0};
- int ret = 0;
-
- do {
- ret = smd_read_from_cb(me->channel[cid].chan, &rsp,
- sizeof(rsp));
- if (ret != sizeof(rsp))
- break;
- rsp.ctx = rsp.ctx & ~1;
- context_notify_user(uint64_to_ptr(rsp.ctx), rsp.retval);
- } while (ret == sizeof(rsp));
-}
-
-static void smd_event_handler(void *priv, unsigned event)
-{
- struct fastrpc_apps *me = &gfa;
- int cid = (int)(uintptr_t)priv;
-
- switch (event) {
- case SMD_EVENT_OPEN:
- complete(&me->channel[cid].work);
- break;
- case SMD_EVENT_CLOSE:
- fastrpc_notify_drivers(me, cid);
- break;
- case SMD_EVENT_DATA:
- fastrpc_smd_read_handler(cid);
- break;
- }
-}
-
static void fastrpc_init(struct fastrpc_apps *me)
{
int i;
@@ -1883,11 +1839,7 @@ static void fastrpc_channel_close(struct kref *kref)
ctx = container_of(kref, struct fastrpc_channel_ctx, kref);
cid = ctx - &gcinfo[0];
- if (!me->glink) {
- smd_close(ctx->chan);
- } else {
- fastrpc_glink_close(ctx->chan, cid);
- }
+ fastrpc_glink_close(ctx->chan, cid);
ctx->chan = 0;
mutex_unlock(&me->smd_mutex);
pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
@@ -2042,6 +1994,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
if (fl) {
+ if (fl->debugfs_file != NULL)
+ debugfs_remove(fl->debugfs_file);
fastrpc_file_free(fl);
file->private_data = 0;
}
@@ -2158,9 +2112,124 @@ bail:
return err;
}
+static int fastrpc_debugfs_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *position)
+{
+ struct fastrpc_file *fl = filp->private_data;
+ struct hlist_node *n;
+ struct fastrpc_buf *buf = 0;
+ struct fastrpc_mmap *map = 0;
+ struct smq_invoke_ctx *ictx = 0;
+ struct fastrpc_channel_ctx *chan;
+ struct fastrpc_session_ctx *sess;
+ unsigned int len = 0;
+ int i, j, ret = 0;
+ char *fileinfo = NULL;
+
+ fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL);
+ if (!fileinfo)
+ goto bail;
+ if (fl == NULL) {
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ chan = &gcinfo[i];
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "%s\n\n",
+ chan->name);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "%s %d\n",
+ "sesscount:", chan->sesscount);
+ for (j = 0; j < chan->sesscount; j++) {
+ sess = &chan->session[j];
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len,
+ "%s%d\n\n", "SESSION", j);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len,
+ "%s %d\n", "sid:",
+ sess->smmu.cb);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len,
+ "%s %d\n", "SECURE:",
+ sess->smmu.secure);
+ }
+ }
+ } else {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %d\n\n",
+ "PROCESS_ID:", fl->tgid);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %d\n\n",
+ "CHANNEL_ID:", fl->cid);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %d\n\n",
+ "SSRCOUNT:", fl->ssrcount);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s\n",
+ "LIST OF BUFS:");
+ spin_lock(&fl->hlock);
+ hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %p %s %p %s %llx\n", "buf:",
+ buf, "buf->virt:", buf->virt,
+ "buf->phys:", buf->phys);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s\n",
+ "LIST OF MAPS:");
+ hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %p %s %lx %s %llx\n",
+ "map:", map,
+ "map->va:", map->va,
+ "map->phys:", map->phys);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s\n",
+ "LIST OF PENDING SMQCONTEXTS:");
+ hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %p %s %u %s %u %s %u\n",
+ "smqcontext:", ictx,
+ "sc:", ictx->sc,
+ "tid:", ictx->pid,
+ "handle", ictx->rpra->h);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s\n",
+ "LIST OF INTERRUPTED SMQCONTEXTS:");
+ hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %p %s %u %s %u %s %u\n",
+ "smqcontext:", ictx,
+ "sc:", ictx->sc,
+ "tid:", ictx->pid,
+ "handle", ictx->rpra->h);
+ }
+ spin_unlock(&fl->hlock);
+ }
+ if (len > DEBUGFS_SIZE)
+ len = DEBUGFS_SIZE;
+ ret = simple_read_from_buffer(buffer, count, position, fileinfo, len);
+ kfree(fileinfo);
+bail:
+ return ret;
+}
+
+static const struct file_operations debugfs_fops = {
+ .open = fastrpc_debugfs_open,
+ .read = fastrpc_debugfs_read,
+};
+
static int fastrpc_device_open(struct inode *inode, struct file *filp)
{
int cid = MINOR(inode->i_rdev);
+ struct dentry *debugfs_file;
int err = 0;
struct fastrpc_apps *me = &gfa;
struct fastrpc_file *fl = 0;
@@ -2173,6 +2242,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
mutex_lock(&me->smd_mutex);
+ debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root,
+ fl, &debugfs_fops);
context_list_ctor(&fl->clst);
spin_lock_init(&fl->hlock);
INIT_HLIST_HEAD(&fl->maps);
@@ -2181,6 +2252,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->tgid = current->tgid;
fl->apps = me;
fl->cid = cid;
+ if (debugfs_file != NULL)
+ fl->debugfs_file = debugfs_file;
memset(&fl->perf, 0, sizeof(fl->perf));
VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0,
@@ -2191,16 +2264,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->ssrcount = me->channel[cid].ssrcount;
if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
(me->channel[cid].chan == 0)) {
- if (me->glink) {
- fastrpc_glink_register(cid, me);
- VERIFY(err, 0 == fastrpc_glink_open(cid));
- } else {
- VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID,
- gcinfo[cid].channel,
- (smd_channel_t **)&me->channel[cid].chan,
- (void *)(uintptr_t)cid,
- smd_event_handler));
- }
+ fastrpc_glink_register(cid, me);
+ VERIFY(err, 0 == fastrpc_glink_open(cid));
if (err)
goto bail;
@@ -2387,11 +2452,7 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
mutex_lock(&me->smd_mutex);
ctx->ssrcount++;
if (ctx->chan) {
- if (me->glink) {
- fastrpc_glink_close(ctx->chan, cid);
- } else {
- smd_close(ctx->chan);
- }
+ fastrpc_glink_close(ctx->chan, cid);
ctx->chan = 0;
pr_info("'restart notifier: closed /dev/%s c %d %d'\n",
gcinfo[cid].name, MAJOR(me->dev_no), cid);
@@ -2496,6 +2557,8 @@ static int fastrpc_cb_probe(struct device *dev)
sess->dev = dev;
sess->smmu.enabled = 1;
chan->sesscount++;
+ debugfs_global_file = debugfs_create_file("global", 0644, debugfs_root,
+ NULL, &debugfs_fops);
bail:
return err;
}
@@ -2610,8 +2673,6 @@ static int fastrpc_probe(struct platform_device *pdev)
return 0;
}
- me->glink = of_property_read_bool(dev->of_node, "qcom,fastrpc-glink");
-
VERIFY(err, !of_platform_populate(pdev->dev.of_node,
fastrpc_match_table,
NULL, &pdev->dev));
@@ -2706,6 +2767,7 @@ static int __init fastrpc_device_init(void)
VERIFY(err, !IS_ERR_OR_NULL(me->client));
if (err)
goto device_create_bail;
+ debugfs_root = debugfs_create_dir("adsprpc", NULL);
return 0;
device_create_bail:
for (i = 0; i < NUM_CHANNELS; i++) {
@@ -2744,6 +2806,7 @@ static void __exit fastrpc_device_exit(void)
cdev_del(&me->cdev);
unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
ion_client_destroy(me->client);
+ debugfs_remove_recursive(debugfs_root);
}
late_initcall(fastrpc_device_init);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 409d2724042c..9d235b7abc58 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -514,7 +514,7 @@ struct diagchar_dev {
struct list_head cmd_reg_list;
struct mutex cmd_reg_mutex;
uint32_t cmd_reg_count;
- struct mutex diagfwd_channel_mutex;
+ struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
/* Sizes that reflect memory pool sizes */
unsigned int poolsize;
unsigned int poolsize_hdlc;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index f8b08527d633..facdb0f40e44 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -3371,7 +3371,7 @@ static int diagchar_cleanup(void)
static int __init diagchar_init(void)
{
dev_t dev;
- int error, ret;
+ int error, ret, i;
pr_debug("diagfwd initializing ..\n");
ret = 0;
@@ -3418,7 +3418,8 @@ static int __init diagchar_init(void)
mutex_init(&driver->diag_file_mutex);
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
- mutex_init(&driver->diagfwd_channel_mutex);
+ for (i = 0; i < NUM_PERIPHERALS; i++)
+ mutex_init(&driver->diagfwd_channel_mutex[i]);
init_waitqueue_head(&driver->wait_q);
INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index c1f954cdb080..3f9f7a999fdf 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -655,7 +655,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
return;
}
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[peripheral]);
fwd_info = &early_init_info[transport][peripheral];
if (fwd_info->p_ops && fwd_info->p_ops->close)
fwd_info->p_ops->close(fwd_info->ctxt);
@@ -679,7 +679,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
diagfwd_late_open(dest_info);
diagfwd_cntl_open(dest_info);
init_fn(peripheral);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[peripheral]);
diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]);
diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]);
}
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index 888949816dfe..22a60cdff7e7 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -1088,9 +1088,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
(info->data_ready > 0) || (!info->hdl) ||
(atomic_read(&info->diag_state) == 0));
if (err) {
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return -ERESTARTSYS;
}
@@ -1102,9 +1102,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"%s closing read thread. diag state is closed\n",
info->name);
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return 0;
}
@@ -1171,10 +1171,10 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
if (total_recd > 0) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n",
info->name, total_recd);
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
err = diagfwd_channel_read_done(info->fwd_ctxt,
buf, total_recd);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
if (err)
goto fail;
} else {
@@ -1187,9 +1187,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
return 0;
fail:
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return -EIO;
}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 6493b59dac01..4f1ba98a2b2c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
* Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -2534,7 +2534,46 @@ do { \
pr_info(fmt, ##__VA_ARGS__); \
} while (0)
-int clock_debug_print_clock(struct clk_core *c, struct seq_file *s)
+/*
+ * clock_debug_print_enabled_debug_suspend() - Print names of enabled clocks
+ * during suspend.
+ */
+static void clock_debug_print_enabled_debug_suspend(struct seq_file *s)
+{
+ struct clk_core *core;
+ int cnt = 0;
+
+ if (!mutex_trylock(&clk_debug_lock))
+ return;
+
+ clock_debug_output(s, 0, "Enabled clocks:\n");
+
+ hlist_for_each_entry(core, &clk_debug_list, debug_node) {
+ if (!core || !core->prepare_count)
+ continue;
+
+ if (core->vdd_class)
+ clock_debug_output(s, 0, " %s:%u:%u [%ld, %d]",
+ core->name, core->prepare_count,
+ core->enable_count, core->rate,
+ clk_find_vdd_level(core, core->rate));
+
+ else
+ clock_debug_output(s, 0, " %s:%u:%u [%ld]",
+ core->name, core->prepare_count,
+ core->enable_count, core->rate);
+ cnt++;
+ }
+
+ mutex_unlock(&clk_debug_lock);
+
+ if (cnt)
+ clock_debug_output(s, 0, "Enabled clock count: %d\n", cnt);
+ else
+ clock_debug_output(s, 0, "No clocks enabled.\n");
+}
+
+static int clock_debug_print_clock(struct clk_core *c, struct seq_file *s)
{
char *start = "";
struct clk *clk;
@@ -2910,7 +2949,7 @@ void clock_debug_print_enabled(void)
if (likely(!debug_suspend))
return;
- clock_debug_print_enabled_clocks(NULL);
+ clock_debug_print_enabled_debug_suspend(NULL);
}
EXPORT_SYMBOL_GPL(clock_debug_print_enabled);
diff --git a/drivers/clk/msm/clock-debug.c b/drivers/clk/msm/clock-debug.c
index 00a86ba55171..0fe93ede17cc 100644
--- a/drivers/clk/msm/clock-debug.c
+++ b/drivers/clk/msm/clock-debug.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2014, 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2014, 2016-2017, The Linux Foundation. All rights
+ * reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -77,6 +78,7 @@ static int clock_debug_measure_get(void *data, u64 *val)
else
is_hw_gated = 0;
+ mutex_lock(&clock->prepare_lock);
ret = clk_set_parent(measure, clock);
if (!ret) {
/*
@@ -107,6 +109,7 @@ static int clock_debug_measure_get(void *data, u64 *val)
*/
meas_rate = clk_get_rate(clock);
sw_rate = clk_get_rate(measure->parent);
+ mutex_unlock(&clock->prepare_lock);
if (sw_rate && meas_rate >= (sw_rate * 2))
*val *= DIV_ROUND_CLOSEST(meas_rate, sw_rate);
diff --git a/drivers/clk/msm/clock-gcc-8998.c b/drivers/clk/msm/clock-gcc-8998.c
index 87cf6cc5631e..8b7efbd093b5 100644
--- a/drivers/clk/msm/clock-gcc-8998.c
+++ b/drivers/clk/msm/clock-gcc-8998.c
@@ -263,6 +263,7 @@ static struct rcg_clk hmss_ahb_clk_src = {
static struct clk_freq_tbl ftbl_usb30_master_clk_src[] = {
F( 19200000, cxo_clk_src, 1, 0, 0),
+ F( 60000000, gpll0_out_main, 10, 0, 0),
F( 120000000, gpll0_out_main, 5, 0, 0),
F( 150000000, gpll0_out_main, 4, 0, 0),
F_END
diff --git a/drivers/clk/msm/clock-mmss-8998.c b/drivers/clk/msm/clock-mmss-8998.c
index 2a112aad1fa3..eb543010c17b 100644
--- a/drivers/clk/msm/clock-mmss-8998.c
+++ b/drivers/clk/msm/clock-mmss-8998.c
@@ -527,6 +527,7 @@ static struct clk_freq_tbl ftbl_csiphy_clk_src[] = {
static struct clk_freq_tbl ftbl_csiphy_clk_src_vq[] = {
F_MM( 164570000, mmpll10_pll_out, 3.5, 0, 0),
F_MM( 256000000, mmpll4_pll_out, 3, 0, 0),
+ F_MM( 274290000, mmpll7_pll_out, 3.5, 0, 0),
F_MM( 300000000, mmsscc_gpll0, 2, 0, 0),
F_MM( 384000000, mmpll4_pll_out, 2, 0, 0),
F_END
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
index 096e16db02fe..bfaf4482d668 100644
--- a/drivers/clk/qcom/clk-branch.c
+++ b/drivers/clk/qcom/clk-branch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016-2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -275,6 +275,8 @@ static int clk_branch2_hw_ctl_determine_rate(struct clk_hw *hw,
struct clk_hw *clkp;
clkp = __clk_get_hw(clk_get_parent(hw->clk));
+ if (!clkp)
+ return -EINVAL;
req->best_parent_hw = clkp;
req->best_parent_rate = clk_round_rate(clkp->clk, req->rate);
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 5ed0dba189f7..6d13adf7a6ee 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -1512,7 +1512,7 @@ static int clk_osm_setup_hw_table(struct clk_osm *c)
{
struct osm_entry *entry = c->osm_table;
int i;
- u32 freq_val, volt_val, override_val, spare_val;
+ u32 freq_val = 0, volt_val = 0, override_val = 0, spare_val = 0;
u32 table_entry_offset, last_spare, last_virtual_corner = 0;
for (i = 0; i < OSM_TABLE_SIZE; i++) {
@@ -2472,14 +2472,19 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu)
static void populate_opp_table(struct platform_device *pdev)
{
int cpu;
+ struct device *cpu_dev;
for_each_possible_cpu(cpu) {
if (logical_cpu_to_clk(cpu) == pwrcl_clk.hw.clk) {
- WARN(add_opp(&pwrcl_clk, get_cpu_device(cpu)),
+ cpu_dev = get_cpu_device(cpu);
+ if (cpu_dev)
+ WARN(add_opp(&pwrcl_clk, cpu_dev),
"Failed to add OPP levels for power cluster\n");
}
if (logical_cpu_to_clk(cpu) == perfcl_clk.hw.clk) {
- WARN(add_opp(&perfcl_clk, get_cpu_device(cpu)),
+ cpu_dev = get_cpu_device(cpu);
+ if (cpu_dev)
+ WARN(add_opp(&perfcl_clk, cpu_dev),
"Failed to add OPP levels for perf cluster\n");
}
}
@@ -2543,7 +2548,7 @@ static ssize_t debugfs_trace_method_set(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
- struct clk_osm *c = file->private_data;
+ struct clk_osm *c;
u32 val;
if (IS_ERR(file) || file == NULL) {
@@ -2551,6 +2556,8 @@ static ssize_t debugfs_trace_method_set(struct file *file,
return -EINVAL;
}
+ c = file->private_data;
+
if (!c) {
pr_err("invalid clk_osm handle\n");
return -EINVAL;
@@ -2593,7 +2600,7 @@ static ssize_t debugfs_trace_method_set(struct file *file,
static ssize_t debugfs_trace_method_get(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct clk_osm *c = file->private_data;
+ struct clk_osm *c;
int len, rc;
if (IS_ERR(file) || file == NULL) {
@@ -2601,6 +2608,8 @@ static ssize_t debugfs_trace_method_get(struct file *file, char __user *buf,
return -EINVAL;
}
+ c = file->private_data;
+
if (!c) {
pr_err("invalid clk_osm handle\n");
return -EINVAL;
@@ -3023,7 +3032,7 @@ static unsigned long perfcl_boot_rate = 1747200000;
static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
{
- int rc, cpu, i;
+ int rc = 0, cpu, i;
int speedbin = 0, pvs_ver = 0;
u32 pte_efuse;
int num_clks = ARRAY_SIZE(osm_qcom_clk_hws);
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index 076ff3565ef4..d8ae85b65a47 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -818,7 +818,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = {
.parent_names = gcc_parent_names_ao_1,
.num_parents = 3,
.ops = &clk_rcg2_ops,
- VDD_DIG_FMAX_MAP2(
+ VDD_DIG_FMAX_MAP2_AO(
LOWER, 19200000,
NOMINAL, 50000000),
},
diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile
index 6a0a1de1e942..733b91b993d6 100644
--- a/drivers/clk/qcom/mdss/Makefile
+++ b/drivers/clk/qcom/mdss/Makefile
@@ -2,3 +2,5 @@ obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll-util.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm-util.o
+obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-14nm.o
+obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-14nm-util.o
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c
new file mode 100644
index 000000000000..0965d5590a28
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c
@@ -0,0 +1,624 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/usb/usbpd.h>
+
+#include "mdss-pll.h"
+#include "mdss-dp-pll.h"
+#include "mdss-dp-pll-14nm.h"
+
+int dp_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val)
+{
+ struct mdss_pll_resources *dp_res = context;
+ int rc;
+ u32 auxclk_div;
+
+ rc = mdss_pll_resource_enable(dp_res, true);
+ if (rc) {
+ pr_err("Failed to enable mdss DP PLL resources\n");
+ return rc;
+ }
+
+ auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV);
+ auxclk_div &= ~0x03; /* bits 0 to 1 */
+
+ if (val == 0) /* mux parent index = 0 */
+ auxclk_div |= 1;
+ else if (val == 1) /* mux parent index = 1 */
+ auxclk_div |= 2;
+
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_VCO_DIV, auxclk_div);
+ /* Make sure the PHY registers writes are done */
+ wmb();
+ pr_debug("%s: mux=%d auxclk_div=%x\n", __func__, val, auxclk_div);
+
+ mdss_pll_resource_enable(dp_res, false);
+
+ return 0;
+}
+
+int dp_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val)
+{
+ int rc;
+ u32 auxclk_div = 0;
+ struct mdss_pll_resources *dp_res = context;
+
+ rc = mdss_pll_resource_enable(dp_res, true);
+ if (rc) {
+ pr_err("Failed to enable dp_res resources\n");
+ return rc;
+ }
+
+ auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV);
+ auxclk_div &= 0x03;
+
+ if (auxclk_div == 1) /* Default divider */
+ *val = 0;
+ else if (auxclk_div == 2)
+ *val = 1;
+
+ mdss_pll_resource_enable(dp_res, false);
+
+ pr_debug("%s: auxclk_div=%d, val=%d\n", __func__, auxclk_div, *val);
+
+ return 0;
+}
+
+static int dp_vco_pll_init_db_14nm(struct dp_pll_db *pdb,
+ unsigned long rate)
+{
+ struct mdss_pll_resources *dp_res = pdb->pll;
+ u32 spare_value = 0;
+
+ spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0);
+ pdb->lane_cnt = spare_value & 0x0F;
+ pdb->orientation = (spare_value & 0xF0) >> 4;
+
+ pr_debug("%s: spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n",
+ __func__, spare_value, pdb->lane_cnt, pdb->orientation);
+
+ switch (rate) {
+ case DP_VCO_HSCLK_RATE_1620MHZDIV1000:
+ pdb->hsclk_sel = 0x2c;
+ pdb->dec_start_mode0 = 0x69;
+ pdb->div_frac_start1_mode0 = 0x00;
+ pdb->div_frac_start2_mode0 = 0x80;
+ pdb->div_frac_start3_mode0 = 0x07;
+ pdb->lock_cmp1_mode0 = 0xbf;
+ pdb->lock_cmp2_mode0 = 0x21;
+ pdb->lock_cmp3_mode0 = 0x00;
+ pdb->phy_vco_div = 0x1;
+ break;
+ case DP_VCO_HSCLK_RATE_2700MHZDIV1000:
+ pdb->hsclk_sel = 0x24;
+ pdb->dec_start_mode0 = 0x69;
+ pdb->div_frac_start1_mode0 = 0x00;
+ pdb->div_frac_start2_mode0 = 0x80;
+ pdb->div_frac_start3_mode0 = 0x07;
+ pdb->lock_cmp1_mode0 = 0x3f;
+ pdb->lock_cmp2_mode0 = 0x38;
+ pdb->lock_cmp3_mode0 = 0x00;
+ pdb->phy_vco_div = 0x1;
+ break;
+ case DP_VCO_HSCLK_RATE_5400MHZDIV1000:
+ pdb->hsclk_sel = 0x20;
+ pdb->dec_start_mode0 = 0x8c;
+ pdb->div_frac_start1_mode0 = 0x00;
+ pdb->div_frac_start2_mode0 = 0x00;
+ pdb->div_frac_start3_mode0 = 0x0a;
+ pdb->lock_cmp1_mode0 = 0x7f;
+ pdb->lock_cmp2_mode0 = 0x70;
+ pdb->lock_cmp3_mode0 = 0x00;
+ pdb->phy_vco_div = 0x2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int dp_config_vco_rate_14nm(struct dp_pll_vco_clk *vco,
+ unsigned long rate)
+{
+ u32 res = 0;
+ struct mdss_pll_resources *dp_res = vco->priv;
+ struct dp_pll_db *pdb = (struct dp_pll_db *)dp_res->priv;
+
+ res = dp_vco_pll_init_db_14nm(pdb, rate);
+ if (res) {
+ pr_err("VCO Init DB failed\n");
+ return res;
+ }
+
+ if (pdb->lane_cnt != 4) {
+ if (pdb->orientation == ORIENTATION_CC2)
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x2d);
+ else
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x35);
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_PD_CTL, 0x3d);
+ }
+
+ /* Make sure the PHY register writes are done */
+ wmb();
+
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_SYSCLK_EN_SEL, 0x37);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CLK_SELECT, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_SYS_CLK_CTRL, 0x06);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CLK_ENABLE1, 0x0e);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_BG_CTRL, 0x0f);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CLK_SELECT, 0x30);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_PLL_IVCO, 0x0f);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_PLL_CCTRL_MODE0, 0x28);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CP_CTRL_MODE0, 0x0b);
+
+ /* Parameters dependent on vco clock frequency */
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_HSCLK_SEL, pdb->hsclk_sel);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_LOCK_CMP3_MODE0, pdb->lock_cmp3_mode0);
+
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x40);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_VCO_TUNE_MAP, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_BG_TIMER, 0x08);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CORECLK_DIV, 0x05);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_VCO_TUNE_CTRL, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_VCO_TUNE1_MODE0, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_VCO_TUNE2_MODE0, 0x00);
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_VCO_TUNE_CTRL, 0x00);
+ wmb(); /* make sure write happens */
+
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CORE_CLK_EN, 0x0f);
+ wmb(); /* make sure write happens */
+
+ if (pdb->orientation == ORIENTATION_CC2)
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0xc8);
+ else
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0xd8);
+ wmb(); /* make sure write happens */
+
+ /* TX Lane configuration */
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_TX0_TX1_LANE_CTL, 0x05);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_TX2_TX3_LANE_CTL, 0x05);
+
+ /* TX-0 register configuration */
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, 0x40);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_INTERFACE_SELECT, 0x3d);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x0f);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_RESET_TSYNC_EN, 0x03);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TRAN_DRVR_EMP_EN, 0x03);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TX_INTERFACE_MODE, 0x00);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x23);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x3f);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TX_BAND, 0x4);
+
+ /* TX-1 register configuration */
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, 0x40);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_INTERFACE_SELECT, 0x3d);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x0f);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_RESET_TSYNC_EN, 0x03);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TRAN_DRVR_EMP_EN, 0x03);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, 0x00);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x23);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x3f);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TX_BAND, 0x4);
+ wmb(); /* make sure write happens */
+
+ /* PHY VCO divider programming */
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ DP_PHY_VCO_DIV, pdb->phy_vco_div);
+ wmb(); /* make sure write happens */
+
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_CMN_CONFIG, 0x02);
+ wmb(); /* make sure write happens */
+
+ return res;
+}
+
+static bool dp_14nm_pll_lock_status(struct mdss_pll_resources *dp_res)
+{
+ u32 status;
+ bool pll_locked;
+
+ /* poll for PLL lock status */
+ if (readl_poll_timeout_atomic((dp_res->pll_base +
+ QSERDES_COM_C_READY_STATUS),
+ status,
+ ((status & BIT(0)) > 0),
+ DP_PLL_POLL_SLEEP_US,
+ DP_PLL_POLL_TIMEOUT_US)) {
+ pr_err("%s: C_READY status is not high. Status=%x\n",
+ __func__, status);
+ pll_locked = false;
+ } else {
+ pll_locked = true;
+ }
+
+ return pll_locked;
+}
+
+static bool dp_14nm_phy_rdy_status(struct mdss_pll_resources *dp_res)
+{
+ u32 status;
+ bool phy_ready = true;
+
+ /* poll for PHY ready status */
+ if (readl_poll_timeout_atomic((dp_res->phy_base +
+ DP_PHY_STATUS),
+ status,
+ ((status & (BIT(1) | BIT(0))) > 0),
+ DP_PHY_POLL_SLEEP_US,
+ DP_PHY_POLL_TIMEOUT_US)) {
+ pr_err("%s: Phy_ready is not high. Status=%x\n",
+ __func__, status);
+ phy_ready = false;
+ }
+
+ return phy_ready;
+}
+
+static int dp_pll_enable_14nm(struct clk_hw *hw)
+{
+ int rc = 0;
+ u32 bias_en, drvr_en;
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ struct mdss_pll_resources *dp_res = vco->priv;
+ struct dp_pll_db *pdb = (struct dp_pll_db *)dp_res->priv;
+
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01);
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x05);
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01);
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09);
+ wmb(); /* Make sure the PHY register writes are done */
+
+ MDSS_PLL_REG_W(dp_res->pll_base,
+ QSERDES_COM_RESETSM_CNTRL, 0x20);
+ wmb(); /* Make sure the PLL register writes are done */
+
+ udelay(900); /* hw recommended delay for full PU */
+
+ if (!dp_14nm_pll_lock_status(dp_res)) {
+ rc = -EINVAL;
+ goto lock_err;
+ }
+
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19);
+ wmb(); /* Make sure the PHY register writes are done */
+
+ udelay(10); /* hw recommended delay */
+
+ if (!dp_14nm_phy_rdy_status(dp_res)) {
+ rc = -EINVAL;
+ goto lock_err;
+ }
+
+ pr_debug("%s: PLL is locked\n", __func__);
+
+ if (pdb->lane_cnt == 1) {
+ bias_en = 0x3e;
+ drvr_en = 0x13;
+ } else {
+ bias_en = 0x3f;
+ drvr_en = 0x10;
+ }
+
+ if (pdb->lane_cnt != 4) {
+ if (pdb->orientation == ORIENTATION_CC1) {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, drvr_en);
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, drvr_en);
+ }
+ } else {
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, drvr_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, bias_en);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, drvr_en);
+ }
+
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX0_OFFSET + TXn_TX_POL_INV, 0x0a);
+ MDSS_PLL_REG_W(dp_res->phy_base,
+ QSERDES_TX1_OFFSET + TXn_TX_POL_INV, 0x0a);
+
+ /*
+ * Switch DP Mainlink clock (cc_dpphy_link_clk) from DP
+ * controller side with final frequency
+ */
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18);
+ wmb(); /* Make sure the PHY register writes are done */
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19);
+ wmb(); /* Make sure the PHY register writes are done */
+
+lock_err:
+ return rc;
+}
+
+static int dp_pll_disable_14nm(struct clk_hw *hw)
+{
+ int rc = 0;
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ struct mdss_pll_resources *dp_res = vco->priv;
+
+ /* Assert DP PHY power down */
+ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x2);
+ /*
+ * Make sure all the register writes to disable PLL are
+ * completed before doing any other operation
+ */
+ wmb();
+
+ return rc;
+}
+
+
+int dp_vco_prepare_14nm(struct clk_hw *hw)
+{
+ int rc = 0;
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ struct mdss_pll_resources *dp_res = vco->priv;
+
+ DEV_DBG("rate=%ld\n", vco->rate);
+ rc = mdss_pll_resource_enable(dp_res, true);
+ if (rc) {
+ pr_err("Failed to enable mdss DP pll resources\n");
+ goto error;
+ }
+
+ if ((dp_res->vco_cached_rate != 0)
+ && (dp_res->vco_cached_rate == vco->rate)) {
+ rc = vco->hw.init->ops->set_rate(hw,
+ dp_res->vco_cached_rate, dp_res->vco_cached_rate);
+ if (rc) {
+ pr_err("index=%d vco_set_rate failed. rc=%d\n",
+ rc, dp_res->index);
+ mdss_pll_resource_enable(dp_res, false);
+ goto error;
+ }
+ }
+
+ rc = dp_pll_enable_14nm(hw);
+ if (rc) {
+ mdss_pll_resource_enable(dp_res, false);
+ pr_err("ndx=%d failed to enable dp pll\n",
+ dp_res->index);
+ goto error;
+ }
+
+ mdss_pll_resource_enable(dp_res, false);
+error:
+ return rc;
+}
+
+void dp_vco_unprepare_14nm(struct clk_hw *hw)
+{
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ struct mdss_pll_resources *dp_res = vco->priv;
+
+ if (!dp_res) {
+ DEV_ERR("Invalid input parameter\n");
+ return;
+ }
+
+ if (!dp_res->pll_on &&
+ mdss_pll_resource_enable(dp_res, true)) {
+ DEV_ERR("pll resource can't be enabled\n");
+ return;
+ }
+ dp_res->vco_cached_rate = vco->rate;
+ dp_pll_disable_14nm(hw);
+
+ dp_res->handoff_resources = false;
+ mdss_pll_resource_enable(dp_res, false);
+ dp_res->pll_on = false;
+}
+
+int dp_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ struct mdss_pll_resources *dp_res = vco->priv;
+ int rc;
+
+ rc = mdss_pll_resource_enable(dp_res, true);
+ if (rc) {
+ DEV_ERR("pll resource can't be enabled\n");
+ return rc;
+ }
+
+ DEV_DBG("DP lane CLK rate=%ld\n", rate);
+
+ rc = dp_config_vco_rate_14nm(vco, rate);
+ if (rc)
+ DEV_ERR("%s: Failed to set clk rate\n", __func__);
+
+ mdss_pll_resource_enable(dp_res, false);
+
+ vco->rate = rate;
+
+ return 0;
+}
+
+unsigned long dp_vco_recalc_rate_14nm(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+ int rc;
+ u32 div, hsclk_div, link2xclk_div = 0;
+ u64 vco_rate;
+ struct mdss_pll_resources *dp_res = vco->priv;
+
+ if (is_gdsc_disabled(dp_res))
+ return 0;
+
+ rc = mdss_pll_resource_enable(dp_res, true);
+ if (rc) {
+ pr_err("Failed to enable mdss DP pll=%d\n", dp_res->index);
+ return rc;
+ }
+
+ div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL);
+ div &= 0x0f;
+
+ if (div == 12)
+ hsclk_div = 5; /* Default */
+ else if (div == 4)
+ hsclk_div = 3;
+ else if (div == 0)
+ hsclk_div = 2;
+ else {
+ pr_debug("unknown divider. forcing to default\n");
+ hsclk_div = 5;
+ }
+
+ div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_MODE);
+
+ if (div & 0xd8)
+ pr_err("%s: DP PAR Rate not correct\n", __func__);
+
+ if ((div & 0x3) == 1)
+ link2xclk_div = 10;
+ else if ((div & 0x3) == 0)
+ link2xclk_div = 5;
+ else
+ pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div);
+
+ if (link2xclk_div == 10) {
+ vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000;
+ } else {
+ if (hsclk_div == 5)
+ vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000;
+ else if (hsclk_div == 3)
+ vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000;
+ else
+ vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000;
+ }
+
+ pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
+
+ mdss_pll_resource_enable(dp_res, false);
+
+ return (unsigned long)vco_rate;
+}
+
+long dp_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long rrate = rate;
+ struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw);
+
+ if (rate <= vco->min_rate)
+ rrate = vco->min_rate;
+ else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000)
+ rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000;
+ else
+ rrate = vco->max_rate;
+
+ pr_debug("%s: rrate=%ld\n", __func__, rrate);
+
+ *parent_rate = rrate;
+ return rrate;
+}
+
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c
new file mode 100644
index 000000000000..ffe8286cfaaa
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c
@@ -0,0 +1,234 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+***************************************************************************
+******** Display Port PLL driver block diagram for branch clocks **********
+***************************************************************************
+
+ +--------------------------+
+ | DP_VCO_CLK |
+ | |
+ | +-------------------+ |
+ | | (DP PLL/VCO) | |
+ | +---------+---------+ |
+ | v |
+ | +----------+-----------+ |
+ | | hsclk_divsel_clk_src | |
+ | +----------+-----------+ |
+ +--------------------------+
+ |
+ v
+ +------------<------------|------------>-------------+
+ | | |
++----------v----------+ +----------v----------+ +----------v----------+
+| dp_link_2x_clk | | vco_divided_clk_src | | vco_divided_clk_src |
+| divsel_five | | | | |
+v----------+----------v | divsel_two | | divsel_four |
+ | +----------+----------+ +----------+----------+
+ | | |
+ v v v
+ | +---------------------+ |
+ Input to MMSSCC block | | (aux_clk_ops) | |
+ for link clk, crypto clk +--> vco_divided_clk <-+
+ and interface clock | _src_mux |
+ +----------+----------+
+ |
+ v
+ Input to MMSSCC block
+ for DP pixel clock
+
+******************************************************************************
+*/
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include "mdss-pll.h"
+#include "mdss-dp-pll.h"
+#include "mdss-dp-pll-14nm.h"
+
+static struct dp_pll_db dp_pdb;
+
+static struct regmap_config dp_pll_14nm_cfg = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x910,
+};
+
+static struct regmap_bus dp_pixel_mux_regmap_ops = {
+ .reg_write = dp_mux_set_parent_14nm,
+ .reg_read = dp_mux_get_parent_14nm,
+};
+
+/* Op structures */
+static struct clk_ops dp_14nm_vco_clk_ops = {
+ .recalc_rate = dp_vco_recalc_rate_14nm,
+ .set_rate = dp_vco_set_rate_14nm,
+ .round_rate = dp_vco_round_rate_14nm,
+ .prepare = dp_vco_prepare_14nm,
+ .unprepare = dp_vco_unprepare_14nm,
+};
+
+static struct dp_pll_vco_clk dp_vco_clk = {
+ .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000,
+ .max_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000,
+ .hw.init = &(struct clk_init_data){
+ .name = "dp_vco_clk",
+ .parent_names = (const char *[]){ "xo_board" },
+ .num_parents = 1,
+ .ops = &dp_14nm_vco_clk_ops,
+ },
+};
+
+static struct clk_fixed_factor dp_link_2x_clk_divsel_five = {
+ .div = 5,
+ .mult = 1,
+
+ .hw.init = &(struct clk_init_data){
+ .name = "dp_link_2x_clk_divsel_five",
+ .parent_names =
+ (const char *[]){ "dp_vco_clk" },
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_fixed_factor dp_vco_divsel_two_clk_src = {
+ .div = 2,
+ .mult = 1,
+
+ .hw.init = &(struct clk_init_data){
+ .name = "dp_vco_divsel_two_clk_src",
+ .parent_names =
+ (const char *[]){ "dp_vco_clk" },
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE),
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_fixed_factor dp_vco_divsel_four_clk_src = {
+ .div = 4,
+ .mult = 1,
+
+ .hw.init = &(struct clk_init_data){
+ .name = "dp_vco_divsel_four_clk_src",
+ .parent_names =
+ (const char *[]){ "dp_vco_clk" },
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE),
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_regmap_mux dp_vco_divided_clk_src_mux = {
+ .reg = 0x64,
+ .shift = 0,
+ .width = 1,
+
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "dp_vco_divided_clk_src_mux",
+ .parent_names =
+ (const char *[]){"dp_vco_divsel_two_clk_src",
+ "dp_vco_divsel_four_clk_src"},
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ },
+ },
+};
+
+static struct clk_hw *mdss_dp_pllcc_14nm[] = {
+ [DP_VCO_CLK] = &dp_vco_clk.hw,
+ [DP_LINK_2X_CLK_DIVSEL_FIVE] = &dp_link_2x_clk_divsel_five.hw,
+ [DP_VCO_DIVSEL_FOUR_CLK_SRC] = &dp_vco_divsel_four_clk_src.hw,
+ [DP_VCO_DIVSEL_TWO_CLK_SRC] = &dp_vco_divsel_two_clk_src.hw,
+ [DP_VCO_DIVIDED_CLK_SRC_MUX] = &dp_vco_divided_clk_src_mux.clkr.hw,
+};
+
+int dp_pll_clock_register_14nm(struct platform_device *pdev,
+ struct mdss_pll_resources *pll_res)
+{
+ int rc = -ENOTSUPP, i = 0;
+ struct clk_onecell_data *clk_data;
+ struct clk *clk;
+ struct regmap *regmap;
+ int num_clks = ARRAY_SIZE(mdss_dp_pllcc_14nm);
+
+ if (!pdev || !pdev->dev.of_node) {
+ pr_err("Invalid input parameters\n");
+ return -EINVAL;
+ }
+
+ if (!pll_res || !pll_res->pll_base || !pll_res->phy_base) {
+ DEV_ERR("%s: Invalid input parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks *
+ sizeof(struct clk *)), GFP_KERNEL);
+ if (!clk_data->clks) {
+ devm_kfree(&pdev->dev, clk_data);
+ return -ENOMEM;
+ }
+ clk_data->clk_num = num_clks;
+
+ pll_res->priv = &dp_pdb;
+ dp_pdb.pll = pll_res;
+
+ /* Set client data for vco, mux and div clocks */
+ regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops,
+ pll_res, &dp_pll_14nm_cfg);
+ dp_vco_divided_clk_src_mux.clkr.regmap = regmap;
+
+ dp_vco_clk.priv = pll_res;
+
+ for (i = DP_VCO_CLK; i <= DP_VCO_DIVIDED_CLK_SRC_MUX; i++) {
+ pr_debug("reg clk: %d index: %d\n", i, pll_res->index);
+ clk = devm_clk_register(&pdev->dev,
+ mdss_dp_pllcc_14nm[i]);
+ if (IS_ERR(clk)) {
+ pr_err("clk registration failed for DP: %d\n",
+ pll_res->index);
+ rc = -EINVAL;
+ goto clk_reg_fail;
+ }
+ clk_data->clks[i] = clk;
+ }
+
+ rc = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, clk_data);
+ if (rc) {
+ DEV_ERR("%s: Clock register failed rc=%d\n", __func__, rc);
+ rc = -EPROBE_DEFER;
+ } else {
+ DEV_DBG("%s SUCCESS\n", __func__);
+ }
+ return 0;
+clk_reg_fail:
+ devm_kfree(&pdev->dev, clk_data->clks);
+ devm_kfree(&pdev->dev, clk_data);
+ return rc;
+}
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h
new file mode 100644
index 000000000000..08dee8909da4
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h
@@ -0,0 +1,193 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MDSS_DP_PLL_14NM_H
+#define __MDSS_DP_PLL_14NM_H
+
+#define DP_PHY_REVISION_ID0 0x0000
+#define DP_PHY_REVISION_ID1 0x0004
+#define DP_PHY_REVISION_ID2 0x0008
+#define DP_PHY_REVISION_ID3 0x000C
+
+#define DP_PHY_CFG 0x0010
+#define DP_PHY_CFG_1 0x0014
+#define DP_PHY_PD_CTL 0x0018
+#define DP_PHY_MODE 0x001C
+
+#define DP_PHY_AUX_CFG0 0x0020
+#define DP_PHY_AUX_CFG1 0x0024
+#define DP_PHY_AUX_CFG2 0x0028
+#define DP_PHY_AUX_CFG3 0x002C
+#define DP_PHY_AUX_CFG4 0x0030
+#define DP_PHY_AUX_CFG5 0x0034
+#define DP_PHY_AUX_CFG6 0x0038
+#define DP_PHY_AUX_CFG7 0x003C
+#define DP_PHY_AUX_CFG8 0x0040
+#define DP_PHY_AUX_CFG9 0x0044
+#define DP_PHY_AUX_INTERRUPT_MASK 0x0048
+#define DP_PHY_AUX_INTERRUPT_CLEAR 0x004C
+#define DP_PHY_AUX_BIST_CFG 0x0050
+
+#define DP_PHY_VCO_DIV 0x0068
+#define DP_PHY_TX0_TX1_LANE_CTL 0x006C
+
+#define DP_PHY_TX2_TX3_LANE_CTL 0x0088
+#define DP_PHY_SPARE0 0x00AC
+#define DP_PHY_STATUS 0x00C0
+
+/* Tx registers */
+#define QSERDES_TX0_OFFSET 0x0400
+#define QSERDES_TX1_OFFSET 0x0800
+
+#define TXn_BIST_MODE_LANENO 0x0000
+#define TXn_CLKBUF_ENABLE 0x0008
+#define TXn_TX_EMP_POST1_LVL 0x000C
+
+#define TXn_TX_DRV_LVL 0x001C
+
+#define TXn_RESET_TSYNC_EN 0x0024
+#define TXn_PRE_STALL_LDO_BOOST_EN 0x0028
+#define TXn_TX_BAND 0x002C
+#define TXn_SLEW_CNTL 0x0030
+#define TXn_INTERFACE_SELECT 0x0034
+
+#define TXn_RES_CODE_LANE_TX 0x003C
+#define TXn_RES_CODE_LANE_RX 0x0040
+#define TXn_RES_CODE_LANE_OFFSET_TX 0x0044
+#define TXn_RES_CODE_LANE_OFFSET_RX 0x0048
+
+#define TXn_DEBUG_BUS_SEL 0x0058
+#define TXn_TRANSCEIVER_BIAS_EN 0x005C
+#define TXn_HIGHZ_DRVR_EN 0x0060
+#define TXn_TX_POL_INV 0x0064
+#define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068
+
+#define TXn_LANE_MODE_1 0x008C
+
+#define TXn_TRAN_DRVR_EMP_EN 0x00C0
+#define TXn_TX_INTERFACE_MODE 0x00C4
+
+#define TXn_VMODE_CTRL1 0x00F0
+
+
+/* PLL register offset */
+#define QSERDES_COM_ATB_SEL1 0x0000
+#define QSERDES_COM_ATB_SEL2 0x0004
+#define QSERDES_COM_FREQ_UPDATE 0x0008
+#define QSERDES_COM_BG_TIMER 0x000C
+#define QSERDES_COM_SSC_EN_CENTER 0x0010
+#define QSERDES_COM_SSC_ADJ_PER1 0x0014
+#define QSERDES_COM_SSC_ADJ_PER2 0x0018
+#define QSERDES_COM_SSC_PER1 0x001C
+#define QSERDES_COM_SSC_PER2 0x0020
+#define QSERDES_COM_SSC_STEP_SIZE1 0x0024
+#define QSERDES_COM_SSC_STEP_SIZE2 0x0028
+#define QSERDES_COM_POST_DIV 0x002C
+#define QSERDES_COM_POST_DIV_MUX 0x0030
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0034
+#define QSERDES_COM_CLK_ENABLE1 0x0038
+#define QSERDES_COM_SYS_CLK_CTRL 0x003C
+#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0040
+#define QSERDES_COM_PLL_EN 0x0044
+#define QSERDES_COM_PLL_IVCO 0x0048
+#define QSERDES_COM_LOCK_CMP1_MODE0 0x004C
+#define QSERDES_COM_LOCK_CMP2_MODE0 0x0050
+#define QSERDES_COM_LOCK_CMP3_MODE0 0x0054
+
+#define QSERDES_COM_CP_CTRL_MODE0 0x0078
+#define QSERDES_COM_CP_CTRL_MODE1 0x007C
+#define QSERDES_COM_PLL_RCTRL_MODE0 0x0084
+#define QSERDES_COM_PLL_CCTRL_MODE0 0x0090
+#define QSERDES_COM_PLL_CNTRL 0x009C
+
+#define QSERDES_COM_SYSCLK_EN_SEL 0x00AC
+#define QSERDES_COM_CML_SYSCLK_SEL 0x00B0
+#define QSERDES_COM_RESETSM_CNTRL 0x00B4
+#define QSERDES_COM_RESETSM_CNTRL2 0x00B8
+#define QSERDES_COM_LOCK_CMP_EN 0x00C8
+#define QSERDES_COM_LOCK_CMP_CFG 0x00CC
+
+
+#define QSERDES_COM_DEC_START_MODE0 0x00D0
+#define QSERDES_COM_DEC_START_MODE1 0x00D4
+#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00DC
+#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00E0
+#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00E4
+
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x0108
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x010C
+#define QSERDES_COM_VCO_TUNE_CTRL 0x0124
+#define QSERDES_COM_VCO_TUNE_MAP 0x0128
+#define QSERDES_COM_VCO_TUNE1_MODE0 0x012C
+#define QSERDES_COM_VCO_TUNE2_MODE0 0x0130
+
+#define QSERDES_COM_CMN_STATUS 0x015C
+#define QSERDES_COM_RESET_SM_STATUS 0x0160
+
+#define QSERDES_COM_BG_CTRL 0x0170
+#define QSERDES_COM_CLK_SELECT 0x0174
+#define QSERDES_COM_HSCLK_SEL 0x0178
+#define QSERDES_COM_CORECLK_DIV 0x0184
+#define QSERDES_COM_SW_RESET 0x0188
+#define QSERDES_COM_CORE_CLK_EN 0x018C
+#define QSERDES_COM_C_READY_STATUS 0x0190
+#define QSERDES_COM_CMN_CONFIG 0x0194
+#define QSERDES_COM_SVS_MODE_CLK_SEL 0x019C
+
+#define DP_PLL_POLL_SLEEP_US 500
+#define DP_PLL_POLL_TIMEOUT_US 10000
+
+#define DP_PHY_POLL_SLEEP_US 500
+#define DP_PHY_POLL_TIMEOUT_US 10000
+
+#define DP_VCO_RATE_8100MHZDIV1000 8100000UL
+#define DP_VCO_RATE_10800MHZDIV1000 10800000UL
+
+#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL
+#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL
+#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL
+
+struct dp_pll_db {
+ struct mdss_pll_resources *pll;
+
+ /* lane and orientation settings */
+ u8 lane_cnt;
+ u8 orientation;
+
+ /* COM PHY settings */
+ u32 hsclk_sel;
+ u32 dec_start_mode0;
+ u32 div_frac_start1_mode0;
+ u32 div_frac_start2_mode0;
+ u32 div_frac_start3_mode0;
+ u32 lock_cmp1_mode0;
+ u32 lock_cmp2_mode0;
+ u32 lock_cmp3_mode0;
+
+ /* PHY vco divider */
+ u32 phy_vco_div;
+};
+
+int dp_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+unsigned long dp_vco_recalc_rate_14nm(struct clk_hw *hw,
+ unsigned long parent_rate);
+long dp_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate);
+int dp_vco_prepare_14nm(struct clk_hw *hw);
+void dp_vco_unprepare_14nm(struct clk_hw *hw);
+int dp_mux_set_parent_14nm(void *context,
+ unsigned int reg, unsigned int val);
+int dp_mux_get_parent_14nm(void *context,
+ unsigned int reg, unsigned int *val);
+#endif /* __MDSS_DP_PLL_14NM_H */
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll.h b/drivers/clk/qcom/mdss/mdss-dp-pll.h
new file mode 100644
index 000000000000..a05e27af456e
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MDSS_DP_PLL_H
+#define __MDSS_DP_PLL_H
+
+struct dp_pll_vco_clk {
+ struct clk_hw hw;
+ unsigned long rate; /* current vco rate */
+ u64 min_rate; /* min vco rate */
+ u64 max_rate; /* max vco rate */
+ void *priv;
+};
+
+static inline struct dp_pll_vco_clk *to_dp_vco_hw(struct clk_hw *hw)
+{
+ return container_of(hw, struct dp_pll_vco_clk, hw);
+}
+
+int dp_pll_clock_register_14nm(struct platform_device *pdev,
+ struct mdss_pll_resources *pll_res);
+
+
+#endif /* __MDSS_DP_PLL_H */
+
diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c
index f356be38a25c..2f3a020a761a 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.c
+++ b/drivers/clk/qcom/mdss/mdss-pll.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,7 @@
#include "mdss-pll.h"
#include "mdss-dsi-pll.h"
+#include "mdss-dp-pll.h"
int mdss_pll_resource_enable(struct mdss_pll_resources *pll_res, bool enable)
{
@@ -141,6 +142,9 @@ static int mdss_pll_resource_parse(struct platform_device *pdev,
pll_res->pll_interface_type = MDSS_DSI_PLL_8998;
} else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_8998")) {
pll_res->pll_interface_type = MDSS_DP_PLL_8998;
+ } else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_sdm660")) {
+ pll_res->target_id = MDSS_PLL_TARGET_SDM660;
+ pll_res->pll_interface_type = MDSS_DP_PLL_SDM660;
} else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_8996")) {
pll_res->pll_interface_type = MDSS_HDMI_PLL_8996;
} else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_8996_v2")) {
@@ -178,6 +182,9 @@ static int mdss_pll_clock_register(struct platform_device *pdev,
case MDSS_DSI_PLL_8996:
rc = dsi_pll_clock_register_14nm(pdev, pll_res);
break;
+ case MDSS_DP_PLL_SDM660:
+ rc = dp_pll_clock_register_14nm(pdev, pll_res);
+ break;
case MDSS_UNKNOWN_PLL:
default:
rc = -EINVAL;
@@ -383,6 +390,7 @@ static const struct of_device_id mdss_pll_dt_match[] = {
{.compatible = "qcom,mdss_dp_pll_8998"},
{.compatible = "qcom,mdss_hdmi_pll_8998"},
{.compatible = "qcom,mdss_dsi_pll_sdm660"},
+ {.compatible = "qcom,mdss_dp_pll_sdm660"},
{}
};
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index e0e62a0f379b..9cf785d43504 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,7 @@ enum {
MDSS_DSI_PLL_8996,
MDSS_DSI_PLL_8998,
MDSS_DP_PLL_8998,
+ MDSS_DP_PLL_SDM660,
MDSS_HDMI_PLL_8996,
MDSS_HDMI_PLL_8996_V2,
MDSS_HDMI_PLL_8996_V3,
diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c
index 0226bf49b3b0..934779f16107 100644
--- a/drivers/clk/qcom/mmcc-sdm660.c
+++ b/drivers/clk/qcom/mmcc-sdm660.c
@@ -207,8 +207,8 @@ static const struct parent_map mmcc_parent_map_6[] = {
static const char * const mmcc_parent_names_6[] = {
"xo",
- "dp_phy_pll_link_clk",
- "dp_phy_pll_vco_div",
+ "dp_link_2x_clk_divsel_five",
+ "dp_vco_divided_clk_src_mux",
"core_bi_pll_test_se",
};
@@ -882,9 +882,9 @@ static struct clk_rcg2 dp_aux_clk_src = {
};
static const struct freq_tbl ftbl_dp_crypto_clk_src[] = {
- F(101250000, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
- F(168750000, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
- F(337500000, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
+ F(101250, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
+ F(168750, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
+ F(337500, P_DP_PHY_PLL_VCO_DIV, 4, 0, 0),
{ }
};
@@ -900,9 +900,9 @@ static struct clk_rcg2 dp_crypto_clk_src = {
.num_parents = 4,
.ops = &clk_rcg2_ops,
VDD_DIG_FMAX_MAP3(
- LOWER, 101250000,
- LOW, 168750000,
- NOMINAL, 337500000),
+ LOWER, 101250,
+ LOW, 168750,
+ NOMINAL, 337500),
},
};
@@ -930,9 +930,9 @@ static struct clk_rcg2 dp_gtc_clk_src = {
};
static const struct freq_tbl ftbl_dp_link_clk_src[] = {
- F(162000000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
- F(270000000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
- F(540000000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
+ F(162000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
+ F(270000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
+ F(540000, P_DP_PHY_PLL_LINK_CLK, 2, 0, 0),
{ }
};
@@ -949,9 +949,9 @@ static struct clk_rcg2 dp_link_clk_src = {
.ops = &clk_rcg2_ops,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
VDD_DIG_FMAX_MAP3(
- LOWER, 162000000,
- LOW, 270000000,
- NOMINAL, 540000000),
+ LOWER, 162000,
+ LOW, 270000,
+ NOMINAL, 540000),
},
};
@@ -966,9 +966,9 @@ static struct clk_rcg2 dp_pixel_clk_src = {
.num_parents = 4,
.ops = &clk_dp_ops,
VDD_DIG_FMAX_MAP3(
- LOWER, 148380000,
- LOW, 296740000,
- NOMINAL, 593470000),
+ LOWER, 148380,
+ LOW, 296740,
+ NOMINAL, 593470),
},
};
diff --git a/drivers/clk/qcom/vdd-level-660.h b/drivers/clk/qcom/vdd-level-660.h
index f98a96033ea9..53317fe6d294 100644
--- a/drivers/clk/qcom/vdd-level-660.h
+++ b/drivers/clk/qcom/vdd-level-660.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -95,6 +95,14 @@
}, \
.num_rate_max = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP2_AO(l1, f1, l2, f2) \
+ .vdd_class = &vdd_dig_ao, \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
+ [VDD_DIG_##l1] = (f1), \
+ [VDD_DIG_##l2] = (f2), \
+ }, \
+ .num_rate_max = VDD_DIG_NUM
+
#define VDD_DIG_FMAX_MAP3_AO(l1, f1, l2, f2, l3, f3) \
.vdd_class = &vdd_dig_ao, \
.rate_max = (unsigned long[VDD_DIG_NUM]) { \
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6ec828805428..e4d9aef1dda4 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1258,6 +1258,9 @@ static int cpufreq_online(unsigned int cpu)
for_each_cpu(j, policy->related_cpus)
per_cpu(cpufreq_cpu_data, j) = policy;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ } else {
+ policy->min = policy->user_policy.min;
+ policy->max = policy->user_policy.max;
}
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 433e4783d1d1..a629c621648c 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1,6 +1,6 @@
/* Qualcomm CE device driver.
*
- * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1381,7 +1381,7 @@ static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
/* if not using HW key make sure key
* length is valid
*/
- if ((req->mode == QCEDEV_AES_MODE_XTS)) {
+ if (req->mode == QCEDEV_AES_MODE_XTS) {
if ((req->encklen != QCEDEV_AES_KEY_128*2) &&
(req->encklen != QCEDEV_AES_KEY_256*2)) {
pr_err("%s: unsupported key size: %d\n",
@@ -1445,6 +1445,15 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
pr_err("%s: Invalid byte offset\n", __func__);
goto error;
}
+ total = req->byteoffset;
+ for (i = 0; i < req->entries; i++) {
+ if (total > U32_MAX - req->vbuf.src[i].len) {
+ pr_err("%s:Integer overflow on total src len\n",
+ __func__);
+ goto error;
+ }
+ total += req->vbuf.src[i].len;
+ }
}
if (req->data_len < req->byteoffset) {
@@ -1480,7 +1489,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
}
}
/* Check for sum of all dst length is equal to data_len */
- for (i = 0; i < req->entries; i++) {
+ for (i = 0, total = 0; i < req->entries; i++) {
if (req->vbuf.dst[i].len >= U32_MAX - total) {
pr_err("%s: Integer overflow on total req dst vbuf length\n",
__func__);
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 7f29f3644fb6..84d3ec98e6b9 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -3,7 +3,7 @@ config DRM_MSM
tristate "MSM DRM"
depends on DRM
depends on ARCH_QCOM || (ARM && COMPILE_TEST)
- depends on OF
+ depends on OF && COMMON_CLK
select REGULATOR
select DRM_KMS_HELPER
select DRM_PANEL
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 05b6ca9b5c55..1c90290be716 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -38,14 +38,6 @@ msm-y := \
mdp/mdp5/mdp5_kms.o \
mdp/mdp5/mdp5_plane.o \
mdp/mdp5/mdp5_smp.o \
- sde/sde_crtc.o \
- sde/sde_encoder.o \
- sde/sde_encoder_phys_vid.o \
- sde/sde_encoder_phys_cmd.o \
- sde/sde_irq.o \
- sde/sde_kms_utils.o \
- sde/sde_kms.o \
- sde/sde_plane.o \
msm_atomic.o \
msm_drv.o \
msm_fb.o \
@@ -54,7 +46,6 @@ msm-y := \
msm_gem_submit.o \
msm_gpu.o \
msm_iommu.o \
- msm_smmu.o \
msm_perf.o \
msm_rd.o \
msm_ringbuffer.o
@@ -78,18 +69,3 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
endif
obj-$(CONFIG_DRM_MSM) += msm.o
-
-obj-$(CONFIG_DRM_MSM) += sde/sde_hw_catalog.o \
- sde/sde_hw_catalog_8996.o \
- sde/sde_hw_cdm.o \
- sde/sde_hw_dspp.o \
- sde/sde_hw_intf.o \
- sde/sde_hw_lm.o \
- sde/sde_hw_mdp_ctl.o \
- sde/sde_hw_mdp_util.o \
- sde/sde_hw_sspp.o \
- sde/sde_hw_wb.o \
- sde/sde_hw_pingpong.o \
- sde/sde_hw_mdp_top.o \
- sde/sde_hw_interrupts.o \
- sde/sde_mdp_formats.o
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
deleted file mode 100644
index 114998fb8fc5..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "msm-dsi-catalog:[%s] " fmt, __func__
-#include <linux/errno.h>
-
-#include "dsi_catalog.h"
-
-/**
- * dsi_catalog_14_init() - catalog init for dsi controller v1.4
- */
-static void dsi_catalog_14_init(struct dsi_ctrl_hw *ctrl)
-{
- ctrl->ops.host_setup = dsi_ctrl_hw_14_host_setup;
- ctrl->ops.setup_lane_map = dsi_ctrl_hw_14_setup_lane_map;
- ctrl->ops.video_engine_en = dsi_ctrl_hw_14_video_engine_en;
- ctrl->ops.video_engine_setup = dsi_ctrl_hw_14_video_engine_setup;
- ctrl->ops.set_video_timing = dsi_ctrl_hw_14_set_video_timing;
- ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_14_cmd_engine_setup;
- ctrl->ops.ctrl_en = dsi_ctrl_hw_14_ctrl_en;
- ctrl->ops.cmd_engine_en = dsi_ctrl_hw_14_cmd_engine_en;
- ctrl->ops.phy_sw_reset = dsi_ctrl_hw_14_phy_sw_reset;
- ctrl->ops.soft_reset = dsi_ctrl_hw_14_soft_reset;
- ctrl->ops.kickoff_command = dsi_ctrl_hw_14_kickoff_command;
- ctrl->ops.kickoff_fifo_command = dsi_ctrl_hw_14_kickoff_fifo_command;
- ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_14_reset_cmd_fifo;
- ctrl->ops.trigger_command_dma = dsi_ctrl_hw_14_trigger_command_dma;
- ctrl->ops.ulps_request = dsi_ctrl_hw_14_ulps_request;
- ctrl->ops.ulps_exit = dsi_ctrl_hw_14_ulps_exit;
- ctrl->ops.clear_ulps_request = dsi_ctrl_hw_14_clear_ulps_request;
- ctrl->ops.get_lanes_in_ulps = dsi_ctrl_hw_14_get_lanes_in_ulps;
- ctrl->ops.clamp_enable = dsi_ctrl_hw_14_clamp_enable;
- ctrl->ops.clamp_disable = dsi_ctrl_hw_14_clamp_disable;
- ctrl->ops.get_interrupt_status = dsi_ctrl_hw_14_get_interrupt_status;
- ctrl->ops.get_error_status = dsi_ctrl_hw_14_get_error_status;
- ctrl->ops.clear_error_status = dsi_ctrl_hw_14_clear_error_status;
- ctrl->ops.clear_interrupt_status =
- dsi_ctrl_hw_14_clear_interrupt_status;
- ctrl->ops.enable_status_interrupts =
- dsi_ctrl_hw_14_enable_status_interrupts;
- ctrl->ops.enable_error_interrupts =
- dsi_ctrl_hw_14_enable_error_interrupts;
- ctrl->ops.video_test_pattern_setup =
- dsi_ctrl_hw_14_video_test_pattern_setup;
- ctrl->ops.cmd_test_pattern_setup =
- dsi_ctrl_hw_14_cmd_test_pattern_setup;
- ctrl->ops.test_pattern_enable = dsi_ctrl_hw_14_test_pattern_enable;
- ctrl->ops.trigger_cmd_test_pattern =
- dsi_ctrl_hw_14_trigger_cmd_test_pattern;
-}
-
-/**
- * dsi_catalog_20_init() - catalog init for dsi controller v2.0
- */
-static void dsi_catalog_20_init(struct dsi_ctrl_hw *ctrl)
-{
- set_bit(DSI_CTRL_CPHY, ctrl->feature_map);
-}
-
-/**
- * dsi_catalog_ctrl_setup() - return catalog info for dsi controller
- * @ctrl: Pointer to DSI controller hw object.
- * @version: DSI controller version.
- * @index: DSI controller instance ID.
- *
- * This function setups the catalog information in the dsi_ctrl_hw object.
- *
- * return: error code for failure and 0 for success.
- */
-int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_ctrl_version version,
- u32 index)
-{
- int rc = 0;
-
- if (version == DSI_CTRL_VERSION_UNKNOWN ||
- version >= DSI_CTRL_VERSION_MAX) {
- pr_err("Unsupported version: %d\n", version);
- return -ENOTSUPP;
- }
-
- ctrl->index = index;
- set_bit(DSI_CTRL_VIDEO_TPG, ctrl->feature_map);
- set_bit(DSI_CTRL_CMD_TPG, ctrl->feature_map);
- set_bit(DSI_CTRL_VARIABLE_REFRESH_RATE, ctrl->feature_map);
- set_bit(DSI_CTRL_DYNAMIC_REFRESH, ctrl->feature_map);
- set_bit(DSI_CTRL_DESKEW_CALIB, ctrl->feature_map);
- set_bit(DSI_CTRL_DPHY, ctrl->feature_map);
-
- switch (version) {
- case DSI_CTRL_VERSION_1_4:
- dsi_catalog_14_init(ctrl);
- break;
- case DSI_CTRL_VERSION_2_0:
- dsi_catalog_20_init(ctrl);
- break;
- default:
- return -ENOTSUPP;
- }
-
- return rc;
-}
-
-/**
- * dsi_catalog_phy_4_0_init() - catalog init for DSI PHY v4.0
- */
-static void dsi_catalog_phy_4_0_init(struct dsi_phy_hw *phy)
-{
- phy->ops.regulator_enable = dsi_phy_hw_v4_0_regulator_enable;
- phy->ops.regulator_disable = dsi_phy_hw_v4_0_regulator_disable;
- phy->ops.enable = dsi_phy_hw_v4_0_enable;
- phy->ops.disable = dsi_phy_hw_v4_0_disable;
- phy->ops.calculate_timing_params =
- dsi_phy_hw_v4_0_calculate_timing_params;
-}
-
-/**
- * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware
- * @ctrl: Pointer to DSI PHY hw object.
- * @version: DSI PHY version.
- * @index: DSI PHY instance ID.
- *
- * This function setups the catalog information in the dsi_phy_hw object.
- *
- * return: error code for failure and 0 for success.
- */
-int dsi_catalog_phy_setup(struct dsi_phy_hw *phy,
- enum dsi_phy_version version,
- u32 index)
-{
- int rc = 0;
-
- if (version == DSI_PHY_VERSION_UNKNOWN ||
- version >= DSI_PHY_VERSION_MAX) {
- pr_err("Unsupported version: %d\n", version);
- return -ENOTSUPP;
- }
-
- phy->index = index;
- set_bit(DSI_PHY_DPHY, phy->feature_map);
-
- switch (version) {
- case DSI_PHY_VERSION_4_0:
- dsi_catalog_phy_4_0_init(phy);
- break;
- case DSI_PHY_VERSION_1_0:
- case DSI_PHY_VERSION_2_0:
- case DSI_PHY_VERSION_3_0:
- default:
- return -ENOTSUPP;
- }
-
- return rc;
-}
-
-
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
deleted file mode 100644
index e4b33c259540..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DSI_CATALOG_H_
-#define _DSI_CATALOG_H_
-
-#include "dsi_ctrl_hw.h"
-#include "dsi_phy_hw.h"
-
-/**
- * dsi_catalog_ctrl_setup() - return catalog info for dsi controller
- * @ctrl: Pointer to DSI controller hw object.
- * @version: DSI controller version.
- * @index: DSI controller instance ID.
- *
- * This function setups the catalog information in the dsi_ctrl_hw object.
- *
- * return: error code for failure and 0 for success.
- */
-int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_ctrl_version version,
- u32 index);
-
-/**
- * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware
- * @ctrl: Pointer to DSI PHY hw object.
- * @version: DSI PHY version.
- * @index: DSI PHY instance ID.
- *
- * This function setups the catalog information in the dsi_phy_hw object.
- *
- * return: error code for failure and 0 for success.
- */
-int dsi_catalog_phy_setup(struct dsi_phy_hw *phy,
- enum dsi_phy_version version,
- u32 index);
-
-/* Definitions for 4.0 PHY hardware driver */
-void dsi_phy_hw_v4_0_regulator_enable(struct dsi_phy_hw *phy,
- struct dsi_phy_per_lane_cfgs *cfg);
-void dsi_phy_hw_v4_0_regulator_disable(struct dsi_phy_hw *phy);
-void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg);
-void dsi_phy_hw_v4_0_disable(struct dsi_phy_hw *phy);
-int dsi_phy_hw_v4_0_calculate_timing_params(struct dsi_phy_hw *phy,
- struct dsi_mode_info *mode,
- struct dsi_host_common_cfg *cfg,
- struct dsi_phy_per_lane_cfgs
- *timing);
-
-/* Definitions for 1.4 controller hardware driver */
-void dsi_ctrl_hw_14_host_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *config);
-void dsi_ctrl_hw_14_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
-void dsi_ctrl_hw_14_video_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_video_engine_cfg *cfg);
-void dsi_ctrl_hw_14_set_video_timing(struct dsi_ctrl_hw *ctrl,
- struct dsi_mode_info *mode);
-
-void dsi_ctrl_hw_14_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_cmd_engine_cfg *cfg);
-
-void dsi_ctrl_hw_14_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on);
-void dsi_ctrl_hw_14_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
-
-void dsi_ctrl_hw_14_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_soft_reset(struct dsi_ctrl_hw *ctrl);
-
-void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map);
-void dsi_ctrl_hw_14_kickoff_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_info *cmd,
- u32 flags);
-
-void dsi_ctrl_hw_14_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_fifo_info *cmd,
- u32 flags);
-void dsi_ctrl_hw_14_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_trigger_command_dma(struct dsi_ctrl_hw *ctrl);
-
-void dsi_ctrl_hw_14_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes);
-void dsi_ctrl_hw_14_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes);
-void dsi_ctrl_hw_14_clear_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes);
-u32 dsi_ctrl_hw_14_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl);
-
-void dsi_ctrl_hw_14_clamp_enable(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool enable_ulps);
-
-void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool disable_ulps);
-u32 dsi_ctrl_hw_14_get_interrupt_status(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints);
-void dsi_ctrl_hw_14_enable_status_interrupts(struct dsi_ctrl_hw *ctrl,
- u32 ints);
-
-u64 dsi_ctrl_hw_14_get_error_status(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors);
-void dsi_ctrl_hw_14_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
- u64 errors);
-
-void dsi_ctrl_hw_14_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val);
-void dsi_ctrl_hw_14_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val,
- u32 stream_id);
-void dsi_ctrl_hw_14_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable);
-void dsi_ctrl_hw_14_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
- u32 stream_id);
-#endif /* _DSI_CATALOG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
deleted file mode 100644
index b5ddfbb4ef72..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DSI_CTRL_HW_H_
-#define _DSI_CTRL_HW_H_
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/bitmap.h>
-
-#include "dsi_defs.h"
-
-/**
- * Modifier flag for command transmission. If this flag is set, command
- * information is programmed to hardware and transmission is not triggered.
- * Caller should call the trigger_command_dma() to start the transmission. This
- * flag is valed for kickoff_command() and kickoff_fifo_command() operations.
- */
-#define DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER 0x1
-
-/**
- * enum dsi_ctrl_version - version of the dsi host controller
- * @DSI_CTRL_VERSION_UNKNOWN: Unknown controller version
- * @DSI_CTRL_VERSION_1_4: DSI host v1.4 controller
- * @DSI_CTRL_VERSION_2_0: DSI host v2.0 controller
- * @DSI_CTRL_VERSION_MAX: max version
- */
-enum dsi_ctrl_version {
- DSI_CTRL_VERSION_UNKNOWN,
- DSI_CTRL_VERSION_1_4,
- DSI_CTRL_VERSION_2_0,
- DSI_CTRL_VERSION_MAX
-};
-
-/**
- * enum dsi_ctrl_hw_features - features supported by dsi host controller
- * @DSI_CTRL_VIDEO_TPG: Test pattern support for video mode.
- * @DSI_CTRL_CMD_TPG: Test pattern support for command mode.
- * @DSI_CTRL_VARIABLE_REFRESH_RATE: variable panel timing
- * @DSI_CTRL_DYNAMIC_REFRESH: variable pixel clock rate
- * @DSI_CTRL_NULL_PACKET_INSERTION: NULL packet insertion
- * @DSI_CTRL_DESKEW_CALIB: Deskew calibration support
- * @DSI_CTRL_DPHY: Controller support for DPHY
- * @DSI_CTRL_CPHY: Controller support for CPHY
- * @DSI_CTRL_MAX_FEATURES:
- */
-enum dsi_ctrl_hw_features {
- DSI_CTRL_VIDEO_TPG,
- DSI_CTRL_CMD_TPG,
- DSI_CTRL_VARIABLE_REFRESH_RATE,
- DSI_CTRL_DYNAMIC_REFRESH,
- DSI_CTRL_NULL_PACKET_INSERTION,
- DSI_CTRL_DESKEW_CALIB,
- DSI_CTRL_DPHY,
- DSI_CTRL_CPHY,
- DSI_CTRL_MAX_FEATURES
-};
-
-/**
- * enum dsi_test_pattern - test pattern type
- * @DSI_TEST_PATTERN_FIXED: Test pattern is fixed, based on init value.
- * @DSI_TEST_PATTERN_INC: Incremental test pattern, base on init value.
- * @DSI_TEST_PATTERN_POLY: Pattern generated from polynomial and init val.
- * @DSI_TEST_PATTERN_MAX:
- */
-enum dsi_test_pattern {
- DSI_TEST_PATTERN_FIXED = 0,
- DSI_TEST_PATTERN_INC,
- DSI_TEST_PATTERN_POLY,
- DSI_TEST_PATTERN_MAX
-};
-
-/**
- * enum dsi_status_int_type - status interrupts generated by DSI controller
- * @DSI_CMD_MODE_DMA_DONE: Command mode DMA packets are sent out.
- * @DSI_CMD_STREAM0_FRAME_DONE: A frame of command mode stream0 is sent out.
- * @DSI_CMD_STREAM1_FRAME_DONE: A frame of command mode stream1 is sent out.
- * @DSI_CMD_STREAM2_FRAME_DONE: A frame of command mode stream2 is sent out.
- * @DSI_VIDEO_MODE_FRAME_DONE: A frame of video mode stream is sent out.
- * @DSI_BTA_DONE: A BTA is completed.
- * @DSI_CMD_FRAME_DONE: A frame of selected command mode stream is
- * sent out by MDP.
- * @DSI_DYN_REFRESH_DONE: The dynamic refresh operation has completed.
- * @DSI_DESKEW_DONE: The deskew calibration operation has completed
- * @DSI_DYN_BLANK_DMA_DONE: The dynamic blankin DMA operation has
- * completed.
- */
-enum dsi_status_int_type {
- DSI_CMD_MODE_DMA_DONE = BIT(0),
- DSI_CMD_STREAM0_FRAME_DONE = BIT(1),
- DSI_CMD_STREAM1_FRAME_DONE = BIT(2),
- DSI_CMD_STREAM2_FRAME_DONE = BIT(3),
- DSI_VIDEO_MODE_FRAME_DONE = BIT(4),
- DSI_BTA_DONE = BIT(5),
- DSI_CMD_FRAME_DONE = BIT(6),
- DSI_DYN_REFRESH_DONE = BIT(7),
- DSI_DESKEW_DONE = BIT(8),
- DSI_DYN_BLANK_DMA_DONE = BIT(9)
-};
-
-/**
- * enum dsi_error_int_type - error interrupts generated by DSI controller
- * @DSI_RDBK_SINGLE_ECC_ERR: Single bit ECC error in read packet.
- * @DSI_RDBK_MULTI_ECC_ERR: Multi bit ECC error in read packet.
- * @DSI_RDBK_CRC_ERR: CRC error in read packet.
- * @DSI_RDBK_INCOMPLETE_PKT: Incomplete read packet.
- * @DSI_PERIPH_ERROR_PKT: Error packet returned from peripheral,
- * @DSI_LP_RX_TIMEOUT: Low power reverse transmission timeout.
- * @DSI_HS_TX_TIMEOUT: High speed forward transmission timeout.
- * @DSI_BTA_TIMEOUT: BTA timeout.
- * @DSI_PLL_UNLOCK: PLL has unlocked.
- * @DSI_DLN0_ESC_ENTRY_ERR: Incorrect LP Rx escape entry.
- * @DSI_DLN0_ESC_SYNC_ERR: LP Rx data is not byte aligned.
- * @DSI_DLN0_LP_CONTROL_ERR: Incorrect LP Rx state sequence.
- * @DSI_PENDING_HS_TX_TIMEOUT: Pending High-speed transfer timeout.
- * @DSI_INTERLEAVE_OP_CONTENTION: Interleave operation contention.
- * @DSI_CMD_DMA_FIFO_UNDERFLOW: Command mode DMA FIFO underflow.
- * @DSI_CMD_MDP_FIFO_UNDERFLOW: Command MDP FIFO underflow (failed to
- * receive one complete line from MDP).
- * @DSI_DLN0_HS_FIFO_OVERFLOW: High speed FIFO for data lane 0 overflows.
- * @DSI_DLN1_HS_FIFO_OVERFLOW: High speed FIFO for data lane 1 overflows.
- * @DSI_DLN2_HS_FIFO_OVERFLOW: High speed FIFO for data lane 2 overflows.
- * @DSI_DLN3_HS_FIFO_OVERFLOW: High speed FIFO for data lane 3 overflows.
- * @DSI_DLN0_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 0 underflows.
- * @DSI_DLN1_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 1 underflows.
- * @DSI_DLN2_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 2 underflows.
- * @DSI_DLN3_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 3 undeflows.
- * @DSI_DLN0_LP0_CONTENTION: PHY level contention while lane 0 is low.
- * @DSI_DLN1_LP0_CONTENTION: PHY level contention while lane 1 is low.
- * @DSI_DLN2_LP0_CONTENTION: PHY level contention while lane 2 is low.
- * @DSI_DLN3_LP0_CONTENTION: PHY level contention while lane 3 is low.
- * @DSI_DLN0_LP1_CONTENTION: PHY level contention while lane 0 is high.
- * @DSI_DLN1_LP1_CONTENTION: PHY level contention while lane 1 is high.
- * @DSI_DLN2_LP1_CONTENTION: PHY level contention while lane 2 is high.
- * @DSI_DLN3_LP1_CONTENTION: PHY level contention while lane 3 is high.
- */
-enum dsi_error_int_type {
- DSI_RDBK_SINGLE_ECC_ERR = BIT(0),
- DSI_RDBK_MULTI_ECC_ERR = BIT(1),
- DSI_RDBK_CRC_ERR = BIT(2),
- DSI_RDBK_INCOMPLETE_PKT = BIT(3),
- DSI_PERIPH_ERROR_PKT = BIT(4),
- DSI_LP_RX_TIMEOUT = BIT(5),
- DSI_HS_TX_TIMEOUT = BIT(6),
- DSI_BTA_TIMEOUT = BIT(7),
- DSI_PLL_UNLOCK = BIT(8),
- DSI_DLN0_ESC_ENTRY_ERR = BIT(9),
- DSI_DLN0_ESC_SYNC_ERR = BIT(10),
- DSI_DLN0_LP_CONTROL_ERR = BIT(11),
- DSI_PENDING_HS_TX_TIMEOUT = BIT(12),
- DSI_INTERLEAVE_OP_CONTENTION = BIT(13),
- DSI_CMD_DMA_FIFO_UNDERFLOW = BIT(14),
- DSI_CMD_MDP_FIFO_UNDERFLOW = BIT(15),
- DSI_DLN0_HS_FIFO_OVERFLOW = BIT(16),
- DSI_DLN1_HS_FIFO_OVERFLOW = BIT(17),
- DSI_DLN2_HS_FIFO_OVERFLOW = BIT(18),
- DSI_DLN3_HS_FIFO_OVERFLOW = BIT(19),
- DSI_DLN0_HS_FIFO_UNDERFLOW = BIT(20),
- DSI_DLN1_HS_FIFO_UNDERFLOW = BIT(21),
- DSI_DLN2_HS_FIFO_UNDERFLOW = BIT(22),
- DSI_DLN3_HS_FIFO_UNDERFLOW = BIT(23),
- DSI_DLN0_LP0_CONTENTION = BIT(24),
- DSI_DLN1_LP0_CONTENTION = BIT(25),
- DSI_DLN2_LP0_CONTENTION = BIT(26),
- DSI_DLN3_LP0_CONTENTION = BIT(27),
- DSI_DLN0_LP1_CONTENTION = BIT(28),
- DSI_DLN1_LP1_CONTENTION = BIT(29),
- DSI_DLN2_LP1_CONTENTION = BIT(30),
- DSI_DLN3_LP1_CONTENTION = BIT(31),
-};
-
-/**
- * struct dsi_ctrl_cmd_dma_info - command buffer information
- * @offset: IOMMU VA for command buffer address.
- * @length: Length of the command buffer.
- * @en_broadcast: Enable broadcast mode if set to true.
- * @is_master: Is master in broadcast mode.
- * @use_lpm: Use low power mode for command transmission.
- */
-struct dsi_ctrl_cmd_dma_info {
- u32 offset;
- u32 length;
- bool en_broadcast;
- bool is_master;
- bool use_lpm;
-};
-
-/**
- * struct dsi_ctrl_cmd_dma_fifo_info - command payload tp be sent using FIFO
- * @command: VA for command buffer.
- * @size: Size of the command buffer.
- * @en_broadcast: Enable broadcast mode if set to true.
- * @is_master: Is master in broadcast mode.
- * @use_lpm: Use low power mode for command transmission.
- */
-struct dsi_ctrl_cmd_dma_fifo_info {
- u32 *command;
- u32 size;
- bool en_broadcast;
- bool is_master;
- bool use_lpm;
-};
-
-struct dsi_ctrl_hw;
-
-/**
- * struct dsi_ctrl_hw_ops - operations supported by dsi host hardware
- */
-struct dsi_ctrl_hw_ops {
-
- /**
- * host_setup() - Setup DSI host configuration
- * @ctrl: Pointer to controller host hardware.
- * @config: Configuration for DSI host controller
- */
- void (*host_setup)(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *config);
-
- /**
- * video_engine_en() - enable DSI video engine
- * @ctrl: Pointer to controller host hardware.
- * @on: Enable/disabel video engine.
- */
- void (*video_engine_en)(struct dsi_ctrl_hw *ctrl, bool on);
-
- /**
- * video_engine_setup() - Setup dsi host controller for video mode
- * @ctrl: Pointer to controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Video mode configuration.
- *
- * Set up DSI video engine with a specific configuration. Controller and
- * video engine are not enabled as part of this function.
- */
- void (*video_engine_setup)(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_video_engine_cfg *cfg);
-
- /**
- * set_video_timing() - set up the timing for video frame
- * @ctrl: Pointer to controller host hardware.
- * @mode: Video mode information.
- *
- * Set up the video timing parameters for the DSI video mode operation.
- */
- void (*set_video_timing)(struct dsi_ctrl_hw *ctrl,
- struct dsi_mode_info *mode);
-
- /**
- * cmd_engine_setup() - setup dsi host controller for command mode
- * @ctrl: Pointer to the controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Command mode configuration.
- *
- * Setup DSI CMD engine with a specific configuration. Controller and
- * command engine are not enabled as part of this function.
- */
- void (*cmd_engine_setup)(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_cmd_engine_cfg *cfg);
-
- /**
- * ctrl_en() - enable DSI controller engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: turn on/off the DSI controller engine.
- */
- void (*ctrl_en)(struct dsi_ctrl_hw *ctrl, bool on);
-
- /**
- * cmd_engine_en() - enable DSI controller command engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: Turn on/off the DSI command engine.
- */
- void (*cmd_engine_en)(struct dsi_ctrl_hw *ctrl, bool on);
-
- /**
- * phy_sw_reset() - perform a soft reset on the PHY.
- * @ctrl: Pointer to the controller host hardware.
- */
- void (*phy_sw_reset)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * soft_reset() - perform a soft reset on DSI controller
- * @ctrl: Pointer to the controller host hardware.
- *
- * The video, command and controller engines will be disable before the
- * reset is triggered. These engines will not be enabled after the reset
- * is complete. Caller must re-enable the engines.
- *
- * If the reset is done while MDP timing engine is turned on, the video
- * enigne should be re-enabled only during the vertical blanking time.
- */
- void (*soft_reset)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * setup_lane_map() - setup mapping between logical and physical lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lane_map: Structure defining the mapping between DSI logical
- * lanes and physical lanes.
- */
- void (*setup_lane_map)(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map);
-
- /**
- * kickoff_command() - transmits commands stored in memory
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware is programmed with address and size of the
- * command buffer. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
- void (*kickoff_command)(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_info *cmd,
- u32 flags);
-
- /**
- * kickoff_fifo_command() - transmits a command using FIFO in dsi
- * hardware.
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware FIFO is programmed with command header and
- * payload. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
- void (*kickoff_fifo_command)(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_fifo_info *cmd,
- u32 flags);
-
- void (*reset_cmd_fifo)(struct dsi_ctrl_hw *ctrl);
- /**
- * trigger_command_dma() - trigger transmission of command buffer.
- * @ctrl: Pointer to the controller host hardware.
- *
- * This trigger can be only used if there was a prior call to
- * kickoff_command() of kickoff_fifo_command() with
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag.
- */
- void (*trigger_command_dma)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * get_cmd_read_data() - get data read from the peripheral
- * @ctrl: Pointer to the controller host hardware.
- * @rd_buf: Buffer where data will be read into.
- * @total_read_len: Number of bytes to read.
- */
- u32 (*get_cmd_read_data)(struct dsi_ctrl_hw *ctrl,
- u8 *rd_buf,
- u32 total_read_len);
-
- /**
- * ulps_request() - request ulps entry for specified lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
- * to enter ULPS.
- *
- * Caller should check if lanes are in ULPS mode by calling
- * get_lanes_in_ulps() operation.
- */
- void (*ulps_request)(struct dsi_ctrl_hw *ctrl, u32 lanes);
-
- /**
- * ulps_exit() - exit ULPS on specified lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
- * to exit ULPS.
- *
- * Caller should check if lanes are in active mode by calling
- * get_lanes_in_ulps() operation.
- */
- void (*ulps_exit)(struct dsi_ctrl_hw *ctrl, u32 lanes);
-
- /**
- * clear_ulps_request() - clear ulps request once all lanes are active
- * @ctrl: Pointer to controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes).
- *
- * ULPS request should be cleared after the lanes have exited ULPS.
- */
- void (*clear_ulps_request)(struct dsi_ctrl_hw *ctrl, u32 lanes);
-
- /**
- * get_lanes_in_ulps() - returns the list of lanes in ULPS mode
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS
- * state. If 0 is returned, all the lanes are active.
- *
- * Return: List of lanes in ULPS state.
- */
- u32 (*get_lanes_in_ulps)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * clamp_enable() - enable DSI clamps to keep PHY driving a stable link
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes which need to be clamped.
- * @enable_ulps: TODO:??
- */
- void (*clamp_enable)(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool enable_ulps);
-
- /**
- * clamp_disable() - disable DSI clamps
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes which need to have clamps released.
- * @disable_ulps: TODO:??
- */
- void (*clamp_disable)(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool disable_ulps);
-
- /**
- * get_interrupt_status() - returns the interrupt status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of interrupts(enum dsi_status_int_type) that
- * are active. This list does not include any error interrupts. Caller
- * should call get_error_status for error interrupts.
- *
- * Return: List of active interrupts.
- */
- u32 (*get_interrupt_status)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * clear_interrupt_status() - clears the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be cleared.
- */
- void (*clear_interrupt_status)(struct dsi_ctrl_hw *ctrl, u32 ints);
-
- /**
- * enable_status_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set ints to 0.
- */
- void (*enable_status_interrupts)(struct dsi_ctrl_hw *ctrl, u32 ints);
-
- /**
- * get_error_status() - returns the error status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of errors(enum dsi_error_int_type) that are
- * active. This list does not include any status interrupts. Caller
- * should call get_interrupt_status for status interrupts.
- *
- * Return: List of active error interrupts.
- */
- u64 (*get_error_status)(struct dsi_ctrl_hw *ctrl);
-
- /**
- * clear_error_status() - clears the specified errors
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be cleared.
- */
- void (*clear_error_status)(struct dsi_ctrl_hw *ctrl, u64 errors);
-
- /**
- * enable_error_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set errors to 0.
- */
- void (*enable_error_interrupts)(struct dsi_ctrl_hw *ctrl, u64 errors);
-
- /**
- * video_test_pattern_setup() - setup test pattern engine for video mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- */
- void (*video_test_pattern_setup)(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val);
-
- /**
- * cmd_test_pattern_setup() - setup test patttern engine for cmd mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- * @stream_id: Stream Id on which packets are generated.
- */
- void (*cmd_test_pattern_setup)(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val,
- u32 stream_id);
-
- /**
- * test_pattern_enable() - enable test pattern engine
- * @ctrl: Pointer to the controller host hardware.
- * @enable: Enable/Disable test pattern engine.
- */
- void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable);
-
- /**
- * trigger_cmd_test_pattern() - trigger a command mode frame update with
- * test pattern
- * @ctrl: Pointer to the controller host hardware.
- * @stream_id: Stream on which frame update is sent.
- */
- void (*trigger_cmd_test_pattern)(struct dsi_ctrl_hw *ctrl,
- u32 stream_id);
-};
-
-/*
- * struct dsi_ctrl_hw - DSI controller hardware object specific to an instance
- * @base: VA for the DSI controller base address.
- * @length: Length of the DSI controller register map.
- * @index: Instance ID of the controller.
- * @feature_map: Features supported by the DSI controller.
- * @ops: Function pointers to the operations supported by the
- * controller.
- */
-struct dsi_ctrl_hw {
- void __iomem *base;
- u32 length;
- void __iomem *mmss_misc_base;
- u32 mmss_misc_length;
- u32 index;
-
- /* features */
- DECLARE_BITMAP(feature_map, DSI_CTRL_MAX_FEATURES);
- struct dsi_ctrl_hw_ops ops;
-
- /* capabilities */
- u32 supported_interrupts;
- u64 supported_errors;
-};
-
-#endif /* _DSI_CTRL_HW_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
deleted file mode 100644
index 8326024f76ec..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
+++ /dev/null
@@ -1,1321 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "dsi-hw:" fmt
-#include <linux/delay.h>
-
-#include "dsi_ctrl_hw.h"
-#include "dsi_ctrl_reg_1_4.h"
-#include "dsi_hw.h"
-
-#define MMSS_MISC_CLAMP_REG_OFF 0x0014
-
-/* Unsupported formats default to RGB888 */
-static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
- 0x6, 0x7, 0x8, 0x8, 0x0, 0x3, 0x4 };
-static const u8 video_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
- 0x0, 0x1, 0x2, 0x3, 0x3, 0x3, 0x3 };
-
-
-/**
- * dsi_setup_trigger_controls() - setup dsi trigger configurations
- * @ctrl: Pointer to the controller host hardware.
- * @cfg: DSI host configuration that is common to both video and
- * command modes.
- */
-static void dsi_setup_trigger_controls(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *cfg)
-{
- u32 reg = 0;
- const u8 trigger_map[DSI_TRIGGER_MAX] = {
- 0x0, 0x2, 0x1, 0x4, 0x5, 0x6 };
-
- reg |= (cfg->te_mode == DSI_TE_ON_EXT_PIN) ? BIT(31) : 0;
- reg |= (trigger_map[cfg->dma_cmd_trigger] & 0x7);
- reg |= (trigger_map[cfg->mdp_cmd_trigger] & 0x7) << 4;
- DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
-}
-
-/**
- * dsi_ctrl_hw_14_host_setup() - setup dsi host configuration
- * @ctrl: Pointer to the controller host hardware.
- * @cfg: DSI host configuration that is common to both video and
- * command modes.
- */
-void dsi_ctrl_hw_14_host_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *cfg)
-{
- u32 reg_value = 0;
-
- dsi_setup_trigger_controls(ctrl, cfg);
-
- /* Setup clocking timing controls */
- reg_value = ((cfg->t_clk_post & 0x3F) << 8);
- reg_value |= (cfg->t_clk_pre & 0x3F);
- DSI_W32(ctrl, DSI_CLKOUT_TIMING_CTRL, reg_value);
-
- /* EOT packet control */
- reg_value = cfg->append_tx_eot ? 1 : 0;
- reg_value |= (cfg->ignore_rx_eot ? (1 << 4) : 0);
- DSI_W32(ctrl, DSI_EOT_PACKET_CTRL, reg_value);
-
- /* Turn on dsi clocks */
- DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F);
-
- /* Setup DSI control register */
- reg_value = 0;
- reg_value |= (cfg->en_crc_check ? BIT(24) : 0);
- reg_value |= (cfg->en_ecc_check ? BIT(20) : 0);
- reg_value |= BIT(8); /* Clock lane */
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(7) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(6) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(5) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(4) : 0);
-
- DSI_W32(ctrl, DSI_CTRL, reg_value);
-
- /* Enable Timing double buffering */
- DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
-
- pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index);
-}
-
-/**
- * phy_sw_reset() - perform a soft reset on the PHY.
- * @ctrl: Pointer to the controller host hardware.
- */
-void dsi_ctrl_hw_14_phy_sw_reset(struct dsi_ctrl_hw *ctrl)
-{
- DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x1);
- udelay(1000);
- DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x0);
- udelay(100);
-
- pr_debug("[DSI_%d] phy sw reset done\n", ctrl->index);
-}
-
-/**
- * soft_reset() - perform a soft reset on DSI controller
- * @ctrl: Pointer to the controller host hardware.
- *
- * The video, command and controller engines will be disable before the
- * reset is triggered. These engines will not be enabled after the reset
- * is complete. Caller must re-enable the engines.
- *
- * If the reset is done while MDP timing engine is turned on, the video
- * enigne should be re-enabled only during the vertical blanking time.
- */
-void dsi_ctrl_hw_14_soft_reset(struct dsi_ctrl_hw *ctrl)
-{
- u32 reg = 0;
- u32 reg_ctrl = 0;
-
- /* Clear DSI_EN, VIDEO_MODE_EN, CMD_MODE_EN */
- reg_ctrl = DSI_R32(ctrl, DSI_CTRL);
- DSI_W32(ctrl, DSI_CTRL, reg_ctrl & ~0x7);
-
- /* Force enable PCLK, BYTECLK, AHBM_HCLK */
- reg = DSI_R32(ctrl, DSI_CLK_CTRL);
- reg |= 0x23F;
- DSI_W32(ctrl, DSI_CLK_CTRL, reg);
-
- /* Trigger soft reset */
- DSI_W32(ctrl, DSI_SOFT_RESET, 0x1);
- udelay(1);
- DSI_W32(ctrl, DSI_SOFT_RESET, 0x0);
-
- /* Disable force clock on */
- reg &= ~(BIT(20) | BIT(11));
- DSI_W32(ctrl, DSI_CLK_CTRL, reg);
-
- /* Re-enable DSI controller */
- DSI_W32(ctrl, DSI_CTRL, reg_ctrl);
- pr_debug("[DSI_%d] ctrl soft reset done\n", ctrl->index);
-}
-
-/**
- * set_video_timing() - set up the timing for video frame
- * @ctrl: Pointer to controller host hardware.
- * @mode: Video mode information.
- *
- * Set up the video timing parameters for the DSI video mode operation.
- */
-void dsi_ctrl_hw_14_set_video_timing(struct dsi_ctrl_hw *ctrl,
- struct dsi_mode_info *mode)
-{
- u32 reg = 0;
- u32 hs_start = 0;
- u32 hs_end, active_h_start, active_h_end, h_total;
- u32 vs_start = 0, vs_end = 0;
- u32 vpos_start = 0, vpos_end, active_v_start, active_v_end, v_total;
-
- hs_end = mode->h_sync_width;
- active_h_start = mode->h_sync_width + mode->h_back_porch;
- active_h_end = active_h_start + mode->h_active;
- h_total = (mode->h_sync_width + mode->h_back_porch + mode->h_active +
- mode->h_front_porch) - 1;
-
- vpos_end = mode->v_sync_width;
- active_v_start = mode->v_sync_width + mode->v_back_porch;
- active_v_end = active_v_start + mode->v_active;
- v_total = (mode->v_sync_width + mode->v_back_porch + mode->v_active +
- mode->v_front_porch) - 1;
-
- reg = ((active_h_end & 0xFFFF) << 16) | (active_h_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_H, reg);
-
- reg = ((active_v_end & 0xFFFF) << 16) | (active_v_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_V, reg);
-
- reg = ((v_total & 0xFFFF) << 16) | (h_total & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_TOTAL, reg);
-
- reg = ((hs_end & 0xFFFF) << 16) | (hs_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_HSYNC, reg);
-
- reg = ((vs_end & 0xFFFF) << 16) | (vs_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC, reg);
-
- reg = ((vpos_end & 0xFFFF) << 16) | (vpos_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC_VPOS, reg);
-
- /* TODO: HS TIMER value? */
- DSI_W32(ctrl, DSI_HS_TIMER_CTRL, 0x3FD08);
- DSI_W32(ctrl, DSI_MISR_VIDEO_CTRL, 0x10100);
- DSI_W32(ctrl, DSI_DSI_TIMING_FLUSH, 0x1);
- pr_debug("[DSI_%d] ctrl video parameters updated\n", ctrl->index);
-}
-
-/**
- * video_engine_setup() - Setup dsi host controller for video mode
- * @ctrl: Pointer to controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Video mode configuration.
- *
- * Set up DSI video engine with a specific configuration. Controller and
- * video engine are not enabled as part of this function.
- */
-void dsi_ctrl_hw_14_video_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_video_engine_cfg *cfg)
-{
- u32 reg = 0;
-
- reg |= (cfg->last_line_interleave_en ? BIT(31) : 0);
- reg |= (cfg->pulse_mode_hsa_he ? BIT(28) : 0);
- reg |= (cfg->hfp_lp11_en ? BIT(24) : 0);
- reg |= (cfg->hbp_lp11_en ? BIT(20) : 0);
- reg |= (cfg->hsa_lp11_en ? BIT(16) : 0);
- reg |= (cfg->eof_bllp_lp11_en ? BIT(15) : 0);
- reg |= (cfg->bllp_lp11_en ? BIT(12) : 0);
- reg |= (cfg->traffic_mode & 0x3) << 8;
- reg |= (cfg->vc_id & 0x3);
- reg |= (video_mode_format_map[common_cfg->dst_format] & 0x3) << 4;
- DSI_W32(ctrl, DSI_VIDEO_MODE_CTRL, reg);
-
- reg = (common_cfg->swap_mode & 0x7) << 12;
- reg |= (common_cfg->bit_swap_red ? BIT(0) : 0);
- reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
- reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
- DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
-
- pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
-}
-
-/**
- * cmd_engine_setup() - setup dsi host controller for command mode
- * @ctrl: Pointer to the controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Command mode configuration.
- *
- * Setup DSI CMD engine with a specific configuration. Controller and
- * command engine are not enabled as part of this function.
- */
-void dsi_ctrl_hw_14_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_cmd_engine_cfg *cfg)
-{
- u32 reg = 0;
-
- reg = (cfg->max_cmd_packets_interleave & 0xF) << 20;
- reg |= (common_cfg->bit_swap_red ? BIT(4) : 0);
- reg |= (common_cfg->bit_swap_green ? BIT(8) : 0);
- reg |= (common_cfg->bit_swap_blue ? BIT(12) : 0);
- reg |= cmd_mode_format_map[common_cfg->dst_format];
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL, reg);
-
- reg = cfg->wr_mem_start & 0xFF;
- reg |= (cfg->wr_mem_continue & 0xFF) << 8;
- reg |= (cfg->insert_dcs_command ? BIT(16) : 0);
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL, reg);
-
- pr_debug("[DSI_%d] Cmd engine setup done\n", ctrl->index);
-}
-
-/**
- * video_engine_en() - enable DSI video engine
- * @ctrl: Pointer to controller host hardware.
- * @on: Enable/disabel video engine.
- */
-void dsi_ctrl_hw_14_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear VIDEO_MODE_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(1);
- else
- reg &= ~BIT(1);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] Video engine = %d\n", ctrl->index, on);
-}
-
-/**
- * ctrl_en() - enable DSI controller engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: turn on/off the DSI controller engine.
- */
-void dsi_ctrl_hw_14_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear DSI_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(0);
- else
- reg &= ~BIT(0);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] Controller engine = %d\n", ctrl->index, on);
-}
-
-/**
- * cmd_engine_en() - enable DSI controller command engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: Turn on/off the DSI command engine.
- */
-void dsi_ctrl_hw_14_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear CMD_MODE_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(2);
- else
- reg &= ~BIT(2);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] command engine = %d\n", ctrl->index, on);
-}
-
-/**
- * setup_lane_map() - setup mapping between logical and physical lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lane_map: Structure defining the mapping between DSI logical
- * lanes and physical lanes.
- */
-void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map)
-{
- u32 reg_value = 0;
- u32 lane_number = ((lane_map->physical_lane0 * 1000)+
- (lane_map->physical_lane1 * 100) +
- (lane_map->physical_lane2 * 10) +
- (lane_map->physical_lane3));
-
- if (lane_number == 123)
- reg_value = 0;
- else if (lane_number == 3012)
- reg_value = 1;
- else if (lane_number == 2301)
- reg_value = 2;
- else if (lane_number == 1230)
- reg_value = 3;
- else if (lane_number == 321)
- reg_value = 4;
- else if (lane_number == 1032)
- reg_value = 5;
- else if (lane_number == 2103)
- reg_value = 6;
- else if (lane_number == 3210)
- reg_value = 7;
-
- DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, reg_value);
-
- pr_debug("[DSI_%d] Lane swap setup complete\n", ctrl->index);
-}
-
-/**
- * kickoff_command() - transmits commands stored in memory
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware is programmed with address and size of the
- * command buffer. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
-void dsi_ctrl_hw_14_kickoff_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_info *cmd,
- u32 flags)
-{
- u32 reg = 0;
-
- /*Set BROADCAST_EN and EMBEDDED_MODE */
- reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
- if (cmd->en_broadcast)
- reg |= BIT(31);
- else
- reg &= ~BIT(31);
-
- if (cmd->is_master)
- reg |= BIT(30);
- else
- reg &= ~BIT(30);
-
- if (cmd->use_lpm)
- reg |= BIT(26);
- else
- reg &= ~BIT(26);
-
- reg |= BIT(28);
- DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
-
- DSI_W32(ctrl, DSI_DMA_CMD_OFFSET, cmd->offset);
- DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->length & 0xFFFFFF));
-
- /* wait for writes to complete before kick off */
- wmb();
-
- if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
-}
-
-/**
- * kickoff_fifo_command() - transmits a command using FIFO in dsi
- * hardware.
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware FIFO is programmed with command header and
- * payload. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
-void dsi_ctrl_hw_14_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_fifo_info *cmd,
- u32 flags)
-{
- u32 reg = 0, i = 0;
- u32 *ptr = cmd->command;
- /*
- * Set CMD_DMA_TPG_EN, TPG_DMA_FIFO_MODE and
- * CMD_DMA_PATTERN_SEL = custom pattern stored in TPG DMA FIFO
- */
- reg = (BIT(1) | BIT(2) | (0x3 << 16));
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- /*
- * Program the FIFO with command buffer. Hardware requires an extra
- * DWORD (set to zero) if the length of command buffer is odd DWORDS.
- */
- for (i = 0; i < cmd->size; i += 4) {
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, *ptr);
- ptr++;
- }
-
- if ((cmd->size / 4) & 0x1)
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, 0);
-
- /*Set BROADCAST_EN and EMBEDDED_MODE */
- reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
- if (cmd->en_broadcast)
- reg |= BIT(31);
- else
- reg &= ~BIT(31);
-
- if (cmd->is_master)
- reg |= BIT(30);
- else
- reg &= ~BIT(30);
-
- if (cmd->use_lpm)
- reg |= BIT(26);
- else
- reg &= ~BIT(26);
-
- reg |= BIT(28);
-
- DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
-
- DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->size & 0xFFFFFFFF));
- /* Finish writes before command trigger */
- wmb();
-
- if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
-
- pr_debug("[DSI_%d]size=%d, trigger = %d\n",
- ctrl->index, cmd->size,
- (flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER) ? false : true);
-}
-
-void dsi_ctrl_hw_14_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl)
-{
- /* disable cmd dma tpg */
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, 0x0);
-
- DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x1);
- udelay(1);
- DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x0);
-}
-
-/**
- * trigger_command_dma() - trigger transmission of command buffer.
- * @ctrl: Pointer to the controller host hardware.
- *
- * This trigger can be only used if there was a prior call to
- * kickoff_command() of kickoff_fifo_command() with
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag.
- */
-void dsi_ctrl_hw_14_trigger_command_dma(struct dsi_ctrl_hw *ctrl)
-{
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
- pr_debug("[DSI_%d] CMD DMA triggered\n", ctrl->index);
-}
-
-/**
- * get_cmd_read_data() - get data read from the peripheral
- * @ctrl: Pointer to the controller host hardware.
- * @rd_buf: Buffer where data will be read into.
- * @total_read_len: Number of bytes to read.
- *
- * return: number of bytes read.
- */
-u32 dsi_ctrl_hw_14_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
- u8 *rd_buf,
- u32 read_offset,
- u32 total_read_len)
-{
- u32 *lp, *temp, data;
- int i, j = 0, cnt;
- u32 read_cnt;
- u32 rx_byte = 0;
- u32 repeated_bytes = 0;
- u8 reg[16];
- u32 pkt_size = 0;
- int buf_offset = read_offset;
-
- lp = (u32 *)rd_buf;
- temp = (u32 *)reg;
- cnt = (rx_byte + 3) >> 2;
-
- if (cnt > 4)
- cnt = 4;
-
- if (rx_byte == 4)
- read_cnt = 4;
- else
- read_cnt = pkt_size + 6;
-
- if (read_cnt > 16) {
- int bytes_shifted;
-
- bytes_shifted = read_cnt - 16;
- repeated_bytes = buf_offset - bytes_shifted;
- }
-
- for (i = cnt - 1; i >= 0; i--) {
- data = DSI_R32(ctrl, DSI_RDBK_DATA0 + i*4);
- *temp++ = ntohl(data);
- }
-
- for (i = repeated_bytes; i < 16; i++)
- rd_buf[j++] = reg[i];
-
- pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, j);
- return j;
-}
-/**
- * ulps_request() - request ulps entry for specified lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
- * to enter ULPS.
- *
- * Caller should check if lanes are in ULPS mode by calling
- * get_lanes_in_ulps() operation.
- */
-void dsi_ctrl_hw_14_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes)
-{
- u32 reg = 0;
-
- if (lanes & DSI_CLOCK_LANE)
- reg = BIT(4);
- if (lanes & DSI_DATA_LANE_0)
- reg |= BIT(0);
- if (lanes & DSI_DATA_LANE_1)
- reg |= BIT(1);
- if (lanes & DSI_DATA_LANE_2)
- reg |= BIT(2);
- if (lanes & DSI_DATA_LANE_3)
- reg |= BIT(3);
-
- DSI_W32(ctrl, DSI_LANE_CTRL, reg);
-
- pr_debug("[DSI_%d] ULPS requested for lanes 0x%x\n", ctrl->index,
- lanes);
-}
-
-/**
- * ulps_exit() - exit ULPS on specified lanes
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
- * to exit ULPS.
- *
- * Caller should check if lanes are in active mode by calling
- * get_lanes_in_ulps() operation.
- */
-void dsi_ctrl_hw_14_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes)
-{
- u32 reg = 0;
-
- reg = DSI_R32(ctrl, DSI_LANE_CTRL);
- if (lanes & DSI_CLOCK_LANE)
- reg |= BIT(12);
- if (lanes & DSI_DATA_LANE_0)
- reg |= BIT(8);
- if (lanes & DSI_DATA_LANE_1)
- reg |= BIT(9);
- if (lanes & DSI_DATA_LANE_2)
- reg |= BIT(10);
- if (lanes & DSI_DATA_LANE_3)
- reg |= BIT(11);
-
- DSI_W32(ctrl, DSI_LANE_CTRL, reg);
-
- pr_debug("[DSI_%d] ULPS exit request for lanes=0x%x\n",
- ctrl->index, lanes);
-}
-
-/**
- * clear_ulps_request() - clear ulps request once all lanes are active
- * @ctrl: Pointer to controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes).
- *
- * ULPS request should be cleared after the lanes have exited ULPS.
- */
-void dsi_ctrl_hw_14_clear_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes)
-{
- u32 reg = 0;
-
- reg = DSI_R32(ctrl, DSI_LANE_CTRL);
- reg &= ~BIT(4); /* clock lane */
- if (lanes & DSI_DATA_LANE_0)
- reg &= ~BIT(0);
- if (lanes & DSI_DATA_LANE_1)
- reg &= ~BIT(1);
- if (lanes & DSI_DATA_LANE_2)
- reg &= ~BIT(2);
- if (lanes & DSI_DATA_LANE_3)
- reg &= ~BIT(3);
-
- DSI_W32(ctrl, DSI_LANE_CTRL, reg);
- /*
- * HPG recommends separate writes for clearing ULPS_REQUEST and
- * ULPS_EXIT.
- */
- DSI_W32(ctrl, DSI_LANE_CTRL, 0x0);
-
- pr_debug("[DSI_%d] ULPS request cleared\n", ctrl->index);
-}
-
-/**
- * get_lanes_in_ulps() - returns the list of lanes in ULPS mode
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS
- * state. If 0 is returned, all the lanes are active.
- *
- * Return: List of lanes in ULPS state.
- */
-u32 dsi_ctrl_hw_14_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl)
-{
- u32 reg = 0;
- u32 lanes = 0;
-
- reg = DSI_R32(ctrl, DSI_LANE_STATUS);
- if (!(reg & BIT(8)))
- lanes |= DSI_DATA_LANE_0;
- if (!(reg & BIT(9)))
- lanes |= DSI_DATA_LANE_1;
- if (!(reg & BIT(10)))
- lanes |= DSI_DATA_LANE_2;
- if (!(reg & BIT(11)))
- lanes |= DSI_DATA_LANE_3;
- if (!(reg & BIT(12)))
- lanes |= DSI_CLOCK_LANE;
-
- pr_debug("[DSI_%d] lanes in ulps = 0x%x\n", ctrl->index, lanes);
- return lanes;
-}
-
-/**
- * clamp_enable() - enable DSI clamps to keep PHY driving a stable link
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes which need to be clamped.
- * @enable_ulps: TODO:??
- */
-void dsi_ctrl_hw_14_clamp_enable(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool enable_ulps)
-{
- u32 clamp_reg = 0;
- u32 bit_shift = 0;
- u32 reg = 0;
-
- if (ctrl->index == 1)
- bit_shift = 16;
-
- if (lanes & DSI_CLOCK_LANE) {
- clamp_reg |= BIT(9);
- if (enable_ulps)
- clamp_reg |= BIT(8);
- }
-
- if (lanes & DSI_DATA_LANE_0) {
- clamp_reg |= BIT(7);
- if (enable_ulps)
- clamp_reg |= BIT(6);
- }
-
- if (lanes & DSI_DATA_LANE_1) {
- clamp_reg |= BIT(5);
- if (enable_ulps)
- clamp_reg |= BIT(4);
- }
-
- if (lanes & DSI_DATA_LANE_2) {
- clamp_reg |= BIT(3);
- if (enable_ulps)
- clamp_reg |= BIT(2);
- }
-
- if (lanes & DSI_DATA_LANE_3) {
- clamp_reg |= BIT(1);
- if (enable_ulps)
- clamp_reg |= BIT(0);
- }
-
- clamp_reg |= BIT(15); /* Enable clamp */
-
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg |= (clamp_reg << bit_shift);
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
-
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg |= BIT(30);
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
- pr_debug("[DSI_%d] Clamps enabled for lanes=0x%x\n", ctrl->index,
- lanes);
-}
-
-/**
- * clamp_disable() - disable DSI clamps
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes which need to have clamps released.
- * @disable_ulps: TODO:??
- */
-void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl,
- u32 lanes,
- bool disable_ulps)
-{
- u32 clamp_reg = 0;
- u32 bit_shift = 0;
- u32 reg = 0;
-
- if (ctrl->index == 1)
- bit_shift = 16;
-
- if (lanes & DSI_CLOCK_LANE) {
- clamp_reg |= BIT(9);
- if (disable_ulps)
- clamp_reg |= BIT(8);
- }
-
- if (lanes & DSI_DATA_LANE_0) {
- clamp_reg |= BIT(7);
- if (disable_ulps)
- clamp_reg |= BIT(6);
- }
-
- if (lanes & DSI_DATA_LANE_1) {
- clamp_reg |= BIT(5);
- if (disable_ulps)
- clamp_reg |= BIT(4);
- }
-
- if (lanes & DSI_DATA_LANE_2) {
- clamp_reg |= BIT(3);
- if (disable_ulps)
- clamp_reg |= BIT(2);
- }
-
- if (lanes & DSI_DATA_LANE_3) {
- clamp_reg |= BIT(1);
- if (disable_ulps)
- clamp_reg |= BIT(0);
- }
-
- clamp_reg |= BIT(15); /* Enable clamp */
- clamp_reg <<= bit_shift;
-
- /* Disable PHY reset skip */
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg &= ~BIT(30);
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg &= ~(clamp_reg);
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
- pr_debug("[DSI_%d] Disable clamps for lanes=%d\n", ctrl->index, lanes);
-}
-
-/**
- * get_interrupt_status() - returns the interrupt status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of interrupts(enum dsi_status_int_type) that
- * are active. This list does not include any error interrupts. Caller
- * should call get_error_status for error interrupts.
- *
- * Return: List of active interrupts.
- */
-u32 dsi_ctrl_hw_14_get_interrupt_status(struct dsi_ctrl_hw *ctrl)
-{
- u32 reg = 0;
- u32 ints = 0;
-
- reg = DSI_R32(ctrl, DSI_INT_CTRL);
-
- if (reg & BIT(0))
- ints |= DSI_CMD_MODE_DMA_DONE;
- if (reg & BIT(8))
- ints |= DSI_CMD_FRAME_DONE;
- if (reg & BIT(10))
- ints |= DSI_CMD_STREAM0_FRAME_DONE;
- if (reg & BIT(12))
- ints |= DSI_CMD_STREAM1_FRAME_DONE;
- if (reg & BIT(14))
- ints |= DSI_CMD_STREAM2_FRAME_DONE;
- if (reg & BIT(16))
- ints |= DSI_VIDEO_MODE_FRAME_DONE;
- if (reg & BIT(20))
- ints |= DSI_BTA_DONE;
- if (reg & BIT(28))
- ints |= DSI_DYN_REFRESH_DONE;
- if (reg & BIT(30))
- ints |= DSI_DESKEW_DONE;
-
- pr_debug("[DSI_%d] Interrupt status = 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
- return ints;
-}
-
-/**
- * clear_interrupt_status() - clears the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be cleared.
- */
-void dsi_ctrl_hw_14_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints)
-{
- u32 reg = 0;
-
- if (ints & DSI_CMD_MODE_DMA_DONE)
- reg |= BIT(0);
- if (ints & DSI_CMD_FRAME_DONE)
- reg |= BIT(8);
- if (ints & DSI_CMD_STREAM0_FRAME_DONE)
- reg |= BIT(10);
- if (ints & DSI_CMD_STREAM1_FRAME_DONE)
- reg |= BIT(12);
- if (ints & DSI_CMD_STREAM2_FRAME_DONE)
- reg |= BIT(14);
- if (ints & DSI_VIDEO_MODE_FRAME_DONE)
- reg |= BIT(16);
- if (ints & DSI_BTA_DONE)
- reg |= BIT(20);
- if (ints & DSI_DYN_REFRESH_DONE)
- reg |= BIT(28);
- if (ints & DSI_DESKEW_DONE)
- reg |= BIT(30);
-
- DSI_W32(ctrl, DSI_INT_CTRL, reg);
-
- pr_debug("[DSI_%d] Clear interrupts, ints = 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
-}
-
-/**
- * enable_status_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set ints to 0.
- */
-void dsi_ctrl_hw_14_enable_status_interrupts(struct dsi_ctrl_hw *ctrl, u32 ints)
-{
- u32 reg = 0;
-
- /* Do not change value of DSI_ERROR_MASK bit */
- reg |= (DSI_R32(ctrl, DSI_INT_CTRL) & BIT(25));
- if (ints & DSI_CMD_MODE_DMA_DONE)
- reg |= BIT(1);
- if (ints & DSI_CMD_FRAME_DONE)
- reg |= BIT(9);
- if (ints & DSI_CMD_STREAM0_FRAME_DONE)
- reg |= BIT(11);
- if (ints & DSI_CMD_STREAM1_FRAME_DONE)
- reg |= BIT(13);
- if (ints & DSI_CMD_STREAM2_FRAME_DONE)
- reg |= BIT(15);
- if (ints & DSI_VIDEO_MODE_FRAME_DONE)
- reg |= BIT(17);
- if (ints & DSI_BTA_DONE)
- reg |= BIT(21);
- if (ints & DSI_DYN_REFRESH_DONE)
- reg |= BIT(29);
- if (ints & DSI_DESKEW_DONE)
- reg |= BIT(31);
-
- DSI_W32(ctrl, DSI_INT_CTRL, reg);
-
- pr_debug("[DSI_%d] Enable interrupts 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
-}
-
-/**
- * get_error_status() - returns the error status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of errors(enum dsi_error_int_type) that are
- * active. This list does not include any status interrupts. Caller
- * should call get_interrupt_status for status interrupts.
- *
- * Return: List of active error interrupts.
- */
-u64 dsi_ctrl_hw_14_get_error_status(struct dsi_ctrl_hw *ctrl)
-{
- u32 dln0_phy_err;
- u32 fifo_status;
- u32 ack_error;
- u32 timeout_errors;
- u32 clk_error;
- u32 dsi_status;
- u64 errors = 0;
-
- dln0_phy_err = DSI_R32(ctrl, DSI_DLN0_PHY_ERR);
- if (dln0_phy_err & BIT(0))
- errors |= DSI_DLN0_ESC_ENTRY_ERR;
- if (dln0_phy_err & BIT(4))
- errors |= DSI_DLN0_ESC_SYNC_ERR;
- if (dln0_phy_err & BIT(8))
- errors |= DSI_DLN0_LP_CONTROL_ERR;
- if (dln0_phy_err & BIT(12))
- errors |= DSI_DLN0_LP0_CONTENTION;
- if (dln0_phy_err & BIT(16))
- errors |= DSI_DLN0_LP1_CONTENTION;
-
- fifo_status = DSI_R32(ctrl, DSI_FIFO_STATUS);
- if (fifo_status & BIT(7))
- errors |= DSI_CMD_MDP_FIFO_UNDERFLOW;
- if (fifo_status & BIT(10))
- errors |= DSI_CMD_DMA_FIFO_UNDERFLOW;
- if (fifo_status & BIT(18))
- errors |= DSI_DLN0_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(19))
- errors |= DSI_DLN0_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(22))
- errors |= DSI_DLN1_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(23))
- errors |= DSI_DLN1_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(26))
- errors |= DSI_DLN2_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(27))
- errors |= DSI_DLN2_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(30))
- errors |= DSI_DLN3_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(31))
- errors |= DSI_DLN3_HS_FIFO_UNDERFLOW;
-
- ack_error = DSI_R32(ctrl, DSI_ACK_ERR_STATUS);
- if (ack_error & BIT(16))
- errors |= DSI_RDBK_SINGLE_ECC_ERR;
- if (ack_error & BIT(17))
- errors |= DSI_RDBK_MULTI_ECC_ERR;
- if (ack_error & BIT(20))
- errors |= DSI_RDBK_CRC_ERR;
- if (ack_error & BIT(23))
- errors |= DSI_RDBK_INCOMPLETE_PKT;
- if (ack_error & BIT(24))
- errors |= DSI_PERIPH_ERROR_PKT;
-
- timeout_errors = DSI_R32(ctrl, DSI_TIMEOUT_STATUS);
- if (timeout_errors & BIT(0))
- errors |= DSI_HS_TX_TIMEOUT;
- if (timeout_errors & BIT(4))
- errors |= DSI_LP_RX_TIMEOUT;
- if (timeout_errors & BIT(8))
- errors |= DSI_BTA_TIMEOUT;
-
- clk_error = DSI_R32(ctrl, DSI_CLK_STATUS);
- if (clk_error & BIT(16))
- errors |= DSI_PLL_UNLOCK;
-
- dsi_status = DSI_R32(ctrl, DSI_STATUS);
- if (dsi_status & BIT(31))
- errors |= DSI_INTERLEAVE_OP_CONTENTION;
-
- pr_debug("[DSI_%d] Error status = 0x%llx, phy=0x%x, fifo=0x%x",
- ctrl->index, errors, dln0_phy_err, fifo_status);
- pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
- ctrl->index, ack_error, timeout_errors, clk_error, dsi_status);
- return errors;
-}
-
-/**
- * clear_error_status() - clears the specified errors
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be cleared.
- */
-void dsi_ctrl_hw_14_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors)
-{
- u32 dln0_phy_err = 0;
- u32 fifo_status = 0;
- u32 ack_error = 0;
- u32 timeout_error = 0;
- u32 clk_error = 0;
- u32 dsi_status = 0;
- u32 int_ctrl = 0;
-
- if (errors & DSI_RDBK_SINGLE_ECC_ERR)
- ack_error |= BIT(16);
- if (errors & DSI_RDBK_MULTI_ECC_ERR)
- ack_error |= BIT(17);
- if (errors & DSI_RDBK_CRC_ERR)
- ack_error |= BIT(20);
- if (errors & DSI_RDBK_INCOMPLETE_PKT)
- ack_error |= BIT(23);
- if (errors & DSI_PERIPH_ERROR_PKT)
- ack_error |= BIT(24);
-
- if (errors & DSI_LP_RX_TIMEOUT)
- timeout_error |= BIT(4);
- if (errors & DSI_HS_TX_TIMEOUT)
- timeout_error |= BIT(0);
- if (errors & DSI_BTA_TIMEOUT)
- timeout_error |= BIT(8);
-
- if (errors & DSI_PLL_UNLOCK)
- clk_error |= BIT(16);
-
- if (errors & DSI_DLN0_LP0_CONTENTION)
- dln0_phy_err |= BIT(12);
- if (errors & DSI_DLN0_LP1_CONTENTION)
- dln0_phy_err |= BIT(16);
- if (errors & DSI_DLN0_ESC_ENTRY_ERR)
- dln0_phy_err |= BIT(0);
- if (errors & DSI_DLN0_ESC_SYNC_ERR)
- dln0_phy_err |= BIT(4);
- if (errors & DSI_DLN0_LP_CONTROL_ERR)
- dln0_phy_err |= BIT(8);
-
- if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
- fifo_status |= BIT(10);
- if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
- fifo_status |= BIT(7);
- if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(18);
- if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(22);
- if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(26);
- if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(30);
- if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(19);
- if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(23);
- if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(27);
- if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(31);
-
- if (errors & DSI_INTERLEAVE_OP_CONTENTION)
- dsi_status |= BIT(31);
-
- DSI_W32(ctrl, DSI_DLN0_PHY_ERR, dln0_phy_err);
- DSI_W32(ctrl, DSI_FIFO_STATUS, fifo_status);
- DSI_W32(ctrl, DSI_ACK_ERR_STATUS, ack_error);
- DSI_W32(ctrl, DSI_TIMEOUT_STATUS, timeout_error);
- DSI_W32(ctrl, DSI_CLK_STATUS, clk_error);
- DSI_W32(ctrl, DSI_STATUS, dsi_status);
-
- int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
- int_ctrl |= BIT(24);
- DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
- pr_debug("[DSI_%d] clear errors = 0x%llx, phy=0x%x, fifo=0x%x",
- ctrl->index, errors, dln0_phy_err, fifo_status);
- pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
- ctrl->index, ack_error, timeout_error, clk_error, dsi_status);
-}
-
-/**
- * enable_error_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set errors to 0.
- */
-void dsi_ctrl_hw_14_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
- u64 errors)
-{
- u32 int_ctrl = 0;
- u32 int_mask0 = 0x7FFF3BFF;
-
- int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
- if (errors)
- int_ctrl |= BIT(25);
- else
- int_ctrl &= ~BIT(25);
-
- if (errors & DSI_RDBK_SINGLE_ECC_ERR)
- int_mask0 &= ~BIT(0);
- if (errors & DSI_RDBK_MULTI_ECC_ERR)
- int_mask0 &= ~BIT(1);
- if (errors & DSI_RDBK_CRC_ERR)
- int_mask0 &= ~BIT(2);
- if (errors & DSI_RDBK_INCOMPLETE_PKT)
- int_mask0 &= ~BIT(3);
- if (errors & DSI_PERIPH_ERROR_PKT)
- int_mask0 &= ~BIT(4);
-
- if (errors & DSI_LP_RX_TIMEOUT)
- int_mask0 &= ~BIT(5);
- if (errors & DSI_HS_TX_TIMEOUT)
- int_mask0 &= ~BIT(6);
- if (errors & DSI_BTA_TIMEOUT)
- int_mask0 &= ~BIT(7);
-
- if (errors & DSI_PLL_UNLOCK)
- int_mask0 &= ~BIT(28);
-
- if (errors & DSI_DLN0_LP0_CONTENTION)
- int_mask0 &= ~BIT(24);
- if (errors & DSI_DLN0_LP1_CONTENTION)
- int_mask0 &= ~BIT(25);
- if (errors & DSI_DLN0_ESC_ENTRY_ERR)
- int_mask0 &= ~BIT(21);
- if (errors & DSI_DLN0_ESC_SYNC_ERR)
- int_mask0 &= ~BIT(22);
- if (errors & DSI_DLN0_LP_CONTROL_ERR)
- int_mask0 &= ~BIT(23);
-
- if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(9);
- if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(11);
- if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(16);
- if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(17);
- if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(18);
- if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(19);
- if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(26);
- if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(27);
- if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(29);
- if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(30);
-
- if (errors & DSI_INTERLEAVE_OP_CONTENTION)
- int_mask0 &= ~BIT(8);
-
- DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
- DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0);
-
- pr_debug("[DSI_%d] enable errors = 0x%llx, int_mask0=0x%x\n",
- ctrl->index, errors, int_mask0);
-}
-
-/**
- * video_test_pattern_setup() - setup test pattern engine for video mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- */
-void dsi_ctrl_hw_14_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val)
-{
- u32 reg = 0;
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val);
-
- switch (type) {
- case DSI_TEST_PATTERN_FIXED:
- reg |= (0x2 << 4);
- break;
- case DSI_TEST_PATTERN_INC:
- reg |= (0x1 << 4);
- break;
- case DSI_TEST_PATTERN_POLY:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F);
- break;
- default:
- break;
- }
-
- DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, 0x100);
- DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, 0x5);
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- pr_debug("[DSI_%d] Video test pattern setup done\n", ctrl->index);
-}
-
-/**
- * cmd_test_pattern_setup() - setup test patttern engine for cmd mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- * @stream_id: Stream Id on which packets are generated.
- */
-void dsi_ctrl_hw_14_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val,
- u32 stream_id)
-{
- u32 reg = 0;
- u32 init_offset;
- u32 poly_offset;
- u32 pattern_sel_shift;
-
- switch (stream_id) {
- case 0:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY;
- pattern_sel_shift = 8;
- break;
- case 1:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY;
- pattern_sel_shift = 12;
- break;
- case 2:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY;
- pattern_sel_shift = 20;
- break;
- default:
- return;
- }
-
- DSI_W32(ctrl, init_offset, init_val);
-
- switch (type) {
- case DSI_TEST_PATTERN_FIXED:
- reg |= (0x2 << pattern_sel_shift);
- break;
- case DSI_TEST_PATTERN_INC:
- reg |= (0x1 << pattern_sel_shift);
- break;
- case DSI_TEST_PATTERN_POLY:
- DSI_W32(ctrl, poly_offset, 0xF0F0F);
- break;
- default:
- break;
- }
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
- pr_debug("[DSI_%d] Cmd test pattern setup done\n", ctrl->index);
-}
-
-/**
- * test_pattern_enable() - enable test pattern engine
- * @ctrl: Pointer to the controller host hardware.
- * @enable: Enable/Disable test pattern engine.
- */
-void dsi_ctrl_hw_14_test_pattern_enable(struct dsi_ctrl_hw *ctrl,
- bool enable)
-{
- u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL);
-
- if (enable)
- reg |= BIT(0);
- else
- reg &= ~BIT(0);
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- pr_debug("[DSI_%d] Test pattern enable=%d\n", ctrl->index, enable);
-}
-
-/**
- * trigger_cmd_test_pattern() - trigger a command mode frame update with
- * test pattern
- * @ctrl: Pointer to the controller host hardware.
- * @stream_id: Stream on which frame update is sent.
- */
-void dsi_ctrl_hw_14_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
- u32 stream_id)
-{
- switch (stream_id) {
- case 0:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER, 0x1);
- break;
- case 1:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER, 0x1);
- break;
- case 2:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER, 0x1);
- break;
- default:
- break;
- }
-
- pr_debug("[DSI_%d] Cmd Test pattern trigger\n", ctrl->index);
-}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h
deleted file mode 100644
index 028ad46664a7..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DSI_CTRL_REG_H_
-#define _DSI_CTRL_REG_H_
-
-#define DSI_HW_VERSION (0x0000)
-#define DSI_CTRL (0x0004)
-#define DSI_STATUS (0x0008)
-#define DSI_FIFO_STATUS (0x000C)
-#define DSI_VIDEO_MODE_CTRL (0x0010)
-#define DSI_VIDEO_MODE_SYNC_DATATYPE (0x0014)
-#define DSI_VIDEO_MODE_PIXEL_DATATYPE (0x0018)
-#define DSI_VIDEO_MODE_BLANKING_DATATYPE (0x001C)
-#define DSI_VIDEO_MODE_DATA_CTRL (0x0020)
-#define DSI_VIDEO_MODE_ACTIVE_H (0x0024)
-#define DSI_VIDEO_MODE_ACTIVE_V (0x0028)
-#define DSI_VIDEO_MODE_TOTAL (0x002C)
-#define DSI_VIDEO_MODE_HSYNC (0x0030)
-#define DSI_VIDEO_MODE_VSYNC (0x0034)
-#define DSI_VIDEO_MODE_VSYNC_VPOS (0x0038)
-#define DSI_COMMAND_MODE_DMA_CTRL (0x003C)
-#define DSI_COMMAND_MODE_MDP_CTRL (0x0040)
-#define DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL (0x0044)
-#define DSI_DMA_CMD_OFFSET (0x0048)
-#define DSI_DMA_CMD_LENGTH (0x004C)
-#define DSI_DMA_FIFO_CTRL (0x0050)
-#define DSI_DMA_NULL_PACKET_DATA (0x0054)
-#define DSI_COMMAND_MODE_MDP_STREAM0_CTRL (0x0058)
-#define DSI_COMMAND_MODE_MDP_STREAM0_TOTAL (0x005C)
-#define DSI_COMMAND_MODE_MDP_STREAM1_CTRL (0x0060)
-#define DSI_COMMAND_MODE_MDP_STREAM1_TOTAL (0x0064)
-#define DSI_ACK_ERR_STATUS (0x0068)
-#define DSI_RDBK_DATA0 (0x006C)
-#define DSI_RDBK_DATA1 (0x0070)
-#define DSI_RDBK_DATA2 (0x0074)
-#define DSI_RDBK_DATA3 (0x0078)
-#define DSI_RDBK_DATATYPE0 (0x007C)
-#define DSI_RDBK_DATATYPE1 (0x0080)
-#define DSI_TRIG_CTRL (0x0084)
-#define DSI_EXT_MUX (0x0088)
-#define DSI_EXT_MUX_TE_PULSE_DETECT_CTRL (0x008C)
-#define DSI_CMD_MODE_DMA_SW_TRIGGER (0x0090)
-#define DSI_CMD_MODE_MDP_SW_TRIGGER (0x0094)
-#define DSI_CMD_MODE_BTA_SW_TRIGGER (0x0098)
-#define DSI_RESET_SW_TRIGGER (0x009C)
-#define DSI_MISR_CMD_CTRL (0x00A0)
-#define DSI_MISR_VIDEO_CTRL (0x00A4)
-#define DSI_LANE_STATUS (0x00A8)
-#define DSI_LANE_CTRL (0x00AC)
-#define DSI_LANE_SWAP_CTRL (0x00B0)
-#define DSI_DLN0_PHY_ERR (0x00B4)
-#define DSI_LP_TIMER_CTRL (0x00B8)
-#define DSI_HS_TIMER_CTRL (0x00BC)
-#define DSI_TIMEOUT_STATUS (0x00C0)
-#define DSI_CLKOUT_TIMING_CTRL (0x00C4)
-#define DSI_EOT_PACKET (0x00C8)
-#define DSI_EOT_PACKET_CTRL (0x00CC)
-#define DSI_GENERIC_ESC_TX_TRIGGER (0x00D0)
-#define DSI_CAM_BIST_CTRL (0x00D4)
-#define DSI_CAM_BIST_FRAME_SIZE (0x00D8)
-#define DSI_CAM_BIST_BLOCK_SIZE (0x00DC)
-#define DSI_CAM_BIST_FRAME_CONFIG (0x00E0)
-#define DSI_CAM_BIST_LSFR_CTRL (0x00E4)
-#define DSI_CAM_BIST_LSFR_INIT (0x00E8)
-#define DSI_CAM_BIST_START (0x00EC)
-#define DSI_CAM_BIST_STATUS (0x00F0)
-#define DSI_ERR_INT_MASK0 (0x010C)
-#define DSI_INT_CTRL (0x0110)
-#define DSI_IOBIST_CTRL (0x0114)
-#define DSI_SOFT_RESET (0x0118)
-#define DSI_CLK_CTRL (0x011C)
-#define DSI_CLK_STATUS (0x0120)
-#define DSI_PHY_SW_RESET (0x012C)
-#define DSI_AXI2AHB_CTRL (0x0130)
-#define DSI_MISR_CMD_MDP0_32BIT (0x0134)
-#define DSI_MISR_CMD_MDP1_32BIT (0x0138)
-#define DSI_MISR_CMD_DMA_32BIT (0x013C)
-#define DSI_MISR_VIDEO_32BIT (0x0140)
-#define DSI_LANE_MISR_CTRL (0x0144)
-#define DSI_LANE0_MISR (0x0148)
-#define DSI_LANE1_MISR (0x014C)
-#define DSI_LANE2_MISR (0x0150)
-#define DSI_LANE3_MISR (0x0154)
-#define DSI_TEST_PATTERN_GEN_CTRL (0x015C)
-#define DSI_TEST_PATTERN_GEN_VIDEO_POLY (0x0160)
-#define DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL (0x0164)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY (0x0168)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0 (0x016C)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY (0x0170)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1 (0x0174)
-#define DSI_TEST_PATTERN_GEN_CMD_DMA_POLY (0x0178)
-#define DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL (0x017C)
-#define DSI_TEST_PATTERN_GEN_VIDEO_ENABLE (0x0180)
-#define DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER (0x0184)
-#define DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER (0x0188)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2 (0x018C)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY (0x0190)
-#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY (0x0190)
-#define DSI_COMMAND_MODE_MDP_IDLE_CTRL (0x0194)
-#define DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER (0x0198)
-#define DSI_TPG_MAIN_CONTROL (0x019C)
-#define DSI_TPG_MAIN_CONTROL2 (0x01A0)
-#define DSI_TPG_VIDEO_CONFIG (0x01A4)
-#define DSI_TPG_COMPONENT_LIMITS (0x01A8)
-#define DSI_TPG_RECTANGLE (0x01AC)
-#define DSI_TPG_BLACK_WHITE_PATTERN_FRAMES (0x01B0)
-#define DSI_TPG_RGB_MAPPING (0x01B4)
-#define DSI_COMMAND_MODE_MDP_CTRL2 (0x01B8)
-#define DSI_COMMAND_MODE_MDP_STREAM2_CTRL (0x01BC)
-#define DSI_COMMAND_MODE_MDP_STREAM2_TOTAL (0x01C0)
-#define DSI_MISR_CMD_MDP2_8BIT (0x01C4)
-#define DSI_MISR_CMD_MDP2_32BIT (0x01C8)
-#define DSI_VBIF_CTRL (0x01CC)
-#define DSI_AES_CTRL (0x01D0)
-#define DSI_RDBK_DATA_CTRL (0x01D4)
-#define DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL2 (0x01D8)
-#define DSI_TPG_DMA_FIFO_STATUS (0x01DC)
-#define DSI_TPG_DMA_FIFO_WRITE_TRIGGER (0x01E0)
-#define DSI_DSI_TIMING_FLUSH (0x01E4)
-#define DSI_DSI_TIMING_DB_MODE (0x01E8)
-#define DSI_TPG_DMA_FIFO_RESET (0x01EC)
-#define DSI_SCRATCH_REGISTER_0 (0x01F0)
-#define DSI_VERSION (0x01F4)
-#define DSI_SCRATCH_REGISTER_1 (0x01F8)
-#define DSI_SCRATCH_REGISTER_2 (0x01FC)
-#define DSI_DYNAMIC_REFRESH_CTRL (0x0200)
-#define DSI_DYNAMIC_REFRESH_PIPE_DELAY (0x0204)
-#define DSI_DYNAMIC_REFRESH_PIPE_DELAY2 (0x0208)
-#define DSI_DYNAMIC_REFRESH_PLL_DELAY (0x020C)
-#define DSI_DYNAMIC_REFRESH_STATUS (0x0210)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 (0x0214)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 (0x0218)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 (0x021C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 (0x0220)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 (0x0224)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 (0x0228)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 (0x022C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 (0x0230)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 (0x0234)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 (0x0238)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 (0x023C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 (0x0240)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 (0x0244)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 (0x0248)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 (0x024C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 (0x0250)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 (0x0254)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 (0x0258)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 (0x025C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 (0x0260)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 (0x0264)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 (0x0268)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 (0x026C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 (0x0270)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 (0x0274)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 (0x0278)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 (0x027C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 (0x0280)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 (0x0284)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 (0x0288)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 (0x028C)
-#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 (0x0290)
-#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR (0x0294)
-#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 (0x0298)
-#define DSI_VIDEO_COMPRESSION_MODE_CTRL (0x02A0)
-#define DSI_VIDEO_COMPRESSION_MODE_CTRL2 (0x02A4)
-#define DSI_COMMAND_COMPRESSION_MODE_CTRL (0x02A8)
-#define DSI_COMMAND_COMPRESSION_MODE_CTRL2 (0x02AC)
-#define DSI_COMMAND_COMPRESSION_MODE_CTRL3 (0x02B0)
-#define DSI_COMMAND_MODE_NULL_INSERTION_CTRL (0x02B4)
-#define DSI_READ_BACK_DISABLE_STATUS (0x02B8)
-#define DSI_DESKEW_CTRL (0x02BC)
-#define DSI_DESKEW_DELAY_CTRL (0x02C0)
-#define DSI_DESKEW_SW_TRIGGER (0x02C4)
-#define DSI_SECURE_DISPLAY_STATUS (0x02CC)
-#define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR (0x02D0)
-#define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR (0x02D4)
-
-
-#endif /* _DSI_CTRL_REG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
deleted file mode 100644
index ded7ed3710ee..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DSI_DEFS_H_
-#define _DSI_DEFS_H_
-
-#include <linux/types.h>
-
-#define DSI_H_TOTAL(t) (((t)->h_active) + ((t)->h_back_porch) + \
- ((t)->h_sync_width) + ((t)->h_front_porch))
-
-#define DSI_V_TOTAL(t) (((t)->v_active) + ((t)->v_back_porch) + \
- ((t)->v_sync_width) + ((t)->v_front_porch))
-
-/**
- * enum dsi_pixel_format - DSI pixel formats
- * @DSI_PIXEL_FORMAT_RGB565:
- * @DSI_PIXEL_FORMAT_RGB666:
- * @DSI_PIXEL_FORMAT_RGB666_LOOSE:
- * @DSI_PIXEL_FORMAT_RGB888:
- * @DSI_PIXEL_FORMAT_RGB111:
- * @DSI_PIXEL_FORMAT_RGB332:
- * @DSI_PIXEL_FORMAT_RGB444:
- * @DSI_PIXEL_FORMAT_MAX:
- */
-enum dsi_pixel_format {
- DSI_PIXEL_FORMAT_RGB565 = 0,
- DSI_PIXEL_FORMAT_RGB666,
- DSI_PIXEL_FORMAT_RGB666_LOOSE,
- DSI_PIXEL_FORMAT_RGB888,
- DSI_PIXEL_FORMAT_RGB111,
- DSI_PIXEL_FORMAT_RGB332,
- DSI_PIXEL_FORMAT_RGB444,
- DSI_PIXEL_FORMAT_MAX
-};
-
-/**
- * enum dsi_op_mode - dsi operation mode
- * @DSI_OP_VIDEO_MODE: DSI video mode operation
- * @DSI_OP_CMD_MODE: DSI Command mode operation
- * @DSI_OP_MODE_MAX:
- */
-enum dsi_op_mode {
- DSI_OP_VIDEO_MODE = 0,
- DSI_OP_CMD_MODE,
- DSI_OP_MODE_MAX
-};
-
-/**
- * enum dsi_data_lanes - dsi physical lanes
- * @DSI_DATA_LANE_0: Physical lane 0
- * @DSI_DATA_LANE_1: Physical lane 1
- * @DSI_DATA_LANE_2: Physical lane 2
- * @DSI_DATA_LANE_3: Physical lane 3
- * @DSI_CLOCK_LANE: Physical clock lane
- */
-enum dsi_data_lanes {
- DSI_DATA_LANE_0 = BIT(0),
- DSI_DATA_LANE_1 = BIT(1),
- DSI_DATA_LANE_2 = BIT(2),
- DSI_DATA_LANE_3 = BIT(3),
- DSI_CLOCK_LANE = BIT(4)
-};
-
-/**
- * enum dsi_logical_lane - dsi logical lanes
- * @DSI_LOGICAL_LANE_0: Logical lane 0
- * @DSI_LOGICAL_LANE_1: Logical lane 1
- * @DSI_LOGICAL_LANE_2: Logical lane 2
- * @DSI_LOGICAL_LANE_3: Logical lane 3
- * @DSI_LOGICAL_CLOCK_LANE: Clock lane
- * @DSI_LANE_MAX: Maximum lanes supported
- */
-enum dsi_logical_lane {
- DSI_LOGICAL_LANE_0 = 0,
- DSI_LOGICAL_LANE_1,
- DSI_LOGICAL_LANE_2,
- DSI_LOGICAL_LANE_3,
- DSI_LOGICAL_CLOCK_LANE,
- DSI_LANE_MAX
-};
-
-/**
- * enum dsi_trigger_type - dsi trigger type
- * @DSI_TRIGGER_NONE: No trigger.
- * @DSI_TRIGGER_TE: TE trigger.
- * @DSI_TRIGGER_SEOF: Start or End of frame.
- * @DSI_TRIGGER_SW: Software trigger.
- * @DSI_TRIGGER_SW_SEOF: Software trigger and start/end of frame.
- * @DSI_TRIGGER_SW_TE: Software and TE triggers.
- * @DSI_TRIGGER_MAX: Max trigger values.
- */
-enum dsi_trigger_type {
- DSI_TRIGGER_NONE = 0,
- DSI_TRIGGER_TE,
- DSI_TRIGGER_SEOF,
- DSI_TRIGGER_SW,
- DSI_TRIGGER_SW_SEOF,
- DSI_TRIGGER_SW_TE,
- DSI_TRIGGER_MAX
-};
-
-/**
- * enum dsi_color_swap_mode - color swap mode
- * @DSI_COLOR_SWAP_RGB:
- * @DSI_COLOR_SWAP_RBG:
- * @DSI_COLOR_SWAP_BGR:
- * @DSI_COLOR_SWAP_BRG:
- * @DSI_COLOR_SWAP_GRB:
- * @DSI_COLOR_SWAP_GBR:
- */
-enum dsi_color_swap_mode {
- DSI_COLOR_SWAP_RGB = 0,
- DSI_COLOR_SWAP_RBG,
- DSI_COLOR_SWAP_BGR,
- DSI_COLOR_SWAP_BRG,
- DSI_COLOR_SWAP_GRB,
- DSI_COLOR_SWAP_GBR
-};
-
-/**
- * enum dsi_dfps_type - Dynamic FPS support type
- * @DSI_DFPS_NONE: Dynamic FPS is not supported.
- * @DSI_DFPS_SUSPEND_RESUME:
- * @DSI_DFPS_IMMEDIATE_CLK:
- * @DSI_DFPS_IMMEDIATE_HFP:
- * @DSI_DFPS_IMMEDIATE_VFP:
- * @DSI_DPFS_MAX:
- */
-enum dsi_dfps_type {
- DSI_DFPS_NONE = 0,
- DSI_DFPS_SUSPEND_RESUME,
- DSI_DFPS_IMMEDIATE_CLK,
- DSI_DFPS_IMMEDIATE_HFP,
- DSI_DFPS_IMMEDIATE_VFP,
- DSI_DFPS_MAX
-};
-
-/**
- * enum dsi_phy_type - DSI phy types
- * @DSI_PHY_TYPE_DPHY:
- * @DSI_PHY_TYPE_CPHY:
- */
-enum dsi_phy_type {
- DSI_PHY_TYPE_DPHY,
- DSI_PHY_TYPE_CPHY
-};
-
-/**
- * enum dsi_te_mode - dsi te source
- * @DSI_TE_ON_DATA_LINK: TE read from DSI link
- * @DSI_TE_ON_EXT_PIN: TE signal on an external GPIO
- */
-enum dsi_te_mode {
- DSI_TE_ON_DATA_LINK = 0,
- DSI_TE_ON_EXT_PIN,
-};
-
-/**
- * enum dsi_video_traffic_mode - video mode pixel transmission type
- * @DSI_VIDEO_TRAFFIC_SYNC_PULSES: Non-burst mode with sync pulses.
- * @DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS: Non-burst mode with sync start events.
- * @DSI_VIDEO_TRAFFIC_BURST_MODE: Burst mode using sync start events.
- */
-enum dsi_video_traffic_mode {
- DSI_VIDEO_TRAFFIC_SYNC_PULSES = 0,
- DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS,
- DSI_VIDEO_TRAFFIC_BURST_MODE,
-};
-
-/**
- * struct dsi_mode_info - video mode information dsi frame
- * @h_active: Active width of one frame in pixels.
- * @h_back_porch: Horizontal back porch in pixels.
- * @h_sync_width: HSYNC width in pixels.
- * @h_front_porch: Horizontal fron porch in pixels.
- * @h_skew:
- * @h_sync_polarity: Polarity of HSYNC (false is active low).
- * @v_active: Active height of one frame in lines.
- * @v_back_porch: Vertical back porch in lines.
- * @v_sync_width: VSYNC width in lines.
- * @v_front_porch: Vertical front porch in lines.
- * @v_sync_polarity: Polarity of VSYNC (false is active low).
- * @refresh_rate: Refresh rate in Hz.
- */
-struct dsi_mode_info {
- u32 h_active;
- u32 h_back_porch;
- u32 h_sync_width;
- u32 h_front_porch;
- u32 h_skew;
- bool h_sync_polarity;
-
- u32 v_active;
- u32 v_back_porch;
- u32 v_sync_width;
- u32 v_front_porch;
- bool v_sync_polarity;
-
- u32 refresh_rate;
-};
-
-/**
- * struct dsi_lane_mapping - Mapping between DSI logical and physical lanes
- * @physical_lane0: Logical lane to which physical lane 0 is mapped.
- * @physical_lane1: Logical lane to which physical lane 1 is mapped.
- * @physical_lane2: Logical lane to which physical lane 2 is mapped.
- * @physical_lane3: Logical lane to which physical lane 3 is mapped.
- */
-struct dsi_lane_mapping {
- enum dsi_logical_lane physical_lane0;
- enum dsi_logical_lane physical_lane1;
- enum dsi_logical_lane physical_lane2;
- enum dsi_logical_lane physical_lane3;
-};
-
-/**
- * struct dsi_host_common_cfg - Host configuration common to video and cmd mode
- * @dst_format: Destination pixel format.
- * @data_lanes: Physical data lanes to be enabled.
- * @en_crc_check: Enable CRC checks.
- * @en_ecc_check: Enable ECC checks.
- * @te_mode: Source for TE signalling.
- * @mdp_cmd_trigger: MDP frame update trigger for command mode.
- * @dma_cmd_trigger: Command DMA trigger.
- * @cmd_trigger_stream: Command mode stream to trigger.
- * @bit_swap_read: Is red color bit swapped.
- * @bit_swap_green: Is green color bit swapped.
- * @bit_swap_blue: Is blue color bit swapped.
- * @t_clk_post: Number of byte clock cycles that the transmitter shall
- * continue sending after last data lane has transitioned
- * to LP mode.
- * @t_clk_pre: Number of byte clock cycles that the high spped clock
- * shall be driven prior to data lane transitions from LP
- * to HS mode.
- * @ignore_rx_eot: Ignore Rx EOT packets if set to true.
- * @append_tx_eot: Append EOT packets for forward transmissions if set to
- * true.
- */
-struct dsi_host_common_cfg {
- enum dsi_pixel_format dst_format;
- enum dsi_data_lanes data_lanes;
- bool en_crc_check;
- bool en_ecc_check;
- enum dsi_te_mode te_mode;
- enum dsi_trigger_type mdp_cmd_trigger;
- enum dsi_trigger_type dma_cmd_trigger;
- u32 cmd_trigger_stream;
- enum dsi_color_swap_mode swap_mode;
- bool bit_swap_red;
- bool bit_swap_green;
- bool bit_swap_blue;
- u32 t_clk_post;
- u32 t_clk_pre;
- bool ignore_rx_eot;
- bool append_tx_eot;
-};
-
-/**
- * struct dsi_video_engine_cfg - DSI video engine configuration
- * @host_cfg: Pointer to host common configuration.
- * @last_line_interleave_en: Allow command mode op interleaved on last line of
- * video stream.
- * @pulse_mode_hsa_he: Send HSA and HE following VS/VE packet if set to
- * true.
- * @hfp_lp11_en: Enter low power stop mode (LP-11) during HFP.
- * @hbp_lp11_en: Enter low power stop mode (LP-11) during HBP.
- * @hsa_lp11_en: Enter low power stop mode (LP-11) during HSA.
- * @eof_bllp_lp11_en: Enter low power stop mode (LP-11) during BLLP of
- * last line of a frame.
- * @bllp_lp11_en: Enter low power stop mode (LP-11) during BLLP.
- * @traffic_mode: Traffic mode for video stream.
- * @vc_id: Virtual channel identifier.
- */
-struct dsi_video_engine_cfg {
- bool last_line_interleave_en;
- bool pulse_mode_hsa_he;
- bool hfp_lp11_en;
- bool hbp_lp11_en;
- bool hsa_lp11_en;
- bool eof_bllp_lp11_en;
- bool bllp_lp11_en;
- enum dsi_video_traffic_mode traffic_mode;
- u32 vc_id;
-};
-
-/**
- * struct dsi_cmd_engine_cfg - DSI command engine configuration
- * @host_cfg: Pointer to host common configuration.
- * @host_cfg: Common host configuration
- * @max_cmd_packets_interleave Maximum number of command mode RGB packets to
- * send with in one horizontal blanking period
- * of the video mode frame.
- * @wr_mem_start: DCS command for write_memory_start.
- * @wr_mem_continue: DCS command for write_memory_continue.
- * @insert_dcs_command: Insert DCS command as first byte of payload
- * of the pixel data.
- */
-struct dsi_cmd_engine_cfg {
- u32 max_cmd_packets_interleave;
- u32 wr_mem_start;
- u32 wr_mem_continue;
- bool insert_dcs_command;
-};
-
-/**
- * struct dsi_host_config - DSI host configuration parameters.
- * @panel_mode: Operation mode for panel (video or cmd mode).
- * @common_config: Host configuration common to both Video and Cmd mode.
- * @video_engine: Video engine configuration if panel is in video mode.
- * @cmd_engine: Cmd engine configuration if panel is in cmd mode.
- * @esc_clk_rate_khz: Esc clock frequency in Hz.
- * @bit_clk_rate_hz: Bit clock frequency in Hz.
- * @video_timing: Video timing information of a frame.
- * @lane_map: Mapping between logical and physical lanes.
- * @phy_type: PHY type to be used.
- */
-struct dsi_host_config {
- enum dsi_op_mode panel_mode;
- struct dsi_host_common_cfg common_config;
- union {
- struct dsi_video_engine_cfg video_engine;
- struct dsi_cmd_engine_cfg cmd_engine;
- } u;
- u64 esc_clk_rate_hz;
- u64 bit_clk_rate_hz;
- struct dsi_mode_info video_timing;
- struct dsi_lane_mapping lane_map;
-};
-
-/**
- * struct dsi_display_mode - specifies mode for dsi display
- * @timing: Timing parameters for the panel.
- * @pixel_clk_khz: Pixel clock in Khz.
- * @panel_mode: Panel operation mode.
- * @flags: Additional flags.
- */
-struct dsi_display_mode {
- struct dsi_mode_info timing;
- u32 pixel_clk_khz;
- enum dsi_op_mode panel_mode;
-
- u32 flags;
-};
-
-#endif /* _DSI_DEFS_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
deleted file mode 100644
index 01535c02a7f8..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DSI_HW_H_
-#define _DSI_HW_H_
-#include <linux/io.h>
-
-#define DSI_R32(dsi_hw, off) readl_relaxed((dsi_hw)->base + (off))
-#define DSI_W32(dsi_hw, off, val) \
- do {\
- pr_debug("[DSI_%d][%s] - [0x%08x]\n", \
- (dsi_hw)->index, #off, val); \
- writel_relaxed((val), (dsi_hw)->base + (off)); \
- } while (0)
-
-#define DSI_MMSS_MISC_R32(dsi_hw, off) \
- readl_relaxed((dsi_hw)->mmss_misc_base + (off))
-#define DSI_MMSS_MISC_W32(dsi_hw, off, val) \
- do {\
- pr_debug("[DSI_%d][%s] - [0x%08x]\n", \
- (dsi_hw)->index, #off, val); \
- writel_relaxed((val), (dsi_hw)->mmss_misc_base + (off)); \
- } while (0)
-
-#define DSI_R64(dsi_hw, off) readq_relaxed((dsi_hw)->base + (off))
-#define DSI_W64(dsi_hw, off, val) writeq_relaxed((val), (dsi_hw)->base + (off))
-
-#endif /* _DSI_HW_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
deleted file mode 100644
index 5edfd5e62738..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _DSI_PHY_HW_H_
-#define _DSI_PHY_HW_H_
-
-#include "dsi_defs.h"
-
-#define DSI_MAX_SETTINGS 8
-
-/**
- * enum dsi_phy_version - DSI PHY version enumeration
- * @DSI_PHY_VERSION_UNKNOWN: Unknown version.
- * @DSI_PHY_VERSION_1_0: 28nm-HPM.
- * @DSI_PHY_VERSION_2_0: 28nm-LPM.
- * @DSI_PHY_VERSION_3_0: 20nm.
- * @DSI_PHY_VERSION_4_0: 14nm.
- * @DSI_PHY_VERSION_MAX:
- */
-enum dsi_phy_version {
- DSI_PHY_VERSION_UNKNOWN,
- DSI_PHY_VERSION_1_0, /* 28nm-HPM */
- DSI_PHY_VERSION_2_0, /* 28nm-LPM */
- DSI_PHY_VERSION_3_0, /* 20nm */
- DSI_PHY_VERSION_4_0, /* 14nm */
- DSI_PHY_VERSION_MAX
-};
-
-/**
- * enum dsi_phy_hw_features - features supported by DSI PHY hardware
- * @DSI_PHY_DPHY: Supports DPHY
- * @DSI_PHY_CPHY: Supports CPHY
- */
-enum dsi_phy_hw_features {
- DSI_PHY_DPHY,
- DSI_PHY_CPHY,
- DSI_PHY_MAX_FEATURES
-};
-
-/**
- * enum dsi_phy_pll_source - pll clock source for PHY.
- * @DSI_PLL_SOURCE_STANDALONE: Clock is sourced from native PLL and is not
- * shared by other PHYs.
- * @DSI_PLL_SOURCE_NATIVE: Clock is sourced from native PLL and is
- * shared by other PHYs.
- * @DSI_PLL_SOURCE_NON_NATIVE: Clock is sourced from other PHYs.
- * @DSI_PLL_SOURCE_MAX:
- */
-enum dsi_phy_pll_source {
- DSI_PLL_SOURCE_STANDALONE = 0,
- DSI_PLL_SOURCE_NATIVE,
- DSI_PLL_SOURCE_NON_NATIVE,
- DSI_PLL_SOURCE_MAX
-};
-
-/**
- * struct dsi_phy_per_lane_cfgs - Holds register values for PHY parameters
- * @lane: A set of maximum 8 values for each lane.
- * @count_per_lane: Number of values per each lane.
- */
-struct dsi_phy_per_lane_cfgs {
- u8 lane[DSI_LANE_MAX][DSI_MAX_SETTINGS];
- u32 count_per_lane;
-};
-
-/**
- * struct dsi_phy_cfg - DSI PHY configuration
- * @lanecfg: Lane configuration settings.
- * @strength: Strength settings for lanes.
- * @timing: Timing parameters for lanes.
- * @regulators: Regulator settings for lanes.
- * @pll_source: PLL source.
- */
-struct dsi_phy_cfg {
- struct dsi_phy_per_lane_cfgs lanecfg;
- struct dsi_phy_per_lane_cfgs strength;
- struct dsi_phy_per_lane_cfgs timing;
- struct dsi_phy_per_lane_cfgs regulators;
- enum dsi_phy_pll_source pll_source;
-};
-
-struct dsi_phy_hw;
-
-/**
- * struct dsi_phy_hw_ops - Operations for DSI PHY hardware.
- * @regulator_enable: Enable PHY regulators.
- * @regulator_disable: Disable PHY regulators.
- * @enable: Enable PHY.
- * @disable: Disable PHY.
- * @calculate_timing_params: Calculate PHY timing params from mode information
- */
-struct dsi_phy_hw_ops {
- /**
- * regulator_enable() - enable regulators for DSI PHY
- * @phy: Pointer to DSI PHY hardware object.
- * @reg_cfg: Regulator configuration for all DSI lanes.
- */
- void (*regulator_enable)(struct dsi_phy_hw *phy,
- struct dsi_phy_per_lane_cfgs *reg_cfg);
-
- /**
- * regulator_disable() - disable regulators
- * @phy: Pointer to DSI PHY hardware object.
- */
- void (*regulator_disable)(struct dsi_phy_hw *phy);
-
- /**
- * enable() - Enable PHY hardware
- * @phy: Pointer to DSI PHY hardware object.
- * @cfg: Per lane configurations for timing, strength and lane
- * configurations.
- */
- void (*enable)(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg);
-
- /**
- * disable() - Disable PHY hardware
- * @phy: Pointer to DSI PHY hardware object.
- */
- void (*disable)(struct dsi_phy_hw *phy);
-
- /**
- * calculate_timing_params() - calculates timing parameters.
- * @phy: Pointer to DSI PHY hardware object.
- * @mode: Mode information for which timing has to be calculated.
- * @config: DSI host configuration for this mode.
- * @timing: Timing parameters for each lane which will be returned.
- */
- int (*calculate_timing_params)(struct dsi_phy_hw *phy,
- struct dsi_mode_info *mode,
- struct dsi_host_common_cfg *config,
- struct dsi_phy_per_lane_cfgs *timing);
-};
-
-/**
- * struct dsi_phy_hw - DSI phy hardware object specific to an instance
- * @base: VA for the DSI PHY base address.
- * @length: Length of the DSI PHY register base map.
- * @index: Instance ID of the controller.
- * @version: DSI PHY version.
- * @feature_map: Features supported by DSI PHY.
- * @ops: Function pointer to PHY operations.
- */
-struct dsi_phy_hw {
- void __iomem *base;
- u32 length;
- u32 index;
-
- enum dsi_phy_version version;
-
- DECLARE_BITMAP(feature_map, DSI_PHY_MAX_FEATURES);
- struct dsi_phy_hw_ops ops;
-};
-
-#endif /* _DSI_PHY_HW_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c
deleted file mode 100644
index 512352d96f98..000000000000
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) "dsi-phy-hw:" fmt
-#include <linux/math64.h>
-#include <linux/delay.h>
-#include "dsi_hw.h"
-#include "dsi_phy_hw.h"
-
-#define DSIPHY_CMN_REVISION_ID0 0x0000
-#define DSIPHY_CMN_REVISION_ID1 0x0004
-#define DSIPHY_CMN_REVISION_ID2 0x0008
-#define DSIPHY_CMN_REVISION_ID3 0x000C
-#define DSIPHY_CMN_CLK_CFG0 0x0010
-#define DSIPHY_CMN_CLK_CFG1 0x0014
-#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018
-#define DSIPHY_CMN_CTRL_0 0x001C
-#define DSIPHY_CMN_CTRL_1 0x0020
-#define DSIPHY_CMN_CAL_HW_TRIGGER 0x0024
-#define DSIPHY_CMN_CAL_SW_CFG0 0x0028
-#define DSIPHY_CMN_CAL_SW_CFG1 0x002C
-#define DSIPHY_CMN_CAL_SW_CFG2 0x0030
-#define DSIPHY_CMN_CAL_HW_CFG0 0x0034
-#define DSIPHY_CMN_CAL_HW_CFG1 0x0038
-#define DSIPHY_CMN_CAL_HW_CFG2 0x003C
-#define DSIPHY_CMN_CAL_HW_CFG3 0x0040
-#define DSIPHY_CMN_CAL_HW_CFG4 0x0044
-#define DSIPHY_CMN_PLL_CNTRL 0x0048
-#define DSIPHY_CMN_LDO_CNTRL 0x004C
-
-#define DSIPHY_CMN_REGULATOR_CAL_STATUS0 0x0064
-#define DSIPHY_CMN_REGULATOR_CAL_STATUS1 0x0068
-
-/* n = 0..3 for data lanes and n = 4 for clock lane */
-#define DSIPHY_DLNX_CFG0(n) (0x100 + ((n) * 0x80))
-#define DSIPHY_DLNX_CFG1(n) (0x104 + ((n) * 0x80))
-#define DSIPHY_DLNX_CFG2(n) (0x108 + ((n) * 0x80))
-#define DSIPHY_DLNX_CFG3(n) (0x10C + ((n) * 0x80))
-#define DSIPHY_DLNX_TEST_DATAPATH(n) (0x110 + ((n) * 0x80))
-#define DSIPHY_DLNX_TEST_STR(n) (0x114 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_4(n) (0x118 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_5(n) (0x11C + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_6(n) (0x120 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_7(n) (0x124 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_8(n) (0x128 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_9(n) (0x12C + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_10(n) (0x130 + ((n) * 0x80))
-#define DSIPHY_DLNX_TIMING_CTRL_11(n) (0x134 + ((n) * 0x80))
-#define DSIPHY_DLNX_STRENGTH_CTRL_0(n) (0x138 + ((n) * 0x80))
-#define DSIPHY_DLNX_STRENGTH_CTRL_1(n) (0x13C + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_POLY(n) (0x140 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_SEED0(n) (0x144 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_SEED1(n) (0x148 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_HEAD(n) (0x14C + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_SOT(n) (0x150 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_CTRL0(n) (0x154 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_CTRL1(n) (0x158 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_CTRL2(n) (0x15C + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_CTRL3(n) (0x160 + ((n) * 0x80))
-#define DSIPHY_DLNX_VREG_CNTRL(n) (0x164 + ((n) * 0x80))
-#define DSIPHY_DLNX_HSTX_STR_STATUS(n) (0x168 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_STATUS0(n) (0x16C + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_STATUS1(n) (0x170 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_STATUS2(n) (0x174 + ((n) * 0x80))
-#define DSIPHY_DLNX_BIST_STATUS3(n) (0x178 + ((n) * 0x80))
-#define DSIPHY_DLNX_MISR_STATUS(n) (0x17C + ((n) * 0x80))
-
-#define DSIPHY_PLL_CLKBUFLR_EN 0x041C
-#define DSIPHY_PLL_PLL_BANDGAP 0x0508
-
-/**
- * struct timing_entry - Calculated values for each timing parameter.
- * @mipi_min:
- * @mipi_max:
- * @rec_min:
- * @rec_max:
- * @rec:
- * @reg_value: Value to be programmed in register.
- */
-struct timing_entry {
- s32 mipi_min;
- s32 mipi_max;
- s32 rec_min;
- s32 rec_max;
- s32 rec;
- u8 reg_value;
-};
-
-/**
- * struct phy_timing_desc - Timing parameters for DSI PHY.
- */
-struct phy_timing_desc {
- struct timing_entry clk_prepare;
- struct timing_entry clk_zero;
- struct timing_entry clk_trail;
- struct timing_entry hs_prepare;
- struct timing_entry hs_zero;
- struct timing_entry hs_trail;
- struct timing_entry hs_rqst;
- struct timing_entry hs_rqst_clk;
- struct timing_entry hs_exit;
- struct timing_entry ta_go;
- struct timing_entry ta_sure;
- struct timing_entry ta_set;
- struct timing_entry clk_post;
- struct timing_entry clk_pre;
-};
-
-/**
- * struct phy_clk_params - Clock parameters for PHY timing calculations.
- */
-struct phy_clk_params {
- u32 bitclk_mbps;
- u32 escclk_numer;
- u32 escclk_denom;
- u32 tlpx_numer_ns;
- u32 treot_ns;
-};
-
-/**
- * regulator_enable() - enable regulators for DSI PHY
- * @phy: Pointer to DSI PHY hardware object.
- * @reg_cfg: Regulator configuration for all DSI lanes.
- */
-void dsi_phy_hw_v4_0_regulator_enable(struct dsi_phy_hw *phy,
- struct dsi_phy_per_lane_cfgs *reg_cfg)
-{
- int i;
-
- for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++)
- DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), reg_cfg->lane[i][0]);
-
- /* make sure all values are written to hardware */
- wmb();
-
- pr_debug("[DSI_%d] Phy regulators enabled\n", phy->index);
-}
-
-/**
- * regulator_disable() - disable regulators
- * @phy: Pointer to DSI PHY hardware object.
- */
-void dsi_phy_hw_v4_0_regulator_disable(struct dsi_phy_hw *phy)
-{
- pr_debug("[DSI_%d] Phy regulators disabled\n", phy->index);
-}
-
-/**
- * enable() - Enable PHY hardware
- * @phy: Pointer to DSI PHY hardware object.
- * @cfg: Per lane configurations for timing, strength and lane
- * configurations.
- */
-void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy,
- struct dsi_phy_cfg *cfg)
-{
- int i;
- struct dsi_phy_per_lane_cfgs *timing = &cfg->timing;
- u32 data;
-
- DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C);
-
- DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0x1);
- for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
-
- DSI_W32(phy, DSIPHY_DLNX_CFG0(i), cfg->lanecfg.lane[i][0]);
- DSI_W32(phy, DSIPHY_DLNX_CFG1(i), cfg->lanecfg.lane[i][1]);
- DSI_W32(phy, DSIPHY_DLNX_CFG2(i), cfg->lanecfg.lane[i][2]);
- DSI_W32(phy, DSIPHY_DLNX_CFG3(i), cfg->lanecfg.lane[i][3]);
-
- DSI_W32(phy, DSIPHY_DLNX_TEST_STR(i), 0x88);
-
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_4(i), timing->lane[i][0]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_5(i), timing->lane[i][1]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_6(i), timing->lane[i][2]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_7(i), timing->lane[i][3]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_8(i), timing->lane[i][4]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_9(i), timing->lane[i][5]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_10(i), timing->lane[i][6]);
- DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_11(i), timing->lane[i][7]);
-
- DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i),
- cfg->strength.lane[i][0]);
- DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i),
- cfg->strength.lane[i][1]);
- }
-
- /* make sure all values are written to hardware before enabling phy */
- wmb();
-
- DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x80);
- udelay(100);
- DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x00);
-
- data = DSI_R32(phy, DSIPHY_CMN_GLBL_TEST_CTRL);
-
- switch (cfg->pll_source) {
- case DSI_PLL_SOURCE_STANDALONE:
- DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x01);
- data &= ~BIT(2);
- break;
- case DSI_PLL_SOURCE_NATIVE:
- DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x03);
- data &= ~BIT(2);
- break;
- case DSI_PLL_SOURCE_NON_NATIVE:
- DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x00);
- data |= BIT(2);
- break;
- default:
- break;
- }
-
- DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, data);
-
- /* Enable bias current for pll1 during split display case */
- if (cfg->pll_source == DSI_PLL_SOURCE_NON_NATIVE)
- DSI_W32(phy, DSIPHY_PLL_PLL_BANDGAP, 0x3);
-
- pr_debug("[DSI_%d]Phy enabled ", phy->index);
-}
-
-/**
- * disable() - Disable PHY hardware
- * @phy: Pointer to DSI PHY hardware object.
- */
-void dsi_phy_hw_v4_0_disable(struct dsi_phy_hw *phy)
-{
- DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0);
- DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0);
- DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0);
- pr_debug("[DSI_%d]Phy disabled ", phy->index);
-}
-
-static const u32 bits_per_pixel[DSI_PIXEL_FORMAT_MAX] = {
- 16, 18, 18, 24, 3, 8, 12 };
-
-/**
- * calc_clk_prepare - calculates prepare timing params for clk lane.
- */
-static int calc_clk_prepare(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- s32 *actual_frac,
- s64 *actual_intermediate)
-{
- u32 const min_prepare_frac = 50;
- u64 const multiplier = BIT(20);
-
- struct timing_entry *t = &desc->clk_prepare;
- int rc = 0;
- u64 dividend, temp, temp_multiple;
- s32 frac = 0;
- s64 intermediate;
- s64 clk_prep_actual;
-
- dividend = ((t->rec_max - t->rec_min) * min_prepare_frac * multiplier);
- temp = roundup(div_s64(dividend, 100), multiplier);
- temp += (t->rec_min * multiplier);
- t->rec = div_s64(temp, multiplier);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor clk_prepare\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- /* calculate theoretical value */
- temp_multiple = 8 * t->reg_value * clk_params->tlpx_numer_ns
- * multiplier;
- intermediate = div_s64(temp_multiple, clk_params->bitclk_mbps);
- div_s64_rem(temp_multiple, clk_params->bitclk_mbps, &frac);
- clk_prep_actual = div_s64((intermediate + frac), multiplier);
-
- pr_debug("CLK_PREPARE:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max);
- pr_debug(" reg_value=%d, actual=%lld\n", t->reg_value, clk_prep_actual);
-
- *actual_frac = frac;
- *actual_intermediate = intermediate;
-
- return rc;
-}
-
-/**
- * calc_clk_zero - calculates zero timing params for clk lane.
- */
-static int calc_clk_zero(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- s32 actual_frac,
- s64 actual_intermediate)
-{
- u32 const clk_zero_min_frac = 2;
- u64 const multiplier = BIT(20);
-
- int rc = 0;
- struct timing_entry *t = &desc->clk_zero;
- s64 mipi_min, rec_temp1, rec_temp2, rec_temp3, rec_min;
-
- mipi_min = ((300 * multiplier) - (actual_intermediate + actual_frac));
- t->mipi_min = div_s64(mipi_min, multiplier);
-
- rec_temp1 = div_s64((mipi_min * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
- rec_temp2 = (rec_temp1 - (11 * multiplier));
- rec_temp3 = roundup(div_s64(rec_temp2, 8), multiplier);
- rec_min = (div_s64(rec_temp3, multiplier) - 3);
- t->rec_min = rec_min;
- t->rec_max = ((t->rec_min > 255) ? 511 : 255);
-
- t->rec = DIV_ROUND_UP(
- (((t->rec_max - t->rec_min) * clk_zero_min_frac) +
- (t->rec_min * 100)),
- 100);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor clk_zero\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("CLK_ZERO:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
- return rc;
-}
-
-/**
- * calc_clk_trail - calculates prepare trail params for clk lane.
- */
-static int calc_clk_trail(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- s64 *teot_clk_lane)
-{
- u64 const multiplier = BIT(20);
- u32 const phy_timing_frac = 30;
-
- int rc = 0;
- struct timing_entry *t = &desc->clk_trail;
- u64 temp_multiple;
- s32 frac;
- s64 mipi_max_tr, rec_temp1, rec_temp2, rec_temp3, mipi_max;
- s64 teot_clk_lane1;
-
- temp_multiple = div_s64(
- (12 * multiplier * clk_params->tlpx_numer_ns),
- clk_params->bitclk_mbps);
- div_s64_rem(temp_multiple, multiplier, &frac);
-
- mipi_max_tr = ((105 * multiplier) +
- (temp_multiple + frac));
- teot_clk_lane1 = div_s64(mipi_max_tr, multiplier);
-
- mipi_max = (mipi_max_tr - (clk_params->treot_ns * multiplier));
- t->mipi_max = div_s64(mipi_max, multiplier);
-
- temp_multiple = div_s64(
- (t->mipi_min * multiplier * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
-
- div_s64_rem(temp_multiple, multiplier, &frac);
- rec_temp1 = temp_multiple + frac + (3 * multiplier);
- rec_temp2 = div_s64(rec_temp1, 8);
- rec_temp3 = roundup(rec_temp2, multiplier);
-
- t->rec_min = div_s64(rec_temp3, multiplier);
-
- /* recommended max */
- rec_temp1 = div_s64((mipi_max * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
- rec_temp2 = rec_temp1 + (3 * multiplier);
- rec_temp3 = rec_temp2 / 8;
- t->rec_max = div_s64(rec_temp3, multiplier);
-
- t->rec = DIV_ROUND_UP(
- (((t->rec_max - t->rec_min) * phy_timing_frac) +
- (t->rec_min * 100)),
- 100);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor clk_zero\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- *teot_clk_lane = teot_clk_lane1;
- pr_debug("CLK_TRAIL:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
- return rc;
-
-}
-
-/**
- * calc_hs_prepare - calculates prepare timing params for data lanes in HS.
- */
-static int calc_hs_prepare(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- u64 *temp_mul)
-{
- u64 const multiplier = BIT(20);
- u32 const min_prepare_frac = 50;
- int rc = 0;
- struct timing_entry *t = &desc->hs_prepare;
- u64 temp_multiple, dividend, temp;
- s32 frac;
- s64 rec_temp1, rec_temp2, mipi_max, mipi_min;
- u32 low_clk_multiplier = 0;
-
- if (clk_params->bitclk_mbps <= 120)
- low_clk_multiplier = 2;
- /* mipi min */
- temp_multiple = div_s64((4 * multiplier * clk_params->tlpx_numer_ns),
- clk_params->bitclk_mbps);
- div_s64_rem(temp_multiple, multiplier, &frac);
- mipi_min = (40 * multiplier) + (temp_multiple + frac);
- t->mipi_min = div_s64(mipi_min, multiplier);
-
- /* mipi_max */
- temp_multiple = div_s64(
- (6 * multiplier * clk_params->tlpx_numer_ns),
- clk_params->bitclk_mbps);
- div_s64_rem(temp_multiple, multiplier, &frac);
- mipi_max = (85 * multiplier) + temp_multiple;
- t->mipi_max = div_s64(mipi_max, multiplier);
-
- /* recommended min */
- temp_multiple = div_s64((mipi_min * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
- temp_multiple -= (low_clk_multiplier * multiplier);
- div_s64_rem(temp_multiple, multiplier, &frac);
- rec_temp1 = roundup(((temp_multiple + frac) / 8), multiplier);
- t->rec_min = div_s64(rec_temp1, multiplier);
-
- /* recommended max */
- temp_multiple = div_s64((mipi_max * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
- temp_multiple -= (low_clk_multiplier * multiplier);
- div_s64_rem(temp_multiple, multiplier, &frac);
- rec_temp2 = rounddown((temp_multiple / 8), multiplier);
- t->rec_max = div_s64(rec_temp2, multiplier);
-
- /* register value */
- dividend = ((rec_temp2 - rec_temp1) * min_prepare_frac);
- temp = roundup(div_u64(dividend, 100), multiplier);
- t->rec = div_s64((temp + rec_temp1), multiplier);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_prepare\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- temp_multiple = div_s64(
- (8 * (temp + rec_temp1) * clk_params->tlpx_numer_ns),
- clk_params->bitclk_mbps);
-
- *temp_mul = temp_multiple;
- pr_debug("HS_PREP:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
- return rc;
-}
-
-/**
- * calc_hs_zero - calculates zero timing params for data lanes in HS.
- */
-static int calc_hs_zero(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- u64 temp_multiple)
-{
- u32 const hs_zero_min_frac = 10;
- u64 const multiplier = BIT(20);
- int rc = 0;
- struct timing_entry *t = &desc->hs_zero;
- s64 rec_temp1, rec_temp2, rec_temp3, mipi_min;
- s64 rec_min;
-
- mipi_min = div_s64((10 * clk_params->tlpx_numer_ns * multiplier),
- clk_params->bitclk_mbps);
- rec_temp1 = (145 * multiplier) + mipi_min - temp_multiple;
- t->mipi_min = div_s64(rec_temp1, multiplier);
-
- /* recommended min */
- rec_temp1 = div_s64((rec_temp1 * clk_params->bitclk_mbps),
- clk_params->tlpx_numer_ns);
- rec_temp2 = rec_temp1 - (11 * multiplier);
- rec_temp3 = roundup((rec_temp2 / 8), multiplier);
- rec_min = rec_temp3 - (3 * multiplier);
- t->rec_min = div_s64(rec_min, multiplier);
- t->rec_max = ((t->rec_min > 255) ? 511 : 255);
-
- t->rec = DIV_ROUND_UP(
- (((t->rec_max - t->rec_min) * hs_zero_min_frac) +
- (t->rec_min * 100)),
- 100);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_zero\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("HS_ZERO:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
-
- return rc;
-}
-
-/**
- * calc_hs_trail - calculates trail timing params for data lanes in HS.
- */
-static int calc_hs_trail(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc,
- u64 teot_clk_lane)
-{
- u32 const phy_timing_frac = 30;
- int rc = 0;
- struct timing_entry *t = &desc->hs_trail;
- s64 rec_temp1;
-
- t->mipi_min = 60 +
- mult_frac(clk_params->tlpx_numer_ns, 4,
- clk_params->bitclk_mbps);
-
- t->mipi_max = teot_clk_lane - clk_params->treot_ns;
-
- t->rec_min = DIV_ROUND_UP(
- ((t->mipi_min * clk_params->bitclk_mbps) +
- (3 * clk_params->tlpx_numer_ns)),
- (8 * clk_params->tlpx_numer_ns));
-
- rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) +
- (3 * clk_params->tlpx_numer_ns));
- t->rec_max = (rec_temp1 / (8 * clk_params->tlpx_numer_ns));
- rec_temp1 = DIV_ROUND_UP(
- ((t->rec_max - t->rec_min) * phy_timing_frac),
- 100);
- t->rec = rec_temp1 + t->rec_min;
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_trail\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("HS_TRAIL:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
-
- return rc;
-}
-
-/**
- * calc_hs_rqst - calculates rqst timing params for data lanes in HS.
- */
-static int calc_hs_rqst(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc)
-{
- int rc = 0;
- struct timing_entry *t = &desc->hs_rqst;
-
- t->rec = DIV_ROUND_UP(
- ((t->mipi_min * clk_params->bitclk_mbps) -
- (8 * clk_params->tlpx_numer_ns)),
- (8 * clk_params->tlpx_numer_ns));
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_rqst, %d\n", t->rec);
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("HS_RQST:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
-
- return rc;
-}
-
-/**
- * calc_hs_exit - calculates exit timing params for data lanes in HS.
- */
-static int calc_hs_exit(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc)
-{
- u32 const hs_exit_min_frac = 10;
- int rc = 0;
- struct timing_entry *t = &desc->hs_exit;
-
- t->rec_min = (DIV_ROUND_UP(
- (t->mipi_min * clk_params->bitclk_mbps),
- (8 * clk_params->tlpx_numer_ns)) - 1);
-
- t->rec = DIV_ROUND_UP(
- (((t->rec_max - t->rec_min) * hs_exit_min_frac) +
- (t->rec_min * 100)),
- 100);
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_exit\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("HS_EXIT:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
-
- return rc;
-}
-
-/**
- * calc_hs_rqst_clk - calculates rqst timing params for clock lane..
- */
-static int calc_hs_rqst_clk(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc)
-{
- int rc = 0;
- struct timing_entry *t = &desc->hs_rqst_clk;
-
- t->rec = DIV_ROUND_UP(
- ((t->mipi_min * clk_params->bitclk_mbps) -
- (8 * clk_params->tlpx_numer_ns)),
- (8 * clk_params->tlpx_numer_ns));
-
- if (t->rec & 0xffffff00) {
- pr_err("Incorrect rec valuefor hs_rqst_clk\n");
- rc = -EINVAL;
- } else {
- t->reg_value = t->rec;
- }
-
- pr_debug("HS_RQST_CLK:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n",
- t->mipi_min, t->mipi_max, t->rec_min, t->rec_max,
- t->reg_value);
-
- return rc;
-}
-
-/**
- * dsi_phy_calc_timing_params - calculates timing paramets for a given bit clock
- */
-static int dsi_phy_calc_timing_params(struct phy_clk_params *clk_params,
- struct phy_timing_desc *desc)
-{
- int rc = 0;
- s32 actual_frac = 0;
- s64 actual_intermediate = 0;
- u64 temp_multiple;
- s64 teot_clk_lane;
-
- rc = calc_clk_prepare(clk_params, desc, &actual_frac,
- &actual_intermediate);
- if (rc) {
- pr_err("clk_prepare calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_clk_zero(clk_params, desc, actual_frac, actual_intermediate);
- if (rc) {
- pr_err("clk_zero calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_clk_trail(clk_params, desc, &teot_clk_lane);
- if (rc) {
- pr_err("clk_trail calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_prepare(clk_params, desc, &temp_multiple);
- if (rc) {
- pr_err("hs_prepare calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_zero(clk_params, desc, temp_multiple);
- if (rc) {
- pr_err("hs_zero calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_trail(clk_params, desc, teot_clk_lane);
- if (rc) {
- pr_err("hs_trail calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_rqst(clk_params, desc);
- if (rc) {
- pr_err("hs_rqst calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_exit(clk_params, desc);
- if (rc) {
- pr_err("hs_exit calculations failed, rc=%d\n", rc);
- goto error;
- }
-
- rc = calc_hs_rqst_clk(clk_params, desc);
- if (rc) {
- pr_err("hs_rqst_clk calculations failed, rc=%d\n", rc);
- goto error;
- }
-error:
- return rc;
-}
-
-/**
- * calculate_timing_params() - calculates timing parameters.
- * @phy: Pointer to DSI PHY hardware object.
- * @mode: Mode information for which timing has to be calculated.
- * @config: DSI host configuration for this mode.
- * @timing: Timing parameters for each lane which will be returned.
- */
-int dsi_phy_hw_v4_0_calculate_timing_params(struct dsi_phy_hw *phy,
- struct dsi_mode_info *mode,
- struct dsi_host_common_cfg *host,
- struct dsi_phy_per_lane_cfgs *timing)
-{
- /* constants */
- u32 const esc_clk_mhz = 192; /* TODO: esc clock is hardcoded */
- u32 const esc_clk_mmss_cc_prediv = 10;
- u32 const tlpx_numer = 1000;
- u32 const tr_eot = 20;
- u32 const clk_prepare_spec_min = 38;
- u32 const clk_prepare_spec_max = 95;
- u32 const clk_trail_spec_min = 60;
- u32 const hs_exit_spec_min = 100;
- u32 const hs_exit_reco_max = 255;
- u32 const hs_rqst_spec_min = 50;
-
- /* local vars */
- int rc = 0;
- int i;
- u32 h_total, v_total;
- u64 inter_num;
- u32 num_of_lanes = 0;
- u32 bpp;
- u64 x, y;
- struct phy_timing_desc desc;
- struct phy_clk_params clk_params = {0};
-
- memset(&desc, 0x0, sizeof(desc));
- h_total = DSI_H_TOTAL(mode);
- v_total = DSI_V_TOTAL(mode);
-
- bpp = bits_per_pixel[host->dst_format];
-
- inter_num = bpp * mode->refresh_rate;
-
- if (host->data_lanes & DSI_DATA_LANE_0)
- num_of_lanes++;
- if (host->data_lanes & DSI_DATA_LANE_1)
- num_of_lanes++;
- if (host->data_lanes & DSI_DATA_LANE_2)
- num_of_lanes++;
- if (host->data_lanes & DSI_DATA_LANE_3)
- num_of_lanes++;
-
-
- x = mult_frac(v_total * h_total, inter_num, num_of_lanes);
- y = rounddown(x, 1);
-
- clk_params.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1);
- clk_params.escclk_numer = esc_clk_mhz;
- clk_params.escclk_denom = esc_clk_mmss_cc_prediv;
- clk_params.tlpx_numer_ns = tlpx_numer;
- clk_params.treot_ns = tr_eot;
-
-
- /* Setup default parameters */
- desc.clk_prepare.mipi_min = clk_prepare_spec_min;
- desc.clk_prepare.mipi_max = clk_prepare_spec_max;
- desc.clk_trail.mipi_min = clk_trail_spec_min;
- desc.hs_exit.mipi_min = hs_exit_spec_min;
- desc.hs_exit.rec_max = hs_exit_reco_max;
-
- desc.clk_prepare.rec_min = DIV_ROUND_UP(
- (desc.clk_prepare.mipi_min * clk_params.bitclk_mbps),
- (8 * clk_params.tlpx_numer_ns)
- );
-
- desc.clk_prepare.rec_max = rounddown(
- mult_frac((desc.clk_prepare.mipi_max * clk_params.bitclk_mbps),
- 1, (8 * clk_params.tlpx_numer_ns)),
- 1);
-
- desc.hs_rqst.mipi_min = hs_rqst_spec_min;
- desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min;
-
- pr_debug("BIT CLOCK = %d, tlpx_numer_ns=%d, treot_ns=%d\n",
- clk_params.bitclk_mbps, clk_params.tlpx_numer_ns,
- clk_params.treot_ns);
- rc = dsi_phy_calc_timing_params(&clk_params, &desc);
- if (rc) {
- pr_err("Timing calc failed, rc=%d\n", rc);
- goto error;
- }
-
-
- for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
- timing->lane[i][0] = desc.hs_exit.reg_value;
-
- if (i == DSI_LOGICAL_CLOCK_LANE)
- timing->lane[i][1] = desc.clk_zero.reg_value;
- else
- timing->lane[i][1] = desc.hs_zero.reg_value;
-
- if (i == DSI_LOGICAL_CLOCK_LANE)
- timing->lane[i][2] = desc.clk_prepare.reg_value;
- else
- timing->lane[i][2] = desc.hs_prepare.reg_value;
-
- if (i == DSI_LOGICAL_CLOCK_LANE)
- timing->lane[i][3] = desc.clk_trail.reg_value;
- else
- timing->lane[i][3] = desc.hs_trail.reg_value;
-
- if (i == DSI_LOGICAL_CLOCK_LANE)
- timing->lane[i][4] = desc.hs_rqst_clk.reg_value;
- else
- timing->lane[i][4] = desc.hs_rqst.reg_value;
-
- timing->lane[i][5] = 0x3;
- timing->lane[i][6] = 0x4;
- timing->lane[i][7] = 0xA0;
- pr_debug("[%d][%d %d %d %d %d]\n", i, timing->lane[i][0],
- timing->lane[i][1],
- timing->lane[i][2],
- timing->lane[i][3],
- timing->lane[i][4]);
- }
- timing->count_per_lane = 8;
-
-error:
- return rc;
-}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 210cedb8134d..b532faa8026d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -595,8 +595,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
mdelay(16);
if (config->platform.iommu) {
- mmu = msm_smmu_new(&pdev->dev,
- MSM_SMMU_DOMAIN_UNSECURE);
+ mmu = msm_iommu_new(&pdev->dev, config->platform.iommu);
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
dev_err(dev->dev, "failed to init iommu: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 67c4518e22e1..b88ce514eb8e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -235,20 +235,13 @@ static int msm_unload(struct drm_device *dev)
return 0;
}
-#define KMS_MDP4 0
-#define KMS_MDP5 1
-#define KMS_SDE 2
-
static int get_mdp_ver(struct platform_device *pdev)
{
#ifdef CONFIG_OF
static const struct of_device_id match_types[] = { {
.compatible = "qcom,mdss_mdp",
- .data = (void *)KMS_MDP5,
- },
- {
- .compatible = "qcom,sde-kms",
- .data = (void *)KMS_SDE,
+ .data = (void *)5,
+ }, {
/* end node */
} };
struct device *dev = &pdev->dev;
@@ -257,7 +250,7 @@ static int get_mdp_ver(struct platform_device *pdev)
if (match)
return (int)(unsigned long)match->data;
#endif
- return KMS_MDP4;
+ return 4;
}
#include <linux/of_address.h>
@@ -376,15 +369,12 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
goto fail;
switch (get_mdp_ver(pdev)) {
- case KMS_MDP4:
+ case 4:
kms = mdp4_kms_init(dev);
break;
- case KMS_MDP5:
+ case 5:
kms = mdp5_kms_init(dev);
break;
- case KMS_SDE:
- kms = sde_kms_init(dev);
- break;
default:
kms = ERR_PTR(-ENODEV);
break;
@@ -1150,7 +1140,6 @@ static const struct platform_device_id msm_id[] = {
static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,mdp" }, /* mdp4 */
{ .compatible = "qcom,mdss_mdp" }, /* mdp5 */
- { .compatible = "qcom,sde-kms" }, /* sde */
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e4ebc0fa2f51..3be7a56b14f1 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -55,12 +55,7 @@ struct msm_rd_state;
struct msm_perf_state;
struct msm_gem_submit;
-#define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */
-#define MAX_CRTCS 8
-#define MAX_PLANES 12
-#define MAX_ENCODERS 8
-#define MAX_BRIDGES 8
-#define MAX_CONNECTORS 8
+#define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */
struct msm_file_private {
/* currently we don't do anything useful with this.. but when
@@ -133,19 +128,19 @@ struct msm_drm_private {
struct msm_mmu *mmus[NUM_DOMAINS];
unsigned int num_planes;
- struct drm_plane *planes[MAX_PLANES];
+ struct drm_plane *planes[8];
unsigned int num_crtcs;
- struct drm_crtc *crtcs[MAX_CRTCS];
+ struct drm_crtc *crtcs[8];
unsigned int num_encoders;
- struct drm_encoder *encoders[MAX_ENCODERS];
+ struct drm_encoder *encoders[8];
unsigned int num_bridges;
- struct drm_bridge *bridges[MAX_BRIDGES];
+ struct drm_bridge *bridges[8];
unsigned int num_connectors;
- struct drm_connector *connectors[MAX_CONNECTORS];
+ struct drm_connector *connectors[8];
/* Properties */
struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 6fa56abf0c78..c76cc853b08a 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -295,23 +295,16 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
if (iommu_present(&platform_bus_type)) {
struct msm_mmu *mmu = priv->mmus[id];
+ uint32_t offset;
if (WARN_ON(!mmu))
return -EINVAL;
- if (obj->import_attach && mmu->funcs->map_dma_buf) {
- ret = mmu->funcs->map_dma_buf(mmu, msm_obj->sgt,
- obj->import_attach->dmabuf,
- DMA_BIDIRECTIONAL);
- if (ret) {
- DRM_ERROR("Unable to map dma buf\n");
- return ret;
- }
- }
- msm_obj->domain[id].iova =
- sg_dma_address(msm_obj->sgt->sgl);
+ offset = (uint32_t)mmap_offset(obj);
+ ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
+ obj->size, IOMMU_READ | IOMMU_WRITE);
+ msm_obj->domain[id].iova = offset;
} else {
- WARN_ONCE(1, "physical address being used\n");
msm_obj->domain[id].iova = physaddr(obj);
}
}
@@ -531,11 +524,8 @@ void msm_gem_free_object(struct drm_gem_object *obj)
for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
struct msm_mmu *mmu = priv->mmus[id];
if (mmu && msm_obj->domain[id].iova) {
- if (obj->import_attach && mmu->funcs->unmap_dma_buf) {
- mmu->funcs->unmap_dma_buf(mmu, msm_obj->sgt,
- obj->import_attach->dmabuf,
- DMA_BIDIRECTIONAL);
- }
+ uint32_t offset = msm_obj->domain[id].iova;
+ mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size);
}
}
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 2e4ae6b1c5d0..6fc59bfeedeb 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -53,7 +53,8 @@ struct msm_gem_object {
void *vaddr;
struct {
- dma_addr_t iova;
+ // XXX
+ uint32_t iova;
} domain[NUM_DOMAINS];
/* normally (resv == &_resv) except for imported bo's */
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index f2e1a4fb9fae..9bcabaada179 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -76,6 +76,5 @@ static inline void msm_kms_init(struct msm_kms *kms,
struct msm_kms *mdp4_kms_init(struct drm_device *dev);
struct msm_kms *mdp5_kms_init(struct drm_device *dev);
-struct msm_kms *sde_kms_init(struct drm_device *dev);
#endif /* __MSM_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 6d2f5627bfae..7cd88d9dc155 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -20,14 +20,6 @@
#include <linux/iommu.h>
-struct msm_mmu;
-struct msm_gpu;
-
-enum msm_mmu_domain_type {
- MSM_SMMU_DOMAIN_UNSECURE,
- MSM_SMMU_DOMAIN_MAX,
-};
-
struct msm_mmu_funcs {
int (*attach)(struct msm_mmu *mmu, const char **names, int cnt);
void (*detach)(struct msm_mmu *mmu, const char **names, int cnt);
@@ -35,14 +27,6 @@ struct msm_mmu_funcs {
unsigned len, int prot);
int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
unsigned len);
- int (*map_sg)(struct msm_mmu *mmu, struct sg_table *sgt,
- enum dma_data_direction dir);
- void (*unmap_sg)(struct msm_mmu *mmu, struct sg_table *sgt,
- enum dma_data_direction dir);
- int (*map_dma_buf)(struct msm_mmu *mmu, struct sg_table *sgt,
- struct dma_buf *dma_buf, int dir);
- void (*unmap_dma_buf)(struct msm_mmu *mmu, struct sg_table *sgt,
- struct dma_buf *dma_buf, int dir);
void (*destroy)(struct msm_mmu *mmu);
};
@@ -60,7 +44,5 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
-struct msm_mmu *msm_smmu_new(struct device *dev,
- enum msm_mmu_domain_type domain);
#endif /* __MSM_MMU_H__ */
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
deleted file mode 100644
index d51fbedf90c6..000000000000
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/pm_runtime.h>
-#include <linux/msm_dma_iommu_mapping.h>
-
-#include <asm/dma-iommu.h>
-#include <soc/qcom/secure_buffer.h>
-
-#include "msm_drv.h"
-#include "msm_mmu.h"
-
-struct msm_smmu_client {
- struct device *dev;
- struct dma_iommu_mapping *mmu_mapping;
- bool domain_attached;
-};
-
-struct msm_smmu {
- struct msm_mmu base;
- struct device *client_dev;
- struct msm_smmu_client client;
-};
-
-struct msm_smmu_domain {
- const char *label;
- size_t va_start;
- size_t va_size;
- bool secure;
-};
-
-#define to_msm_smmu(x) container_of(x, struct msm_smmu, base)
-#define msm_smmu_to_client(smmu) (&smmu->client)
-
-static int _msm_smmu_create_mapping(struct msm_smmu_client *client,
- const struct msm_smmu_domain *domain);
-
-static int msm_smmu_attach(struct msm_mmu *mmu, const char **names, int cnt)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- int rc = 0;
-
- /* domain attach only once */
- if (client->domain_attached)
- return 0;
-
- rc = arm_iommu_attach_device(client->dev,
- client->mmu_mapping);
- if (rc) {
- dev_err(client->dev, "iommu attach dev failed (%d)\n",
- rc);
- return rc;
- }
-
- client->domain_attached = true;
-
- dev_dbg(client->dev, "iommu domain attached\n");
-
- return 0;
-}
-
-static void msm_smmu_detach(struct msm_mmu *mmu, const char **names, int cnt)
-{
- DBG("detaching");
-}
-
-static int msm_smmu_map(struct msm_mmu *mmu, uint32_t iova,
- struct sg_table *sgt, unsigned len, int prot)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- struct iommu_domain *domain;
- struct scatterlist *sg;
- unsigned int da = iova;
- unsigned int i, j;
- int ret;
-
- if (!client)
- return -ENODEV;
-
- domain = client->mmu_mapping->domain;
- if (!domain || !sgt)
- return -EINVAL;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- u32 pa = sg_phys(sg) - sg->offset;
- size_t bytes = sg->length + sg->offset;
-
- VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
-
- ret = iommu_map(domain, da, pa, bytes, prot);
- if (ret)
- goto fail;
-
- da += bytes;
- }
-
- return 0;
-
-fail:
- da = iova;
-
- for_each_sg(sgt->sgl, sg, i, j) {
- size_t bytes = sg->length + sg->offset;
-
- iommu_unmap(domain, da, bytes);
- da += bytes;
- }
- return ret;
-}
-
-static int msm_smmu_map_sg(struct msm_mmu *mmu, struct sg_table *sgt,
- enum dma_data_direction dir)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- int ret;
-
- ret = dma_map_sg(client->dev, sgt->sgl, sgt->nents, dir);
- if (ret != sgt->nents)
- return -ENOMEM;
-
- return 0;
-}
-
-static void msm_smmu_unmap_sg(struct msm_mmu *mmu, struct sg_table *sgt,
- enum dma_data_direction dir)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
-
- dma_unmap_sg(client->dev, sgt->sgl, sgt->nents, dir);
-}
-
-static int msm_smmu_unmap(struct msm_mmu *mmu, uint32_t iova,
- struct sg_table *sgt, unsigned len)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- struct iommu_domain *domain;
- struct scatterlist *sg;
- unsigned int da = iova;
- int i;
-
- if (!client)
- return -ENODEV;
-
- domain = client->mmu_mapping->domain;
- if (!domain || !sgt)
- return -EINVAL;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- size_t bytes = sg->length + sg->offset;
- size_t unmapped;
-
- unmapped = iommu_unmap(domain, da, bytes);
- if (unmapped < bytes)
- return unmapped;
-
- VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);
-
- WARN_ON(!PAGE_ALIGNED(bytes));
-
- da += bytes;
- }
-
- return 0;
-}
-
-static void msm_smmu_destroy(struct msm_mmu *mmu)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct platform_device *pdev = to_platform_device(smmu->client_dev);
-
- platform_device_unregister(pdev);
- kfree(smmu);
-}
-
-static int msm_smmu_map_dma_buf(struct msm_mmu *mmu, struct sg_table *sgt,
- struct dma_buf *dma_buf, int dir)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- int ret;
-
- ret = msm_dma_map_sg_lazy(client->dev, sgt->sgl, sgt->nents, dir,
- dma_buf);
- if (ret != sgt->nents) {
- DRM_ERROR("dma map sg failed\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-
-static void msm_smmu_unmap_dma_buf(struct msm_mmu *mmu, struct sg_table *sgt,
- struct dma_buf *dma_buf, int dir)
-{
- struct msm_smmu *smmu = to_msm_smmu(mmu);
- struct msm_smmu_client *client = msm_smmu_to_client(smmu);
-
- msm_dma_unmap_sg(client->dev, sgt->sgl, sgt->nents, dir, dma_buf);
-}
-
-static const struct msm_mmu_funcs funcs = {
- .attach = msm_smmu_attach,
- .detach = msm_smmu_detach,
- .map = msm_smmu_map,
- .map_sg = msm_smmu_map_sg,
- .unmap_sg = msm_smmu_unmap_sg,
- .unmap = msm_smmu_unmap,
- .map_dma_buf = msm_smmu_map_dma_buf,
- .unmap_dma_buf = msm_smmu_unmap_dma_buf,
- .destroy = msm_smmu_destroy,
-};
-
-static struct msm_smmu_domain msm_smmu_domains[MSM_SMMU_DOMAIN_MAX] = {
- [MSM_SMMU_DOMAIN_UNSECURE] = {
- .label = "mdp_ns",
- .va_start = SZ_1M,
- .va_size = SZ_2G,
- },
-};
-
-static const struct of_device_id msm_smmu_dt_match[] = {
- { .compatible = "qcom,smmu_mdp_unsec",
- .data = &msm_smmu_domains[MSM_SMMU_DOMAIN_UNSECURE] },
- {}
-};
-MODULE_DEVICE_TABLE(of, msm_smmu_dt_match);
-
-static struct device *msm_smmu_device_create(struct device *dev,
- enum msm_mmu_domain_type domain,
- struct msm_smmu *smmu)
-{
- struct device_node *child;
- struct platform_device *pdev;
- int i;
- const char *compat = NULL;
-
- for (i = 0; i < ARRAY_SIZE(msm_smmu_dt_match); i++) {
- if (msm_smmu_dt_match[i].data == &msm_smmu_domains[domain]) {
- compat = msm_smmu_dt_match[i].compatible;
- break;
- }
- }
-
- if (!compat) {
- DRM_ERROR("unable to find matching domain for %d\n", domain);
- return ERR_PTR(-ENOENT);
- }
- DRM_INFO("found domain %d compat: %s\n", domain, compat);
-
- if (domain == MSM_SMMU_DOMAIN_UNSECURE) {
- int rc;
-
- smmu->client.dev = dev;
- rc = _msm_smmu_create_mapping(msm_smmu_to_client(smmu),
- msm_smmu_dt_match[i].data);
- if (rc)
- return ERR_PTR(rc);
-
- return NULL;
- }
-
- child = of_find_compatible_node(dev->of_node, NULL, compat);
- if (!child) {
- DRM_ERROR("unable to find compatible node for %s\n", compat);
- return ERR_PTR(-ENODEV);
- }
-
- pdev = of_platform_device_create(child, NULL, dev);
- if (!pdev) {
- DRM_ERROR("unable to create smmu platform dev for domain %d\n",
- domain);
- return ERR_PTR(-ENODEV);
- }
-
- return &pdev->dev;
-}
-
-struct msm_mmu *msm_smmu_new(struct device *dev,
- enum msm_mmu_domain_type domain)
-{
- struct msm_smmu *smmu;
- struct device *client_dev;
-
- smmu = kzalloc(sizeof(*smmu), GFP_KERNEL);
- if (!smmu)
- return ERR_PTR(-ENOMEM);
-
- client_dev = msm_smmu_device_create(dev, domain, smmu);
- if (IS_ERR(client_dev))
- return (void *)client_dev ? : ERR_PTR(-ENODEV);
-
- smmu->client_dev = client_dev;
- msm_mmu_init(&smmu->base, dev, &funcs);
-
- return &smmu->base;
-}
-
-static int _msm_smmu_create_mapping(struct msm_smmu_client *client,
- const struct msm_smmu_domain *domain)
-{
- int disable_htw = 1;
- int rc;
-
- client->mmu_mapping = arm_iommu_create_mapping(&platform_bus_type,
- domain->va_start, domain->va_size);
- if (IS_ERR(client->mmu_mapping)) {
- dev_err(client->dev,
- "iommu create mapping failed for domain=%s\n",
- domain->label);
- return PTR_ERR(client->mmu_mapping);
- }
-
- if (domain->secure) {
- int secure_vmid = VMID_CP_PIXEL;
-
- rc = iommu_domain_set_attr(client->mmu_mapping->domain,
- DOMAIN_ATTR_SECURE_VMID, &secure_vmid);
- if (rc) {
- dev_err(client->dev, "couldn't set secure pix vmid\n");
- goto error;
- }
- }
-
- return 0;
-
-error:
- arm_iommu_release_mapping(client->mmu_mapping);
- return rc;
-}
-
-/**
- * msm_smmu_probe()
- * @pdev: platform device
- *
- * Each smmu context acts as a separate device and the context banks are
- * configured with a VA range.
- * Registers the clks as each context bank has its own clks, for which voting
- * has to be done everytime before using that context bank.
- */
-static int msm_smmu_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- struct msm_smmu_client *client;
- const struct msm_smmu_domain *domain;
- int rc;
-
- match = of_match_device(msm_smmu_dt_match, &pdev->dev);
- if (!match || !match->data) {
- dev_err(&pdev->dev, "probe failed as match data is invalid\n");
- return -EINVAL;
- }
-
- domain = match->data;
- if (!domain) {
- dev_err(&pdev->dev, "no matching device found\n");
- return -EINVAL;
- }
-
- DRM_INFO("probing device %s\n", match->compatible);
-
- client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
-
- client->dev = &pdev->dev;
-
- rc = _msm_smmu_create_mapping(client, domain);
- platform_set_drvdata(pdev, client);
-
- return rc;
-}
-
-static int msm_smmu_remove(struct platform_device *pdev)
-{
- struct msm_smmu_client *client;
-
- client = platform_get_drvdata(pdev);
- if (client->domain_attached) {
- arm_iommu_detach_device(client->dev);
- client->domain_attached = false;
- }
- arm_iommu_release_mapping(client->mmu_mapping);
-
- return 0;
-}
-
-static struct platform_driver msm_smmu_driver = {
- .probe = msm_smmu_probe,
- .remove = msm_smmu_remove,
- .driver = {
- .name = "msmdrm_smmu",
- .of_match_table = msm_smmu_dt_match,
- },
-};
-
-static int __init msm_smmu_driver_init(void)
-{
- int ret;
-
- ret = platform_driver_register(&msm_smmu_driver);
- if (ret)
- pr_err("mdss_smmu_register_driver() failed!\n");
-
- return ret;
-}
-module_init(msm_smmu_driver_init);
-
-static void __exit msm_smmu_driver_cleanup(void)
-{
- platform_driver_unregister(&msm_smmu_driver);
-}
-module_exit(msm_smmu_driver_cleanup);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MSM SMMU driver");
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
deleted file mode 100644
index 5fc1664fd9a0..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/sort.h>
-#include <drm/drm_mode.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_flip_work.h>
-
-#include "sde_kms.h"
-#include "sde_hw_lm.h"
-#include "sde_hw_mdp_ctl.h"
-#include "sde_crtc.h"
-
-#define CTL(i) (CTL_0 + (i))
-#define LM(i) (LM_0 + (i))
-#define INTF(i) (INTF_0 + (i))
-
-static struct sde_kms *get_kms(struct drm_crtc *crtc)
-{
- struct msm_drm_private *priv = crtc->dev->dev_private;
- return to_sde_kms(priv->kms);
-}
-
-static int sde_crtc_reserve_hw_resources(struct drm_crtc *crtc,
- struct drm_encoder *encoder)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_kms *sde_kms = get_kms(crtc);
- struct sde_encoder_hw_resources enc_hw_res;
- const struct sde_hw_res_map *plat_hw_res_map;
- enum sde_lm unused_lm_id[CRTC_DUAL_MIXERS] = {0};
- enum sde_lm lm_idx;
- int i, count = 0;
-
- if (!sde_kms) {
- DBG("[%s] invalid kms", __func__);
- return -EINVAL;
- }
-
- if (!sde_kms->mmio)
- return -EINVAL;
-
- /* Get unused LMs */
- for (i = 0; i < sde_kms->catalog->mixer_count; i++) {
- if (!sde_rm_get_mixer(sde_kms, LM(i))) {
- unused_lm_id[count++] = LM(i);
- if (count == CRTC_DUAL_MIXERS)
- break;
- }
- }
-
- /* query encoder resources */
- sde_encoder_get_hw_resources(sde_crtc->encoder, &enc_hw_res);
-
- /* parse encoder hw resources, find CTL paths */
- for (i = CTL_0; i <= sde_kms->catalog->ctl_count; i++) {
- WARN_ON(sde_crtc->num_ctls > CRTC_DUAL_MIXERS);
- if (enc_hw_res.ctls[i]) {
- struct sde_crtc_mixer *mixer =
- &sde_crtc->mixer[sde_crtc->num_ctls];
- mixer->hw_ctl = sde_rm_get_ctl_path(sde_kms, i);
- if (IS_ERR_OR_NULL(mixer->hw_ctl)) {
- DBG("[%s], Invalid ctl_path", __func__);
- return -EACCES;
- }
- sde_crtc->num_ctls++;
- }
- }
-
- /* shortcut this process if encoder has no ctl paths */
- if (!sde_crtc->num_ctls)
- return 0;
-
- /*
- * Get default LMs if specified in platform config
- * other wise acquire the free LMs
- */
- for (i = INTF_0; i <= sde_kms->catalog->intf_count; i++) {
- if (enc_hw_res.intfs[i]) {
- struct sde_crtc_mixer *mixer =
- &sde_crtc->mixer[sde_crtc->num_mixers];
- plat_hw_res_map = sde_rm_get_res_map(sde_kms, i);
-
- lm_idx = plat_hw_res_map->lm;
- if (!lm_idx)
- lm_idx = unused_lm_id[sde_crtc->num_mixers];
-
- DBG("Acquiring LM %d", lm_idx);
- mixer->hw_lm = sde_rm_acquire_mixer(sde_kms, lm_idx);
- if (IS_ERR_OR_NULL(mixer->hw_lm)) {
- DBG("[%s], Invalid mixer", __func__);
- return -EACCES;
- }
- /* interface info */
- mixer->intf_idx = i;
- mixer->mode = enc_hw_res.intfs[i];
- sde_crtc->num_mixers++;
- }
- }
-
- DBG("control paths %d, num_mixers %d, lm[0] %d, ctl[0] %d ",
- sde_crtc->num_ctls, sde_crtc->num_mixers,
- sde_crtc->mixer[0].hw_lm->idx,
- sde_crtc->mixer[0].hw_ctl->idx);
- if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
- DBG("lm[1] %d, ctl[1], %d",
- sde_crtc->mixer[1].hw_lm->idx,
- sde_crtc->mixer[1].hw_ctl->idx);
- return 0;
-}
-
-static void sde_crtc_destroy(struct drm_crtc *crtc)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
-
- DBG("");
- drm_crtc_cleanup(crtc);
- kfree(sde_crtc);
-}
-
-static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- DBG("");
- return true;
-}
-
-static void sde_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_crtc_mixer *mixer = sde_crtc->mixer;
- struct drm_device *dev = crtc->dev;
- struct sde_hw_mixer *lm;
- unsigned long flags;
- struct drm_display_mode *mode;
- struct sde_hw_mixer_cfg cfg;
- u32 mixer_width;
- int i;
- int rc;
-
- DBG("");
- if (WARN_ON(!crtc->state))
- return;
-
- mode = &crtc->state->adjusted_mode;
-
- DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- sde_crtc->name, mode->base.id, mode->name,
- mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start,
- mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start,
- mode->vsync_end, mode->vtotal,
- mode->type, mode->flags);
-
- /*
- * reserve mixer(s) if not already avaialable
- * if dual mode, mixer_width = half mode width
- * program mode configuration on mixer(s)
- */
- if ((sde_crtc->num_ctls == 0) ||
- (sde_crtc->num_mixers == 0)) {
- rc = sde_crtc_reserve_hw_resources(crtc, sde_crtc->encoder);
- if (rc) {
- dev_err(dev->dev, " error reserving HW resource for this CRTC\n");
- return;
- }
- }
-
- if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
- mixer_width = mode->hdisplay >> 1;
- else
- mixer_width = mode->hdisplay;
-
- spin_lock_irqsave(&sde_crtc->lm_lock, flags);
-
- for (i = 0; i < sde_crtc->num_mixers; i++) {
- lm = mixer[i].hw_lm;
- cfg.out_width = mixer_width;
- cfg.out_height = mode->vdisplay;
- cfg.right_mixer = (i == 0) ? false : true;
- cfg.flags = 0;
- lm->ops.setup_mixer_out(lm, &cfg);
- }
-
- spin_unlock_irqrestore(&sde_crtc->lm_lock, flags);
-}
-
-static void sde_crtc_get_blend_cfg(struct sde_hw_blend_cfg *cfg,
- struct sde_plane_state *pstate)
-{
- const struct mdp_format *format;
- struct drm_plane *plane;
-
- format = to_mdp_format(
- msm_framebuffer_format(pstate->base.fb));
- plane = pstate->base.plane;
-
- cfg->fg.alpha_sel = ALPHA_FG_CONST;
- cfg->bg.alpha_sel = ALPHA_BG_CONST;
- cfg->fg.const_alpha = pstate->alpha;
- cfg->bg.const_alpha = 0xFF - pstate->alpha;
-
- if (format->alpha_enable && pstate->premultiplied) {
- cfg->fg.alpha_sel = ALPHA_FG_CONST;
- cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
- if (pstate->alpha != 0xff) {
- cfg->bg.const_alpha = pstate->alpha;
- cfg->bg.inv_alpha_sel = 1;
- cfg->bg.mod_alpha = 1;
- } else {
- cfg->bg.inv_mode_alpha = 1;
- }
- } else if (format->alpha_enable) {
- cfg->fg.alpha_sel = ALPHA_FG_PIXEL;
- cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
- if (pstate->alpha != 0xff) {
- cfg->bg.const_alpha = pstate->alpha;
- cfg->fg.mod_alpha = 1;
- cfg->bg.inv_alpha_sel = 1;
- cfg->bg.mod_alpha = 1;
- cfg->bg.inv_mode_alpha = 1;
- } else {
- cfg->bg.inv_mode_alpha = 1;
- }
- }
-}
-
-static void blend_setup(struct drm_crtc *crtc)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_crtc_mixer *mixer = sde_crtc->mixer;
- struct drm_plane *plane;
- struct sde_plane_state *pstate, *pstates[SDE_STAGE_MAX] = {0};
- struct sde_hw_stage_cfg stage_cfg;
- struct sde_hw_blend_cfg blend;
- struct sde_hw_ctl *ctl;
- struct sde_hw_mixer *lm;
- u32 flush_mask = 0;
- unsigned long flags;
- int i, j, plane_cnt = 0;
-
- DBG("");
- spin_lock_irqsave(&sde_crtc->lm_lock, flags);
-
- /* ctl could be reserved already */
- if (!sde_crtc->num_ctls)
- goto out;
-
- /* initialize stage cfg */
- memset(&stage_cfg, 0, sizeof(stage_cfg));
- memset(&blend, 0, sizeof(blend));
-
- /* Collect all plane information */
- drm_atomic_crtc_for_each_plane(plane, crtc) {
- pstate = to_sde_plane_state(plane->state);
- pstates[pstate->stage] = pstate;
- plane_cnt++;
- for (i = 0; i < sde_crtc->num_mixers; i++) {
- stage_cfg.stage[pstate->stage][i] =
- sde_plane_pipe(plane);
-
- /* Cache the flushmask for this layer
- * sourcesplit is always enabled, so this layer will
- * be staged on both the mixers
- */
- ctl = mixer[i].hw_ctl;
- ctl->ops.get_bitmask_sspp(ctl, &flush_mask,
- sde_plane_pipe(plane));
- }
- }
-
- /*
- * If there is no base layer, enable border color.
- * currently border color is always black
- */
- if ((stage_cfg.stage[SDE_STAGE_BASE][0] == SSPP_NONE) &&
- plane_cnt) {
- stage_cfg.border_enable = 1;
- DBG("Border Color is enabled\n");
- }
-
- /* Program hw */
- for (i = 0; i < sde_crtc->num_mixers; i++) {
- if (!mixer[i].hw_lm)
- continue;
-
- if (!mixer[i].hw_ctl)
- continue;
-
- ctl = mixer[i].hw_ctl;
- lm = mixer[i].hw_lm;
-
- /* stage config */
- ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
- &stage_cfg);
- /* stage config flush mask */
- mixer[i].flush_mask = flush_mask;
- /* get the flush mask for mixer */
- ctl->ops.get_bitmask_mixer(ctl, &mixer[i].flush_mask,
- mixer[i].hw_lm->idx);
-
- /* blend config */
- for (j = SDE_STAGE_0; j < SDE_STAGE_MAX; j++) {
- if (!pstates[j])
- continue;
- sde_crtc_get_blend_cfg(&blend, pstates[j]);
- blend.fg.alpha_sel = ALPHA_FG_CONST;
- blend.bg.alpha_sel = ALPHA_BG_CONST;
- blend.fg.const_alpha = pstate->alpha;
- blend.bg.const_alpha = 0xFF - pstate->alpha;
- lm->ops.setup_blend_config(lm, j, &blend);
- }
- }
-out:
- spin_unlock_irqrestore(&sde_crtc->lm_lock, flags);
-}
-
-/* if file!=NULL, this is preclose potential cancel-flip path */
-static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct drm_pending_vblank_event *event;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
- event = sde_crtc->event;
- if (event) {
- /* if regular vblank case (!file) or if cancel-flip from
- * preclose on file that requested flip, then send the
- * event:
- */
- if (!file || (event->base.file_priv == file)) {
- sde_crtc->event = NULL;
- DBG("%s: send event: %pK", sde_crtc->name, event);
- drm_send_vblank_event(dev, sde_crtc->id, event);
- }
- }
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void sde_crtc_vblank_cb(void *data)
-{
- struct drm_crtc *crtc = (struct drm_crtc *)data;
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- unsigned pending;
-
- /* unregister callback */
- sde_encoder_register_vblank_callback(sde_crtc->encoder, NULL, NULL);
-
- pending = atomic_xchg(&sde_crtc->pending, 0);
-
- if (pending & PENDING_FLIP)
- complete_flip(crtc, NULL);
-}
-
-static int frame_flushed(struct sde_crtc *sde_crtc)
-{
- struct vsync_info vsync;
-
- /* encoder get vsync_info */
- /* if frame_count does not match frame is flushed */
- sde_encoder_get_vsync_info(sde_crtc->encoder, &vsync);
-
- return (vsync.frame_count & sde_crtc->vsync_count);
-
-}
-
-void sde_crtc_wait_for_commit_done(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- u32 pending;
- int i, ret;
-
- /* ref count the vblank event */
- ret = drm_crtc_vblank_get(crtc);
- if (ret)
- return;
-
- /* register callback */
- sde_encoder_register_vblank_callback(sde_crtc->encoder,
- sde_crtc_vblank_cb,
- (void *)crtc);
-
- /* wait */
- pending = atomic_read(&sde_crtc->pending);
- if (pending & PENDING_FLIP) {
- wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
- (frame_flushed(sde_crtc) != 0),
- msecs_to_jiffies(CRTC_MAX_WAIT_ONE_FRAME));
- if (ret <= 0)
- dev_warn(dev->dev, "vblank time out, crtc=%d\n",
- sde_crtc->id);
- }
-
- for (i = 0; i < sde_crtc->num_ctls; i++)
- sde_crtc->mixer[i].flush_mask = 0;
-
- /* release */
- drm_crtc_vblank_put(crtc);
-}
-
-static void request_pending(struct drm_crtc *crtc, u32 pending)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct vsync_info vsync;
-
- /* request vsync info, cache the current frame count */
- sde_encoder_get_vsync_info(sde_crtc->encoder, &vsync);
- sde_crtc->vsync_count = vsync.frame_count;
-
- atomic_or(pending, &sde_crtc->pending);
-}
-
-/**
- * Flush the CTL PATH
- */
-static u32 crtc_flush_all(struct drm_crtc *crtc)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_hw_ctl *ctl;
- int i;
-
- DBG("");
-
- for (i = 0; i < sde_crtc->num_ctls; i++) {
- ctl = sde_crtc->mixer[i].hw_ctl;
- ctl->ops.get_bitmask_intf(ctl,
- &(sde_crtc->mixer[i].flush_mask),
- sde_crtc->mixer[i].intf_idx);
- DBG("Flushing CTL_ID %d, flush_mask %x", ctl->idx,
- sde_crtc->mixer[i].flush_mask);
- ctl->ops.setup_flush(ctl,
- sde_crtc->mixer[i].flush_mask);
- }
-
- return 0;
-}
-
-static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- unsigned long flags;
-
- DBG("");
-
- WARN_ON(sde_crtc->event);
-
- spin_lock_irqsave(&dev->event_lock, flags);
- sde_crtc->event = crtc->state->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- /*
- * If no CTL has been allocated in sde_crtc_atomic_check(),
- * it means we are trying to flush a CRTC whose state is disabled:
- * nothing else needs to be done.
- */
- if (unlikely(!sde_crtc->num_ctls))
- return;
-
- blend_setup(crtc);
-
- /*
- * PP_DONE irq is only used by command mode for now.
- * It is better to request pending before FLUSH and START trigger
- * to make sure no pp_done irq missed.
- * This is safe because no pp_done will happen before SW trigger
- * in command mode.
- */
-}
-
-static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- unsigned long flags;
-
- DBG("%s: event: %pK", sde_crtc->name, crtc->state->event);
-
- WARN_ON(sde_crtc->event);
-
- spin_lock_irqsave(&dev->event_lock, flags);
- sde_crtc->event = crtc->state->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- /*
- * If no CTL has been allocated in sde_crtc_atomic_check(),
- * it means we are trying to flush a CRTC whose state is disabled:
- * nothing else needs to be done.
- */
- if (unlikely(!sde_crtc->num_ctls))
- return;
-
- crtc_flush_all(crtc);
-
- request_pending(crtc, PENDING_FLIP);
-}
-
-static int sde_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
-{
- return -EINVAL;
-}
-
-static int sde_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file, uint32_t handle,
- uint32_t width, uint32_t height)
-{
- return 0;
-}
-
-static int sde_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- return 0;
-}
-
-static void sde_crtc_disable(struct drm_crtc *crtc)
-{
- DBG("");
-}
-
-static void sde_crtc_enable(struct drm_crtc *crtc)
-{
- DBG("");
-}
-
-struct plane_state {
- struct drm_plane *plane;
- struct sde_plane_state *state;
-};
-
-static int pstate_cmp(const void *a, const void *b)
-{
- struct plane_state *pa = (struct plane_state *)a;
- struct plane_state *pb = (struct plane_state *)b;
-
- return pa->state->zpos - pb->state->zpos;
-}
-
-static int sde_crtc_atomic_check(struct drm_crtc *crtc,
- struct drm_crtc_state *state)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_kms *sde_kms = get_kms(crtc);
- struct drm_plane *plane;
- struct drm_device *dev = crtc->dev;
- struct plane_state pstates[SDE_STAGE_MAX];
- int max_stages = CRTC_HW_MIXER_MAXSTAGES(sde_kms->catalog, 0);
- int cnt = 0, i;
-
- DBG("%s: check", sde_crtc->name);
-
- /* verify that there are not too many planes attached to crtc
- * and that we don't have conflicting mixer stages:
- */
- drm_atomic_crtc_state_for_each_plane(plane, state) {
- struct drm_plane_state *pstate;
-
- if (cnt >= (max_stages)) {
- dev_err(dev->dev, "too many planes!\n");
- return -EINVAL;
- }
-
- pstate = state->state->plane_states[drm_plane_index(plane)];
-
- /* plane might not have changed, in which case take
- * current state:
- */
- if (!pstate)
- pstate = plane->state;
- pstates[cnt].plane = plane;
- pstates[cnt].state = to_sde_plane_state(pstate);
-
- cnt++;
- }
-
- /* assign a stage based on sorted zpos property */
- sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
-
- for (i = 0; i < cnt; i++) {
- pstates[i].state->stage = SDE_STAGE_0 + i;
- DBG("%s: assign pipe %d on stage=%d", sde_crtc->name,
- sde_plane_pipe(pstates[i].plane),
- pstates[i].state->stage);
- }
-
- return 0;
-}
-
-static const struct drm_crtc_funcs sde_crtc_funcs = {
- .set_config = drm_atomic_helper_set_config,
- .destroy = sde_crtc_destroy,
- .page_flip = drm_atomic_helper_page_flip,
- .set_property = sde_crtc_set_property,
- .reset = drm_atomic_helper_crtc_reset,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
- .cursor_set = sde_crtc_cursor_set,
- .cursor_move = sde_crtc_cursor_move,
-};
-
-static const struct drm_crtc_helper_funcs sde_crtc_helper_funcs = {
- .mode_fixup = sde_crtc_mode_fixup,
- .mode_set_nofb = sde_crtc_mode_set_nofb,
- .disable = sde_crtc_disable,
- .enable = sde_crtc_enable,
- .atomic_check = sde_crtc_atomic_check,
- .atomic_begin = sde_crtc_atomic_begin,
- .atomic_flush = sde_crtc_atomic_flush,
-};
-
-uint32_t sde_crtc_vblank(struct drm_crtc *crtc)
-{
- return 0;
-}
-
-void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
-{
-}
-
-static void sde_crtc_install_properties(struct drm_crtc *crtc,
- struct drm_mode_object *obj)
-{
-}
-
-
-/* initialize crtc */
-struct drm_crtc *sde_crtc_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- struct drm_plane *plane, int id)
-{
- struct drm_crtc *crtc = NULL;
- struct sde_crtc *sde_crtc;
- int rc;
-
- sde_crtc = kzalloc(sizeof(*sde_crtc), GFP_KERNEL);
- if (!sde_crtc)
- return ERR_PTR(-ENOMEM);
-
- crtc = &sde_crtc->base;
-
- sde_crtc->id = id;
- sde_crtc->encoder = encoder;
-
- sde_crtc_install_properties(crtc, &crtc->base);
-
- drm_crtc_init_with_planes(dev, crtc, plane, NULL, &sde_crtc_funcs);
-
- drm_crtc_helper_add(crtc, &sde_crtc_helper_funcs);
- plane->crtc = crtc;
-
- rc = sde_crtc_reserve_hw_resources(crtc, encoder);
- if (rc) {
- dev_err(dev->dev, " error reserving HW resource for this CRTC\n");
- return ERR_PTR(-EINVAL);
- }
-
- DBG("%s: Successfully initialized crtc", __func__);
- return crtc;
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
deleted file mode 100644
index 9f14f999913d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_CRTC_H_
-#define _SDE_CRTC_H_
-
-#include "drm_crtc.h"
-
-#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-
-#define CRTC_DUAL_MIXERS 2
-#define PENDING_FLIP 2
-/* worst case one frame wait time based on 30 FPS : 33.33ms*/
-#define CRTC_MAX_WAIT_ONE_FRAME 34
-#define CRTC_HW_MIXER_MAXSTAGES(c, idx) ((c)->mixer[idx].sblk->maxblendstages)
-
-/**
- * struct sde_crtc_mixer - stores the map for each virtual pipeline in the CRTC
- * @hw_dspp : DSPP HW Driver context
- * @hw_lm : LM HW Driver context
- * @hw_ctl : CTL Path HW driver context
- * @intf_idx : Interface idx
- * @mode : Interface mode Active/CMD
- * @flush_mask : Flush mask value for this commit
- */
-struct sde_crtc_mixer {
- struct sde_hw_dspp *hw_dspp;
- struct sde_hw_mixer *hw_lm;
- struct sde_hw_ctl *hw_ctl;
- enum sde_intf intf_idx;
- enum sde_intf_mode mode;
- u32 flush_mask;
-};
-
-/**
- * struct sde_crtc - virtualized CRTC data structure
- * @base : Base drm crtc structure
- * @name : ASCII description of this crtc
- * @encoder : Associated drm encoder object
- * @id : Unique crtc identifier
- * @lm_lock : LM register access spinlock
- * @num_ctls : Number of ctl paths in use
- * @num_mixers : Number of mixers in use
- * @mixer : List of active mixers
- * @event : Pointer to last received drm vblank event
- * @pending : Whether or not an update is pending
- * @vsync_count : Running count of received vsync events
- */
-struct sde_crtc {
- struct drm_crtc base;
- char name[8];
- struct drm_encoder *encoder;
- int id;
-
- spinlock_t lm_lock; /* protect registers */
-
- /* HW Resources reserved for the crtc */
- u32 num_ctls;
- u32 num_mixers;
- struct sde_crtc_mixer mixer[CRTC_DUAL_MIXERS];
-
- /*if there is a pending flip, these will be non-null */
- struct drm_pending_vblank_event *event;
- atomic_t pending;
- u32 vsync_count;
-};
-
-#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
-
-#endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
deleted file mode 100644
index ad72bca11669..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "msm_drv.h"
-#include "sde_kms.h"
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_intf.h"
-#include "sde_hw_mdp_ctl.h"
-#include "sde_mdp_formats.h"
-
-#include "sde_encoder_phys.h"
-#include "display_manager.h"
-
-#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
-
-#ifdef CONFIG_QCOM_BUS_SCALING
-#include <linux/msm-bus.h>
-#include <linux/msm-bus-board.h>
-#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
- { \
- .src = MSM_BUS_MASTER_MDP_PORT0, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ab = (ab_val), \
- .ib = (ib_val), \
- }
-
-static struct msm_bus_vectors mdp_bus_vectors[] = {
- MDP_BUS_VECTOR_ENTRY(0, 0),
- MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
-};
-
-static struct msm_bus_paths mdp_bus_usecases[] = { {
- .num_paths = 1,
- .vectors =
- &mdp_bus_vectors[0],
- }, {
- .num_paths = 1,
- .vectors =
- &mdp_bus_vectors[1],
- }
-};
-
-static struct msm_bus_scale_pdata mdp_bus_scale_table = {
- .usecase = mdp_bus_usecases,
- .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
- .name = "mdss_mdp",
-};
-
-static void bs_init(struct sde_encoder_virt *sde_enc)
-{
- sde_enc->bus_scaling_client =
- msm_bus_scale_register_client(&mdp_bus_scale_table);
- DBG("bus scale client: %08x", sde_enc->bus_scaling_client);
-}
-
-static void bs_fini(struct sde_encoder_virt *sde_enc)
-{
- if (sde_enc->bus_scaling_client) {
- msm_bus_scale_unregister_client(sde_enc->bus_scaling_client);
- sde_enc->bus_scaling_client = 0;
- }
-}
-
-static void bs_set(struct sde_encoder_virt *sde_enc, int idx)
-{
- if (sde_enc->bus_scaling_client) {
- DBG("set bus scaling: %d", idx);
- idx = 1;
- msm_bus_scale_client_update_request(sde_enc->bus_scaling_client,
- idx);
- }
-}
-#else
-static void bs_init(struct sde_encoder_virt *sde_enc)
-{
-}
-
-static void bs_fini(struct sde_encoder_virt *sde_enc)
-{
-}
-
-static void bs_set(struct sde_encoder_virt *sde_enc, int idx)
-{
-}
-#endif
-
-void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
- struct sde_encoder_hw_resources *hw_res)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
-
- DBG("");
-
- if (!hw_res || !drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- /* Query resources used by phys encs, expected to be without overlap */
- memset(hw_res, 0, sizeof(*hw_res));
- for (i = 0; i < sde_enc->num_phys_encs; i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
- if (phys && phys->phys_ops.get_hw_resources)
- phys->phys_ops.get_hw_resources(phys, hw_res);
- }
-}
-
-static void sde_encoder_destroy(struct drm_encoder *drm_enc)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- for (i = 0; i < ARRAY_SIZE(sde_enc->phys_encs); i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
- if (phys && phys->phys_ops.destroy) {
- phys->phys_ops.destroy(phys);
- --sde_enc->num_phys_encs;
- sde_enc->phys_encs[i] = NULL;
- }
- }
-
- if (sde_enc->num_phys_encs) {
- DRM_ERROR("Expected num_phys_encs to be 0 not %d\n",
- sde_enc->num_phys_encs);
- }
-
- drm_encoder_cleanup(drm_enc);
- bs_fini(sde_enc);
- kfree(sde_enc);
-}
-
-static bool sde_encoder_virt_mode_fixup(struct drm_encoder *drm_enc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
- bool ret = true;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return false;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- for (i = 0; i < sde_enc->num_phys_encs; i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
- if (phys && phys->phys_ops.mode_fixup) {
- ret =
- phys->phys_ops.mode_fixup(phys, mode,
- adjusted_mode);
- if (!ret) {
- DBG("Mode unsupported by phys_enc %d", i);
- break;
- }
-
- if (sde_enc->num_phys_encs > 1) {
- DBG("ModeFix only checking 1 phys_enc");
- break;
- }
- }
- }
-
- return ret;
-}
-
-static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
- bool splitmode = false;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- /*
- * Panel is driven by two interfaces ,each interface drives half of
- * the horizontal
- */
- if (sde_enc->num_phys_encs == 2)
- splitmode = true;
-
- for (i = 0; i < sde_enc->num_phys_encs; i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- phys->phys_ops.mode_set(phys,
- mode,
- adjusted_mode,
- splitmode);
- if (memcmp(mode, adjusted_mode, sizeof(*mode)) != 0)
- DRM_ERROR("adjusted modes not supported\n");
- }
- }
-}
-
-static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
- bool splitmode = false;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- bs_set(sde_enc, 1);
-
- if (sde_enc->num_phys_encs == 2)
- splitmode = true;
-
-
- for (i = 0; i < sde_enc->num_phys_encs; i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
- if (phys && phys->phys_ops.enable)
-
- /* enable/disable dual interface top config */
- if (phys->phys_ops.enable_split_config)
- phys->phys_ops.enable_split_config(phys,
- splitmode);
- phys->phys_ops.enable(phys);
- }
-}
-
-static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- int i = 0;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- for (i = 0; i < sde_enc->num_phys_encs; i++) {
- struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
-
- if (phys && phys->phys_ops.disable)
- phys->phys_ops.disable(phys);
- }
-
- bs_set(sde_enc, 0);
-}
-
-static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = {
- .mode_fixup = sde_encoder_virt_mode_fixup,
- .mode_set = sde_encoder_virt_mode_set,
- .disable = sde_encoder_virt_disable,
- .enable = sde_encoder_virt_enable,
-};
-
-static const struct drm_encoder_funcs sde_encoder_funcs = {
- .destroy = sde_encoder_destroy,
-};
-
-static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog,
- enum sde_intf_type type, u32 controller_id)
-{
- int i = 0;
-
- DBG("");
-
- for (i = 0; i < catalog->intf_count; i++) {
- if (catalog->intf[i].type == type
- && catalog->intf[i].controller_id == controller_id) {
- return catalog->intf[i].id;
- }
- }
-
- return INTF_MAX;
-}
-
-static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc)
-{
- struct sde_encoder_virt *sde_enc = NULL;
- unsigned long lock_flags;
-
- DBG("");
-
- if (!drm_enc) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
-
- spin_lock_irqsave(&sde_enc->spin_lock, lock_flags);
- if (sde_enc->kms_vblank_callback)
- sde_enc->kms_vblank_callback(sde_enc->kms_vblank_callback_data);
- spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
-}
-
-static int sde_encoder_virt_add_phys_vid_enc(struct sde_encoder_virt *sde_enc,
- struct sde_kms *sde_kms,
- enum sde_intf intf_idx,
- enum sde_ctl ctl_idx)
-{
- int ret = 0;
-
- DBG("");
-
- if (sde_enc->num_phys_encs >= ARRAY_SIZE(sde_enc->phys_encs)) {
- DRM_ERROR("Too many video encoders %d, unable to add\n",
- sde_enc->num_phys_encs);
- ret = -EINVAL;
- } else {
- struct sde_encoder_virt_ops parent_ops = {
- sde_encoder_vblank_callback
- };
- struct sde_encoder_phys *enc =
- sde_encoder_phys_vid_init(sde_kms, intf_idx, ctl_idx,
- &sde_enc->base,
- parent_ops);
- if (IS_ERR(enc))
- ret = PTR_ERR(enc);
-
- if (!ret) {
- sde_enc->phys_encs[sde_enc->num_phys_encs] = enc;
- ++sde_enc->num_phys_encs;
- }
- }
-
- return ret;
-}
-
-static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
- struct sde_kms *sde_kms,
- struct display_info *disp_info,
- int *drm_enc_mode)
-{
- int ret = 0;
- int i = 0;
- enum sde_intf_type intf_type = INTF_NONE;
-
- DBG("");
-
- if (disp_info->intf == DISPLAY_INTF_DSI) {
- *drm_enc_mode = DRM_MODE_ENCODER_DSI;
- intf_type = INTF_DSI;
- } else if (disp_info->intf == DISPLAY_INTF_HDMI) {
- *drm_enc_mode = DRM_MODE_ENCODER_TMDS;
- intf_type = INTF_HDMI;
- } else {
- DRM_ERROR("Unsupported display interface type");
- return -EINVAL;
- }
-
- WARN_ON(disp_info->num_of_h_tiles < 1);
-
- DBG("dsi_info->num_of_h_tiles %d", disp_info->num_of_h_tiles);
-
- for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
- /*
- * Left-most tile is at index 0, content is controller id
- * h_tile_instance_ids[2] = {0, 1}; DSI0 = left, DSI1 = right
- * h_tile_instance_ids[2] = {1, 0}; DSI1 = left, DSI0 = right
- */
- const struct sde_hw_res_map *hw_res_map = NULL;
- enum sde_intf intf_idx = INTF_MAX;
- enum sde_ctl ctl_idx = CTL_MAX;
- u32 controller_id = disp_info->h_tile_instance[i];
-
- DBG("h_tile_instance %d = %d", i, controller_id);
-
- intf_idx = sde_encoder_get_intf(sde_kms->catalog,
- intf_type, controller_id);
- if (intf_idx == INTF_MAX) {
- DBG("Error: could not get the interface id");
- ret = -EINVAL;
- }
-
- hw_res_map = sde_rm_get_res_map(sde_kms, intf_idx);
- if (IS_ERR_OR_NULL(hw_res_map))
- ret = -EINVAL;
- else
- ctl_idx = hw_res_map->ctl;
-
- /* Create both VID and CMD Phys Encoders here */
- if (!ret)
- ret = sde_encoder_virt_add_phys_vid_enc(
- sde_enc, sde_kms, intf_idx, ctl_idx);
- }
-
-
- return ret;
-}
-
-static struct drm_encoder *sde_encoder_virt_init(
- struct drm_device *dev, struct display_info *disp_info)
-{
- struct msm_drm_private *priv = dev->dev_private;
- struct sde_kms *sde_kms = to_sde_kms(priv->kms);
- struct drm_encoder *drm_enc = NULL;
- struct sde_encoder_virt *sde_enc = NULL;
- int drm_enc_mode = DRM_MODE_ENCODER_NONE;
- int ret = 0;
-
- DBG("");
-
- sde_enc = kzalloc(sizeof(*sde_enc), GFP_KERNEL);
- if (!sde_enc) {
- ret = -ENOMEM;
- goto fail;
- }
-
- ret = sde_encoder_setup_display(sde_enc, sde_kms, disp_info,
- &drm_enc_mode);
- if (ret)
- goto fail;
-
- spin_lock_init(&sde_enc->spin_lock);
- drm_enc = &sde_enc->base;
- drm_encoder_init(dev, drm_enc, &sde_encoder_funcs, drm_enc_mode);
- drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs);
- bs_init(sde_enc);
-
- DBG("Created encoder");
-
- return drm_enc;
-
-fail:
- DRM_ERROR("Failed to create encoder\n");
- if (drm_enc)
- sde_encoder_destroy(drm_enc);
-
- return ERR_PTR(ret);
-}
-
-void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
- void (*cb)(void *), void *data)
-{
- struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
- unsigned long lock_flags;
-
- DBG("");
-
- spin_lock_irqsave(&sde_enc->spin_lock, lock_flags);
- sde_enc->kms_vblank_callback = cb;
- sde_enc->kms_vblank_callback_data = data;
- spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
-}
-
-void sde_encoder_get_vsync_info(struct drm_encoder *drm_enc,
- struct vsync_info *vsync)
-{
- struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
- struct sde_encoder_phys *phys;
-
- DBG("");
-
- if (!vsync) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- /* we get the vsync info from the intf at index 0: master index */
- phys = sde_enc->phys_encs[0];
- if (phys)
- phys->phys_ops.get_vsync_info(phys, vsync);
-}
-
-/* encoders init,
- * initialize encoder based on displays
- */
-void sde_encoders_init(struct drm_device *dev)
-{
- struct msm_drm_private *priv = NULL;
- struct display_manager *disp_man = NULL;
- u32 i = 0;
- u32 num_displays = 0;
-
- DBG("");
-
- if (!dev || !dev->dev_private) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- priv = dev->dev_private;
- priv->num_encoders = 0;
- if (!priv->kms || !priv->dm) {
- DRM_ERROR("Invalid pointer");
- return;
- }
- disp_man = priv->dm;
-
- num_displays = display_manager_get_count(disp_man);
- DBG("num_displays %d", num_displays);
-
- if (num_displays > ARRAY_SIZE(priv->encoders)) {
- num_displays = ARRAY_SIZE(priv->encoders);
- DRM_ERROR("Too many displays found, capping to %d",
- num_displays);
- }
-
- for (i = 0; i < num_displays; i++) {
- struct display_info info = { 0 };
- struct drm_encoder *enc = NULL;
- u32 ret = 0;
-
- ret = display_manager_get_info_by_index(disp_man, i, &info);
- if (ret) {
- DRM_ERROR("Failed to get display info, %d", ret);
- return;
- }
-
- enc = sde_encoder_virt_init(dev, &info);
- if (IS_ERR_OR_NULL(enc)) {
- DRM_ERROR("Encoder initialization failed");
- return;
- }
-
- ret = display_manager_drm_init_by_index(disp_man, i, enc);
- if (ret) {
- DRM_ERROR("Display drm_init failed, %d", ret);
- return;
- }
-
- priv->encoders[priv->num_encoders++] = enc;
- }
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
deleted file mode 100644
index d35e084f9bef..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __SDE_ENCODER_PHYS_H__
-#define __SDE_ENCODER_PHYS_H__
-
-#include "sde_kms.h"
-#include "sde_hw_intf.h"
-#include "sde_hw_mdp_ctl.h"
-
-#define MAX_PHYS_ENCODERS_PER_VIRTUAL 4
-
-struct sde_encoder_phys;
-
-struct sde_encoder_virt_ops {
- void (*handle_vblank_virt)(struct drm_encoder *);
-};
-
-struct sde_encoder_phys_ops {
- void (*mode_set)(struct sde_encoder_phys *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- bool splitmode);
- bool (*mode_fixup)(struct sde_encoder_phys *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
- void (*enable)(struct sde_encoder_phys *encoder);
- void (*disable)(struct sde_encoder_phys *encoder);
- void (*destroy)(struct sde_encoder_phys *encoder);
- void (*get_hw_resources)(struct sde_encoder_phys *encoder,
- struct sde_encoder_hw_resources *hw_res);
- void (*get_vsync_info)(struct sde_encoder_phys *enc,
- struct vsync_info *vsync);
- void (*enable_split_config)(struct sde_encoder_phys *enc,
- bool enable);
-};
-
-struct sde_encoder_phys {
- struct drm_encoder *parent;
- struct sde_encoder_virt_ops parent_ops;
- struct sde_encoder_phys_ops phys_ops;
- struct sde_hw_intf *hw_intf;
- struct sde_hw_ctl *hw_ctl;
- struct sde_kms *sde_kms;
- struct drm_display_mode cached_mode;
- bool enabled;
- spinlock_t spin_lock;
-};
-
-/**
- * struct sde_encoder_phys_vid - sub-class of sde_encoder_phys to handle video
- * mode specific operations
- * @base: Baseclass physical encoder structure
- * @irq_idx: IRQ interface lookup index
- * @vblank_complete: for vblank irq synchronization
- */
-struct sde_encoder_phys_vid {
- struct sde_encoder_phys base;
- int irq_idx;
- struct completion vblank_complete;
-};
-
-struct sde_encoder_virt {
- struct drm_encoder base;
- spinlock_t spin_lock;
- uint32_t bus_scaling_client;
-
- int num_phys_encs;
- struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
-
- void (*kms_vblank_callback)(void *);
- void *kms_vblank_callback_data;
-};
-
-struct sde_encoder_phys *sde_encoder_phys_vid_init(struct sde_kms *sde_kms,
- enum sde_intf intf_idx,
- enum sde_ctl ctl_idx,
- struct drm_encoder *parent,
- struct sde_encoder_virt_ops
- parent_ops);
-
-#endif /* __sde_encoder_phys_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
deleted file mode 100644
index 693e1f33e7d8..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include "msm_drv.h"
-#include "sde_kms.h"
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_intf.h"
-#include "sde_mdp_formats.h"
-
-#include "sde_encoder_phys.h"
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
deleted file mode 100644
index aefa11d5cdde..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "msm_drv.h"
-#include "sde_kms.h"
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-#include "sde_encoder_phys.h"
-#include "sde_mdp_formats.h"
-#include "sde_hw_mdp_top.h"
-
-#define VBLANK_TIMEOUT msecs_to_jiffies(100)
-
-#define to_sde_encoder_phys_vid(x) \
- container_of(x, struct sde_encoder_phys_vid, base)
-
-static bool sde_encoder_phys_vid_is_master(
- struct sde_encoder_phys *phys_enc)
-{
- bool ret = true;
-
- return ret;
-}
-
-static void sde_encoder_phys_vid_wait_for_vblank(
- struct sde_encoder_phys_vid *vid_enc)
-{
- int rc = 0;
-
- DBG("");
- rc = wait_for_completion_timeout(&vid_enc->vblank_complete,
- VBLANK_TIMEOUT);
- if (rc == 0)
- DRM_ERROR("Timed out waiting for vblank irq\n");
-}
-
-static void drm_mode_to_intf_timing_params(
- const struct sde_encoder_phys *phys_enc,
- const struct drm_display_mode *mode,
- struct intf_timing_params *timing)
-{
- memset(timing, 0, sizeof(*timing));
- /*
- * https://www.kernel.org/doc/htmldocs/drm/ch02s05.html
- * Active Region Front Porch Sync Back Porch
- * <-----------------><------------><-----><----------->
- * <- [hv]display --->
- * <--------- [hv]sync_start ------>
- * <----------------- [hv]sync_end ------->
- * <---------------------------- [hv]total ------------->
- */
- timing->width = mode->hdisplay; /* active width */
- timing->height = mode->vdisplay; /* active height */
- timing->xres = timing->width;
- timing->yres = timing->height;
- timing->h_back_porch = mode->htotal - mode->hsync_end;
- timing->h_front_porch = mode->hsync_start - mode->hdisplay;
- timing->v_back_porch = mode->vtotal - mode->vsync_end;
- timing->v_front_porch = mode->vsync_start - mode->vdisplay;
- timing->hsync_pulse_width = mode->hsync_end - mode->hsync_start;
- timing->vsync_pulse_width = mode->vsync_end - mode->vsync_start;
- timing->hsync_polarity = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0;
- timing->vsync_polarity = (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
- timing->border_clr = 0;
- timing->underflow_clr = 0xff;
- timing->hsync_skew = mode->hskew;
-
- /* DSI controller cannot handle active-low sync signals. */
- if (phys_enc->hw_intf->cap->type == INTF_DSI) {
- timing->hsync_polarity = 0;
- timing->vsync_polarity = 0;
- }
-
- /*
- * For edp only:
- * DISPLAY_V_START = (VBP * HCYCLE) + HBP
- * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
- */
- /*
- * if (vid_enc->hw->cap->type == INTF_EDP) {
- * display_v_start += mode->htotal - mode->hsync_start;
- * display_v_end -= mode->hsync_start - mode->hdisplay;
- * }
- */
-}
-
-static inline u32 get_horizontal_total(const struct intf_timing_params *timing)
-{
- u32 active = timing->xres;
- u32 inactive =
- timing->h_back_porch + timing->h_front_porch +
- timing->hsync_pulse_width;
- return active + inactive;
-}
-
-static inline u32 get_vertical_total(const struct intf_timing_params *timing)
-{
- u32 active = timing->yres;
- u32 inactive =
- timing->v_back_porch + timing->v_front_porch +
- timing->vsync_pulse_width;
- return active + inactive;
-}
-
-/*
- * programmable_fetch_get_num_lines:
- * Number of fetch lines in vertical front porch
- * @timing: Pointer to the intf timing information for the requested mode
- *
- * Returns the number of fetch lines in vertical front porch at which mdp
- * can start fetching the next frame.
- *
- * Number of needed prefetch lines is anything that cannot be absorbed in the
- * start of frame time (back porch + vsync pulse width).
- *
- * Some panels have very large VFP, however we only need a total number of
- * lines based on the chip worst case latencies.
- */
-static u32 programmable_fetch_get_num_lines(
- struct sde_encoder_phys *phys_enc,
- const struct intf_timing_params *timing)
-{
- u32 worst_case_needed_lines =
- phys_enc->hw_intf->cap->prog_fetch_lines_worst_case;
- u32 start_of_frame_lines =
- timing->v_back_porch + timing->vsync_pulse_width;
- u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
- u32 actual_vfp_lines = 0;
-
- /* Fetch must be outside active lines, otherwise undefined. */
-
- if (start_of_frame_lines >= worst_case_needed_lines) {
- DBG("Programmable fetch is not needed due to large vbp+vsw");
- actual_vfp_lines = 0;
- } else if (timing->v_front_porch < needed_vfp_lines) {
- /* Warn fetch needed, but not enough porch in panel config */
- pr_warn_once
- ("low vbp+vfp may lead to perf issues in some cases\n");
- DBG("Less vfp than fetch requires, using entire vfp");
- actual_vfp_lines = timing->v_front_porch;
- } else {
- DBG("Room in vfp for needed prefetch");
- actual_vfp_lines = needed_vfp_lines;
- }
-
- DBG("v_front_porch %u v_back_porch %u vsync_pulse_width %u",
- timing->v_front_porch, timing->v_back_porch,
- timing->vsync_pulse_width);
- DBG("wc_lines %u needed_vfp_lines %u actual_vfp_lines %u",
- worst_case_needed_lines, needed_vfp_lines, actual_vfp_lines);
-
- return actual_vfp_lines;
-}
-
-/*
- * programmable_fetch_config: Programs HW to prefetch lines by offsetting
- * the start of fetch into the vertical front porch for cases where the
- * vsync pulse width and vertical back porch time is insufficient
- *
- * Gets # of lines to pre-fetch, then calculate VSYNC counter value.
- * HW layer requires VSYNC counter of first pixel of tgt VFP line.
- *
- * @timing: Pointer to the intf timing information for the requested mode
- */
-static void programmable_fetch_config(struct sde_encoder_phys *phys_enc,
- const struct intf_timing_params *timing)
-{
- struct intf_prog_fetch f = { 0 };
- u32 vfp_fetch_lines = 0;
- u32 horiz_total = 0;
- u32 vert_total = 0;
- u32 vfp_fetch_start_vsync_counter = 0;
- unsigned long lock_flags;
-
- if (WARN_ON_ONCE(!phys_enc->hw_intf->ops.setup_prg_fetch))
- return;
-
- vfp_fetch_lines = programmable_fetch_get_num_lines(phys_enc, timing);
- if (vfp_fetch_lines) {
- vert_total = get_vertical_total(timing);
- horiz_total = get_horizontal_total(timing);
- vfp_fetch_start_vsync_counter =
- (vert_total - vfp_fetch_lines) * horiz_total + 1;
- f.enable = 1;
- f.fetch_start = vfp_fetch_start_vsync_counter;
- }
-
- DBG("vfp_fetch_lines %u vfp_fetch_start_vsync_counter %u",
- vfp_fetch_lines, vfp_fetch_start_vsync_counter);
-
- spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
- phys_enc->hw_intf->ops.setup_prg_fetch(phys_enc->hw_intf, &f);
- spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);
-}
-
-static bool sde_encoder_phys_vid_mode_fixup(
- struct sde_encoder_phys *phys_enc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- DBG("");
-
- /*
- * Modifying mode has consequences when the mode comes back to us
- */
- return true;
-}
-
-static void sde_encoder_phys_vid_flush_intf(struct sde_encoder_phys *phys_enc)
-{
- struct sde_hw_intf *intf = phys_enc->hw_intf;
- struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
- u32 flush_mask = 0;
-
- DBG("");
-
- ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx);
- ctl->ops.setup_flush(ctl, flush_mask);
-
- DBG("Flushing CTL_ID %d, flush_mask %x, INTF %d",
- ctl->idx, flush_mask, intf->idx);
-}
-
-static void sde_encoder_phys_vid_mode_set(struct sde_encoder_phys *phys_enc,
- struct drm_display_mode *mode,
- struct drm_display_mode
- *adjusted_mode,
- bool splitmode)
-{
- mode = adjusted_mode;
- phys_enc->cached_mode = *adjusted_mode;
- if (splitmode) {
- phys_enc->cached_mode.hdisplay >>= 1;
- phys_enc->cached_mode.htotal >>= 1;
- phys_enc->cached_mode.hsync_start >>= 1;
- phys_enc->cached_mode.hsync_end >>= 1;
- }
-
- DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal,
- mode->type, mode->flags);
-}
-
-static void sde_encoder_phys_vid_setup_timing_engine(
- struct sde_encoder_phys *phys_enc)
-{
- struct drm_display_mode *mode = &phys_enc->cached_mode;
- struct intf_timing_params p = { 0 };
- struct sde_mdp_format_params *sde_fmt_params = NULL;
- u32 fmt_fourcc = DRM_FORMAT_RGB888;
- u32 fmt_mod = 0;
- unsigned long lock_flags;
- struct sde_hw_intf_cfg intf_cfg = { 0 };
-
- if (WARN_ON(!phys_enc->hw_intf->ops.setup_timing_gen))
- return;
-
- if (WARN_ON(!phys_enc->hw_ctl->ops.setup_intf_cfg))
- return;
-
- DBG("enable mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal,
- mode->type, mode->flags);
-
- drm_mode_to_intf_timing_params(phys_enc, mode, &p);
-
- sde_fmt_params = sde_mdp_get_format_params(fmt_fourcc, fmt_mod);
-
- intf_cfg.intf = phys_enc->hw_intf->idx;
- intf_cfg.wb = SDE_NONE;
-
- spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
- phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf, &p,
- sde_fmt_params);
- phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
- spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);
-
- programmable_fetch_config(phys_enc, &p);
-}
-
-static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
-{
- struct sde_encoder_phys_vid *vid_enc = arg;
- struct sde_encoder_phys *phys_enc = &vid_enc->base;
-
- phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent);
-
- /* signal VBLANK completion */
- complete_all(&vid_enc->vblank_complete);
-}
-
-static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc)
-{
- struct sde_encoder_phys_vid *vid_enc =
- to_sde_encoder_phys_vid(phys_enc);
- struct sde_irq_callback irq_cb;
- int ret = 0;
-
- vid_enc->irq_idx = sde_irq_idx_lookup(phys_enc->sde_kms,
- SDE_IRQ_TYPE_INTF_VSYNC, phys_enc->hw_intf->idx);
- if (vid_enc->irq_idx < 0) {
- DRM_ERROR(
- "Failed to lookup IRQ index for INTF_VSYNC with intf=%d\n",
- phys_enc->hw_intf->idx);
- return -EINVAL;
- }
-
- irq_cb.func = sde_encoder_phys_vid_vblank_irq;
- irq_cb.arg = vid_enc;
- ret = sde_register_irq_callback(phys_enc->sde_kms, vid_enc->irq_idx,
- &irq_cb);
- if (ret) {
- DRM_ERROR("Failed to register IRQ callback INTF_VSYNC\n");
- return ret;
- }
-
- ret = sde_enable_irq(phys_enc->sde_kms, &vid_enc->irq_idx, 1);
- if (ret) {
- DRM_ERROR(
- "Failed to enable IRQ for INTF_VSYNC, intf %d, irq_idx=%d\n",
- phys_enc->hw_intf->idx,
- vid_enc->irq_idx);
- vid_enc->irq_idx = -EINVAL;
-
- /* Unregister callback on IRQ enable failure */
- sde_register_irq_callback(phys_enc->sde_kms, vid_enc->irq_idx,
- NULL);
- return ret;
- }
-
- DBG("Registered IRQ for intf %d, irq_idx=%d\n",
- phys_enc->hw_intf->idx,
- vid_enc->irq_idx);
-
- return ret;
-}
-
-static int sde_encoder_phys_vid_unregister_irq(
- struct sde_encoder_phys *phys_enc)
-{
- struct sde_encoder_phys_vid *vid_enc =
- to_sde_encoder_phys_vid(phys_enc);
-
- sde_register_irq_callback(phys_enc->sde_kms, vid_enc->irq_idx, NULL);
- sde_disable_irq(phys_enc->sde_kms, &vid_enc->irq_idx, 1);
-
- DBG("Un-Register IRQ for intf %d, irq_idx=%d\n",
- phys_enc->hw_intf->idx,
- vid_enc->irq_idx);
-
- return 0;
-}
-
-static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc)
-{
- int ret = 0;
-
- DBG("");
-
- if (WARN_ON(!phys_enc->hw_intf->ops.enable_timing))
- return;
-
- sde_encoder_phys_vid_setup_timing_engine(phys_enc);
-
- sde_encoder_phys_vid_flush_intf(phys_enc);
-
- /* Register for interrupt unless we're the slave encoder */
- if (sde_encoder_phys_vid_is_master(phys_enc))
- ret = sde_encoder_phys_vid_register_irq(phys_enc);
-
- if (!ret && !phys_enc->enabled) {
- unsigned long lock_flags = 0;
-
- /* Now enable timing engine */
- spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
- phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 1);
- spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);
-
- phys_enc->enabled = true;
- }
-}
-
-static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
-{
- unsigned long lock_flags;
- struct sde_encoder_phys_vid *vid_enc =
- to_sde_encoder_phys_vid(phys_enc);
-
- DBG("");
-
- if (WARN_ON(!phys_enc->enabled))
- return;
-
- if (WARN_ON(!phys_enc->hw_intf->ops.enable_timing))
- return;
-
- spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
- phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 0);
- reinit_completion(&vid_enc->vblank_complete);
- spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);
-
- /*
- * Wait for a vsync so we know the ENABLE=0 latched before
- * the (connector) source of the vsync's gets disabled,
- * otherwise we end up in a funny state if we re-enable
- * before the disable latches, which results that some of
- * the settings changes for the new modeset (like new
- * scanout buffer) don't latch properly..
- */
- sde_encoder_phys_vid_wait_for_vblank(vid_enc);
- sde_encoder_phys_vid_unregister_irq(phys_enc);
- phys_enc->enabled = false;
-}
-
-static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc)
-{
- struct sde_encoder_phys_vid *vid_enc =
- to_sde_encoder_phys_vid(phys_enc);
- DBG("");
- kfree(phys_enc->hw_intf);
- kfree(vid_enc);
-}
-
-static void sde_encoder_phys_vid_get_hw_resources(
- struct sde_encoder_phys *phys_enc,
- struct sde_encoder_hw_resources *hw_res)
-{
- struct msm_drm_private *priv = phys_enc->parent->dev->dev_private;
- struct sde_kms *sde_kms = to_sde_kms(priv->kms);
- const struct sde_hw_res_map *hw_res_map;
-
- DBG("Intf %d\n", phys_enc->hw_intf->idx);
-
- hw_res->intfs[phys_enc->hw_intf->idx] = INTF_MODE_VIDEO;
- /*
- * defaults should not be in use,
- * otherwise signal/return failure
- */
- hw_res_map = sde_rm_get_res_map(sde_kms, phys_enc->hw_intf->idx);
-
- /* This is video mode panel so PINGPONG will be in by-pass mode
- * only assign ctl path.For cmd panel check if pp_split is
- * enabled, override default map
- */
- hw_res->ctls[hw_res_map->ctl] = true;
-}
-
-/**
- * video mode will use the intf (get_status)
- * cmd mode will use the pingpong (get_vsync_info)
- * to get this information
- */
-static void sde_encoder_intf_get_vsync_info(struct sde_encoder_phys *phys_enc,
- struct vsync_info *vsync)
-{
- struct intf_status status;
-
- DBG("");
- phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, &status);
- vsync->frame_count = status.frame_count;
- vsync->line_count = status.line_count;
- DBG(" sde_encoder_intf_get_vsync_info, count %d", vsync->frame_count);
-}
-
-static void sde_encoder_intf_split_config(struct sde_encoder_phys *phys_enc,
- bool enable)
-{
- struct msm_drm_private *priv = phys_enc->parent->dev->dev_private;
- struct sde_kms *sde_kms = to_sde_kms(priv->kms);
- struct sde_hw_mdp *mdp = sde_hw_mdptop_init(MDP_TOP, sde_kms->mmio,
- sde_kms->catalog);
- struct split_pipe_cfg cfg;
-
- DBG("%p", mdp);
- cfg.en = true;
- cfg.mode = INTF_MODE_VIDEO;
- if (!IS_ERR_OR_NULL(mdp))
- mdp->ops.setup_split_pipe(mdp, &cfg);
-}
-
-static void sde_encoder_phys_vid_init_cbs(struct sde_encoder_phys_ops *ops)
-{
- ops->mode_set = sde_encoder_phys_vid_mode_set;
- ops->mode_fixup = sde_encoder_phys_vid_mode_fixup;
- ops->enable = sde_encoder_phys_vid_enable;
- ops->disable = sde_encoder_phys_vid_disable;
- ops->destroy = sde_encoder_phys_vid_destroy;
- ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources;
- ops->get_vsync_info = sde_encoder_intf_get_vsync_info;
- ops->enable_split_config = sde_encoder_intf_split_config;
-}
-
-struct sde_encoder_phys *sde_encoder_phys_vid_init(
- struct sde_kms *sde_kms,
- enum sde_intf intf_idx,
- enum sde_ctl ctl_idx,
- struct drm_encoder *parent,
- struct sde_encoder_virt_ops parent_ops)
-{
- struct sde_encoder_phys *phys_enc = NULL;
- struct sde_encoder_phys_vid *vid_enc = NULL;
- int ret = 0;
-
- DBG("");
-
- vid_enc = kzalloc(sizeof(*vid_enc), GFP_KERNEL);
- if (!vid_enc) {
- ret = -ENOMEM;
- goto fail;
- }
- vid_enc->irq_idx = -EINVAL;
- init_completion(&vid_enc->vblank_complete);
-
- phys_enc = &vid_enc->base;
-
- phys_enc->hw_intf =
- sde_hw_intf_init(intf_idx, sde_kms->mmio, sde_kms->catalog);
- if (!phys_enc->hw_intf) {
- ret = -ENOMEM;
- goto fail;
- }
-
- phys_enc->hw_ctl = sde_rm_acquire_ctl_path(sde_kms, ctl_idx);
- if (!phys_enc->hw_ctl) {
- ret = -ENOMEM;
- goto fail;
- }
-
- sde_encoder_phys_vid_init_cbs(&phys_enc->phys_ops);
- phys_enc->parent = parent;
- phys_enc->parent_ops = parent_ops;
- phys_enc->sde_kms = sde_kms;
- spin_lock_init(&phys_enc->spin_lock);
-
- DBG("Created sde_encoder_phys_vid for intf %d", phys_enc->hw_intf->idx);
-
- return phys_enc;
-
-fail:
- DRM_ERROR("Failed to create encoder\n");
- if (vid_enc)
- sde_encoder_phys_vid_destroy(phys_enc);
-
- return ERR_PTR(ret);
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
deleted file mode 100644
index 118bb786da7e..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_catalog.h"
-
-struct sde_mdss_hw_cfg_handler cfg_table[] = {
- { .major = 1, .minor = 7, .cfg_init = sde_mdss_cfg_170_init},
-};
-
-/**
- * sde_hw_catalog_init: Returns the catalog information for the
- * passed HW version
- * @major: Major version of the MDSS HW
- * @minor: Minor version
- * @step: step version
- */
-struct sde_mdss_cfg *sde_hw_catalog_init(u32 major, u32 minor, u32 step)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cfg_table); i++) {
- if ((cfg_table[i].major == major) &&
- (cfg_table[i].minor == minor))
- return cfg_table[i].cfg_init(step);
- }
-
- return ERR_PTR(-ENODEV);
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
deleted file mode 100644
index 46972f2d5dfd..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ /dev/null
@@ -1,479 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_CATALOG_H
-#define _SDE_HW_CATALOG_H
-
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/bitmap.h>
-#include <linux/err.h>
-
-#define MAX_BLOCKS 8
-#define MAX_LAYERS 12
-
-#define SDE_HW_VER(MAJOR, MINOR, STEP) (((MAJOR & 0xF) << 28) |\
- ((MINOR & 0xFFF) << 16) |\
- (STEP & 0xFFFF))
-
-#define SDE_HW_MAJOR(rev) ((rev) >> 28)
-#define SDE_HW_MINOR(rev) .(((rev) >> 16) & 0xFFF)
-#define SDE_HW_STEP(rev) ((rev) & 0xFFFF)
-#define SDE_HW_MAJOR_MINOR(rev) ((rev) >> 16)
-
-#define IS_SDE_MAJOR_MINOR_SAME(rev1, rev2) \
- (SDE_HW_MAJOR_MINOR((rev1)) == SDE_HW_MAJOR_MINOR((rev2)))
-
-#define SDE_HW_VER_170 SDE_HW_VER(1, 7, 0) /* 8996 v1.0 */
-#define SDE_HW_VER_171 SDE_HW_VER(1, 7, 1) /* 8996 v2.0 */
-#define SDE_HW_VER_172 SDE_HW_VER(1, 7, 2) /* 8996 v3.0 */
-#define SDE_HW_VER_300 SDE_HW_VER(3, 0, 0) /* 8998 v1.0 */
-
-/**
- * MDP TOP BLOCK features
- * @SDE_MDP_PANIC_PER_PIPE Panic configuration needs to be be done per pipe
- * @SDE_MDP_10BIT_SUPPORT, Chipset supports 10 bit pixel formats
- * @SDE_MDP_BWC, MDSS HW supports Bandwidth compression.
- * @SDE_MDP_UBWC_1_0, This chipsets supports Universal Bandwidth
- * compression initial revision
- * @SDE_MDP_UBWC_1_5, Universal Bandwidth compression version 1.5
- * @SDE_MDP_CDP, Client driven prefetch
- * @SDE_MDP_MAX Maximum value
-
- */
-enum {
- SDE_MDP_PANIC_PER_PIPE = 0x1,
- SDE_MDP_10BIT_SUPPORT,
- SDE_MDP_BWC,
- SDE_MDP_UBWC_1_0,
- SDE_MDP_UBWC_1_5,
- SDE_MDP_CDP,
- SDE_MDP_MAX
-};
-
-/**
- * SSPP sub-blocks/features
- * @SDE_SSPP_SRC Src and fetch part of the pipes,
- * @SDE_SSPP_SCALAR_QSEED2, QSEED2 algorithm support
- * @SDE_SSPP_SCALAR_QSEED3, QSEED3 algorithm support
- * @SDE_SSPP_SCALAR_RGB, RGB Scalar, supported by RGB pipes
- * @SDE_SSPP_CSC, Support of Color space conversion
- * @SDE_SSPP_PA_V1, Common op-mode register for PA blocks
- * @SDE_SSPP_HIST_V1 Histogram programming method V1
- * @SDE_SSPP_IGC, Inverse gamma correction
- * @SDE_SSPP_PCC, Color correction support
- * @SDE_SSPP_CURSOR, SSPP can be used as a cursor layer
- * @SDE_SSPP_MAX maximum value
- */
-enum {
- SDE_SSPP_SRC = 0x1,
- SDE_SSPP_SCALAR_QSEED2,
- SDE_SSPP_SCALAR_QSEED3,
- SDE_SSPP_SCALAR_RGB,
- SDE_SSPP_CSC,
- SDE_SSPP_PA_V1, /* Common op-mode register for PA blocks */
- SDE_SSPP_HIST_V1,
- SDE_SSPP_IGC,
- SDE_SSPP_PCC,
- SDE_SSPP_CURSOR,
- SDE_SSPP_MAX
-};
-
-/*
- * MIXER sub-blocks/features
- * @SDE_MIXER_LAYER Layer mixer layer blend configuration,
- * @SDE_MIXER_SOURCESPLIT Layer mixer supports source-split configuration
- * @SDE_MIXER_GC Gamma correction block
- * @SDE_MIXER_MAX maximum value
- */
-enum {
- SDE_MIXER_LAYER = 0x1,
- SDE_MIXER_SOURCESPLIT,
- SDE_MIXER_GC,
- SDE_MIXER_MAX
-};
-
-/**
- * DSPP sub-blocks
- * @SDE_DSPP_IGC DSPP Inverse gamma correction block
- * @SDE_DSPP_PCC Panel color correction block
- * @SDE_DSPP_GC Gamma correction block
- * @SDE_DSPP_PA Picture adjustment block
- * @SDE_DSPP_GAMUT Gamut bloc
- * @SDE_DSPP_DITHER Dither block
- * @SDE_DSPP_HIST Histogram bloc
- * @SDE_DSPP_MAX maximum value
- */
-enum {
- SDE_DSPP_IGC = 0x1,
- SDE_DSPP_PCC,
- SDE_DSPP_GC,
- SDE_DSPP_PA,
- SDE_DSPP_GAMUT,
- SDE_DSPP_DITHER,
- SDE_DSPP_HIST,
- SDE_DSPP_MAX
-};
-
-/**
- * PINGPONG sub-blocks
- * @SDE_PINGPONG_TE Tear check block
- * @SDE_PINGPONG_TE2 Additional tear check block for split pipes
- * @SDE_PINGPONG_SPLIT PP block supports split fifo
- * @SDE_PINGPONG_DSC, Display stream compression blocks
- * @SDE_PINGPONG_MAX
- */
-enum {
- SDE_PINGPONG_TE = 0x1,
- SDE_PINGPONG_TE2,
- SDE_PINGPONG_SPLIT,
- SDE_PINGPONG_DSC,
- SDE_PINGPONG_MAX
-};
-
-/**
- * WB sub-blocks and features
- * @SDE_WB_LINE_MODE Writeback module supports line/linear mode
- * @SDE_WB_BLOCK_MODE Writeback module supports block mode read
- * @SDE_WB_ROTATE rotation support,this is available if writeback
- * supports block mode read
- * @SDE_WB_CSC Writeback color conversion block support
- * @SDE_WB_CHROMA_DOWN, Writeback chroma down block,
- * @SDE_WB_DOWNSCALE, Writeback integer downscaler,
- * @SDE_WB_DITHER, Dither block
- * @SDE_WB_TRAFFIC_SHAPER, Writeback traffic shaper bloc
- * @SDE_WB_UBWC_1_0, Writeback Universal bandwidth compression 1.0
- * support
- * @SDE_WB_WBWC_1_5 UBWC 1.5 support
- * @SDE_WB_MAX maximum value
- */
-enum {
- SDE_WB_LINE_MODE = 0x1,
- SDE_WB_BLOCK_MODE,
- SDE_WB_ROTATE = SDE_WB_BLOCK_MODE,
- SDE_WB_CSC,
- SDE_WB_CHROMA_DOWN,
- SDE_WB_DOWNSCALE,
- SDE_WB_DITHER,
- SDE_WB_TRAFFIC_SHAPER,
- SDE_WB_UBWC_1_0,
- SDE_WB_MAX
-};
-
-/**
- * MACRO SDE_HW_BLK_INFO - information of HW blocks inside SDE
- * @id: enum identifying this block
- * @base: register base offset to mdss
- * @features bit mask identifying sub-blocks/features
- */
-#define SDE_HW_BLK_INFO \
- u32 id; \
- u32 base; \
- unsigned long features
-
-/**
- * MACRO SDE_HW_SUBBLK_INFO - information of HW sub-block inside SDE
- * @id: enum identifying this sub-block
- * @base: offset of this sub-block relative to the block
- * offset
- * @len register block length of this sub-block
- */
-#define SDE_HW_SUBBLK_INFO \
- u32 id; \
- u32 base; \
- u32 len
-
-/**
- * struct sde_src_blk: SSPP part of the source pipes
- * @info: HW register and features supported by this sub-blk
- */
-struct sde_src_blk {
- SDE_HW_SUBBLK_INFO;
-};
-
-/**
- * struct sde_scalar_info: Scalar information
- * @info: HW register and features supported by this sub-blk
- */
-struct sde_scalar_blk {
- SDE_HW_SUBBLK_INFO;
-};
-
-struct sde_csc_blk {
- SDE_HW_SUBBLK_INFO;
-};
-
-/**
- * struct sde_pp_blk : Pixel processing sub-blk information
- * @info: HW register and features supported by this sub-blk
- * @version: HW Algorithm version
- */
-struct sde_pp_blk {
- SDE_HW_SUBBLK_INFO;
- u32 version;
-};
-
-/**
- * struct sde_sspp_sub_blks : SSPP sub-blocks
- * @maxdwnscale: max downscale ratio supported(without DECIMATION)
- * @maxupscale: maxupscale ratio supported
- * @maxwidth: max pixelwidth supported by this pipe
- * @danger_lut: LUT to generate danger signals
- * @safe_lut: LUT to generate safe signals
- * @src_blk:
- * @scalar_blk:
- * @csc_blk:
- * @pa_blk:
- * @hist_lut:
- * @pcc_blk:
- */
-struct sde_sspp_sub_blks {
- u32 maxlinewidth;
- u32 danger_lut;
- u32 safe_lut;
- u32 maxdwnscale;
- u32 maxupscale;
- struct sde_src_blk src_blk;
- struct sde_scalar_blk scalar_blk;
- struct sde_pp_blk csc_blk;
- struct sde_pp_blk pa_blk;
- struct sde_pp_blk hist_lut;
- struct sde_pp_blk pcc_blk;
-};
-
-/**
- * struct sde_lm_sub_blks: information of mixer block
- * @maxwidth: Max pixel width supported by this mixer
- * @maxblendstages: Max number of blend-stages supported
- * @blendstage_base: Blend-stage register base offset
- */
-struct sde_lm_sub_blks {
- u32 maxwidth;
- u32 maxblendstages;
- u32 blendstage_base[MAX_BLOCKS];
-};
-
-struct sde_dspp_sub_blks {
- struct sde_pp_blk igc;
- struct sde_pp_blk pcc;
- struct sde_pp_blk gc;
- struct sde_pp_blk pa;
- struct sde_pp_blk gamut;
- struct sde_pp_blk dither;
- struct sde_pp_blk hist;
-};
-
-struct sde_pingpong_sub_blks {
- struct sde_pp_blk te;
- struct sde_pp_blk te2;
- struct sde_pp_blk dsc;
-};
-
-struct sde_wb_sub_blocks {
- u32 maxlinewidth;
-};
-
-struct sde_mdss_base_cfg {
- SDE_HW_BLK_INFO;
-};
-
-/* struct sde_mdp_cfg : MDP TOP-BLK instance info
- * @id: index identifying this block
- * @base: register base offset to mdss
- * @features bit mask identifying sub-blocks/features
- * @highest_bank_bit: UBWC parameter
- */
-struct sde_mdp_cfg {
- SDE_HW_BLK_INFO;
- u32 highest_bank_bit;
-};
-
-/* struct sde_mdp_cfg : MDP TOP-BLK instance info
- * @id: index identifying this block
- * @base: register base offset to mdss
- * @features bit mask identifying sub-blocks/features
- */
-struct sde_ctl_cfg {
- SDE_HW_BLK_INFO;
-};
-
-/**
- * struct sde_sspp_cfg - information of source pipes
- * @id: index identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @sblk: Sub-blocks of SSPP
- */
-struct sde_sspp_cfg {
- SDE_HW_BLK_INFO;
- const struct sde_sspp_sub_blks *sblk;
-};
-
-/**
- * struct sde_lm_cfg - information of layer mixer blocks
- * @id: index identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @sblk: Sub-blocks of SSPP
- */
-struct sde_lm_cfg {
- SDE_HW_BLK_INFO;
- const struct sde_lm_sub_blks *sblk;
-};
-
-/**
- * struct sde_dspp_cfg - information of DSPP blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * supported by this block
- * @sblk sub-blocks information
- */
-struct sde_dspp_cfg {
- SDE_HW_BLK_INFO;
- const struct sde_dspp_sub_blks *sblk;
-};
-
-/**
- * struct sde_pingpong_cfg - information of PING-PONG blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @sblk sub-blocks information
- */
-struct sde_pingpong_cfg {
- SDE_HW_BLK_INFO;
- const struct sde_pingpong_sub_blks *sblk;
-};
-
-/**
- * struct sde_cdm_cfg - information of chroma down blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @intf_connect Connects to which interfaces
- * @wb_connect: Connects to which writebacks
- */
-struct sde_cdm_cfg {
- SDE_HW_BLK_INFO;
- u32 intf_connect[MAX_BLOCKS];
- u32 wb_connect[MAX_BLOCKS];
-};
-
-/**
- * struct sde_intf_cfg - information of timing engine blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @type: Interface type(DSI, DP, HDMI)
- * @controller_id: Controller Instance ID in case of multiple of intf type
- * @prog_fetch_lines_worst_case Worst case latency num lines needed to prefetch
- */
-struct sde_intf_cfg {
- SDE_HW_BLK_INFO;
- u32 type; /* interface type*/
- u32 controller_id;
- u32 prog_fetch_lines_worst_case;
-};
-
-/**
- * struct sde_wb_cfg - information of writeback blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- */
-struct sde_wb_cfg {
- SDE_HW_BLK_INFO;
- struct sde_wb_sub_blocks *sblk;
-};
-
-/**
- * struct sde_ad_cfg - information of Assertive Display blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- */
-struct sde_ad_cfg {
- SDE_HW_BLK_INFO;
-};
-
-/**
- * struct sde_mdss_cfg - information of MDSS HW
- * This is the main catalog data structure representing
- * this HW version. Contains number of instances,
- * register offsets, capabilities of the all MDSS HW sub-blocks.
- */
-struct sde_mdss_cfg {
- u32 hwversion;
-
- u32 mdss_count;
- struct sde_mdss_base_cfg mdss[MAX_BLOCKS];
-
- u32 mdp_count;
- struct sde_mdp_cfg mdp[MAX_BLOCKS];
-
- u32 ctl_count;
- struct sde_ctl_cfg ctl[MAX_BLOCKS];
-
- u32 sspp_count;
- struct sde_sspp_cfg sspp[MAX_LAYERS];
-
- u32 mixer_count;
- struct sde_lm_cfg mixer[MAX_BLOCKS];
-
- u32 dspp_count;
- struct sde_dspp_cfg dspp[MAX_BLOCKS];
-
- u32 pingpong_count;
- struct sde_pingpong_cfg pingpong[MAX_BLOCKS];
-
- u32 cdm_count;
- struct sde_cdm_cfg cdm[MAX_BLOCKS];
-
- u32 intf_count;
- struct sde_intf_cfg intf[MAX_BLOCKS];
-
- u32 wb_count;
- struct sde_wb_cfg wb[MAX_BLOCKS];
-
- u32 ad_count;
- struct sde_ad_cfg ad[MAX_BLOCKS];
- /* Add additional block data structures here */
-};
-
-struct sde_mdss_hw_cfg_handler {
- u32 major;
- u32 minor;
- struct sde_mdss_cfg* (*cfg_init)(u32);
-};
-
-/*
- * Access Macros
- */
-#define BLK_MDP(s) ((s)->mdp)
-#define BLK_CTL(s) ((s)->ctl)
-#define BLK_VIG(s) ((s)->vig)
-#define BLK_RGB(s) ((s)->rgb)
-#define BLK_DMA(s) ((s)->dma)
-#define BLK_CURSOR(s) ((s)->cursor)
-#define BLK_MIXER(s) ((s)->mixer)
-#define BLK_DSPP(s) ((s)->dspp)
-#define BLK_PINGPONG(s) ((s)->pingpong)
-#define BLK_CDM(s) ((s)->cdm)
-#define BLK_INTF(s) ((s)->intf)
-#define BLK_WB(s) ((s)->wb)
-#define BLK_AD(s) ((s)->ad)
-
-struct sde_mdss_cfg *sde_mdss_cfg_170_init(u32 step);
-struct sde_mdss_cfg *sde_hw_catalog_init(u32 major, u32 minor, u32 step);
-
-#endif /* _SDE_HW_CATALOG_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
deleted file mode 100644
index 7fb5a0616838..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-
-/* VIG layer capability */
-#define VIG_17X_MASK \
- (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALAR_QSEED2) |\
- BIT(SDE_SSPP_CSC) | BIT(SDE_SSPP_PA_V1) |\
- BIT(SDE_SSPP_HIST_V1) | BIT(SDE_SSPP_PCC) |\
- BIT(SDE_SSPP_IGC))
-
-/* RGB layer capability */
-#define RGB_17X_MASK \
- (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALAR_RGB) |\
- BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC))
-
-/* DMA layer capability */
-#define DMA_17X_MASK \
- (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_PA_V1) |\
- BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC))
-
-/* Cursor layer capability */
-#define CURSOR_17X_MASK (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_CURSOR))
-
-#define MIXER_17X_MASK (BIT(SDE_MIXER_SOURCESPLIT) |\
- BIT(SDE_MIXER_GC))
-
-#define DSPP_17X_MASK \
- (BIT(SDE_DSPP_IGC) | BIT(SDE_DSPP_PCC) |\
- BIT(SDE_DSPP_GC) | BIT(SDE_DSPP_PA) | BIT(SDE_DSPP_GAMUT) |\
- BIT(SDE_DSPP_DITHER) | BIT(SDE_DSPP_HIST))
-
-#define PINGPONG_17X_MASK \
- (BIT(SDE_PINGPONG_TE) | BIT(SDE_PINGPONG_DSC))
-
-#define PINGPONG_17X_SPLIT_MASK \
- (PINGPONG_17X_MASK | BIT(SDE_PINGPONG_SPLIT) |\
- BIT(SDE_PINGPONG_TE2))
-
-#define WB01_17X_MASK \
- (BIT(SDE_WB_LINE_MODE) | BIT(SDE_WB_BLOCK_MODE) |\
- BIT(SDE_WB_CSC) | BIT(SDE_WB_CHROMA_DOWN) | BIT(SDE_WB_DOWNSCALE) |\
- BIT(SDE_WB_DITHER) | BIT(SDE_WB_TRAFFIC_SHAPER) |\
- BIT(SDE_WB_UBWC_1_0))
-
-#define WB2_17X_MASK \
- (BIT(SDE_WB_LINE_MODE) | BIT(SDE_WB_TRAFFIC_SHAPER))
-
-/**
- * set_cfg_1xx_init(): populate sde sub-blocks reg offsets and instance counts
- */
-static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg)
-{
-
- /* Layer capability */
- static const struct sde_sspp_sub_blks layer = {
- .maxlinewidth = 2560,
- .danger_lut = 0xFFFF,
- .safe_lut = 0xFF00,
- .maxdwnscale = 4, .maxupscale = 20,
- .src_blk = {.id = SDE_SSPP_SRC,
- .base = 0x00, .len = 0x150,},
- .scalar_blk = {.id = SDE_SSPP_SCALAR_QSEED2,
- .base = 0x200, .len = 0x70,},
- .csc_blk = {.id = SDE_SSPP_CSC,
- .base = 0x320, .len = 0x44,},
- .pa_blk = {.id = SDE_SSPP_PA_V1,
- .base = 0x200, .len = 0x0,},
- .hist_lut = {.id = SDE_SSPP_HIST_V1,
- .base = 0xA00, .len = 0x400,},
- .pcc_blk = {.id = SDE_SSPP_PCC,
- .base = 0x1780, .len = 0x64,},
- };
-
- static const struct sde_sspp_sub_blks dma = {
- .maxlinewidth = 2560,
- .danger_lut = 0xFFFF,
- .safe_lut = 0xFF00,
- .maxdwnscale = 0, .maxupscale = 0,
- .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
- .scalar_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
- .pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x01780, .len = 0x64,},
- };
-
- static const struct sde_sspp_sub_blks cursor = {
- .maxlinewidth = 128,
- .danger_lut = 0xFFFF,
- .safe_lut = 0xFF00,
- .maxdwnscale = 0, .maxupscale = 0,
- .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
- .scalar_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
- .pcc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- };
-
- /* MIXER capability */
- static const struct sde_lm_sub_blks lm = {
- .maxwidth = 2560,
- .maxblendstages = 7, /* excluding base layer */
- .blendstage_base = { /* offsets relative to mixer base */
- 0x20, 0x50, 0x80, 0xB0, 0x230, 0x260, 0x290 }
- };
-
- /* DSPP capability */
- static const struct sde_dspp_sub_blks pp = {
- .igc = {.id = SDE_DSPP_GC, .base = 0x17c0, .len = 0x0,
- .version = 0x1},
- .pcc = {.id = SDE_DSPP_PCC, .base = 0x00, .len = 0x0,
- .version = 0x1},
- .gamut = {.id = SDE_DSPP_GAMUT, .base = 0x01600, .len = 0x0,
- .version = 0x1},
- .dither = {.id = SDE_DSPP_DITHER, .base = 0x00, .len = 0x0,
- .version = 0x1},
- .pa = {.id = SDE_DSPP_PA, .base = 0x00, .len = 0x0,
- .version = 0x1},
- .hist = {.id = SDE_DSPP_HIST, .base = 0x00, .len = 0x0,
- .version = 0x1},
- };
-
- /* PINGPONG capability */
- static const struct sde_pingpong_sub_blks p_p = {
- .te = {.id = SDE_PINGPONG_TE, .base = 0x0000, .len = 0x0,
- .version = 0x1},
- .te2 = {.id = SDE_PINGPONG_TE2, .base = 0x2000, .len = 0x0,
- .version = 0x1},
- .dsc = {.id = SDE_PINGPONG_DSC, .base = 0x10000, .len = 0x0,
- .version = 0x1},
- };
-
- /* Setup Register maps and defaults */
- *cfg = (struct sde_mdss_cfg){
- .mdss_count = 1,
- .mdss = {
- {.id = MDP_TOP, .base = 0x00000000, .features = 0}
- },
- .mdp_count = 1,
- .mdp = {
- {.id = MDP_TOP, .base = 0x00001000, .features = 0,
- .highest_bank_bit = 0x2},
- },
- .ctl_count = 5,
- .ctl = {
- {.id = CTL_0, .base = 0x00002000},
- {.id = CTL_1, .base = 0x00002200},
- {.id = CTL_2, .base = 0x00002400},
- {.id = CTL_3, .base = 0x00002600},
- {.id = CTL_4, .base = 0x00002800},
- },
- /* 4 VIG, + 4 RGB + 2 DMA + 2 CURSOR */
- .sspp_count = 12,
- .sspp = {
- {.id = SSPP_VIG0, .base = 0x00005000,
- .features = VIG_17X_MASK, .sblk = &layer},
- {.id = SSPP_VIG1, .base = 0x00007000,
- .features = VIG_17X_MASK, .sblk = &layer},
- {.id = SSPP_VIG2, .base = 0x00009000,
- .features = VIG_17X_MASK, .sblk = &layer},
- {.id = SSPP_VIG3, .base = 0x0000b000,
- .features = VIG_17X_MASK, .sblk = &layer},
-
- {.id = SSPP_RGB0, .base = 0x00015000,
- .features = RGB_17X_MASK, .sblk = &layer},
- {.id = SSPP_RGB1, .base = 0x00017000,
- .features = RGB_17X_MASK, .sblk = &layer},
- {.id = SSPP_RGB2, .base = 0x00019000,
- .features = RGB_17X_MASK, .sblk = &layer},
- {.id = SSPP_RGB3, .base = 0x0001B000,
- .features = RGB_17X_MASK, .sblk = &layer},
-
- {.id = SSPP_DMA0, .base = 0x00025000,
- .features = DMA_17X_MASK, .sblk = &dma},
- {.id = SSPP_DMA1, .base = 0x00027000,
- .features = DMA_17X_MASK, .sblk = &dma},
-
- {.id = SSPP_CURSOR0, .base = 0x00035000,
- .features = CURSOR_17X_MASK, .sblk = &cursor},
- {.id = SSPP_CURSOR1, .base = 0x00037000,
- .features = CURSOR_17X_MASK, .sblk = &cursor},
- },
- .mixer_count = 6,
- .mixer = {
- {.id = LM_0, .base = 0x00045000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- {.id = LM_1, .base = 0x00046000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- {.id = LM_2, .base = 0x00047000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- {.id = LM_3, .base = 0x00048000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- {.id = LM_4, .base = 0x00049000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- {.id = LM_5, .base = 0x0004a000,
- .features = MIXER_17X_MASK,
- .sblk = &lm},
- },
- .dspp_count = 2,
- .dspp = {
- {.id = DSPP_0, .base = 0x00055000,
- .features = DSPP_17X_MASK,
- .sblk = &pp},
- {.id = DSPP_1, .base = 0x00057000,
- .features = DSPP_17X_MASK,
- .sblk = &pp},
- },
- .pingpong_count = 4,
- .pingpong = {
- {.id = PINGPONG_0, .base = 0x00071000,
- .features = PINGPONG_17X_SPLIT_MASK,
- .sblk = &p_p},
- {.id = PINGPONG_1, .base = 0x00071800,
- .features = PINGPONG_17X_SPLIT_MASK,
- .sblk = &p_p},
- {.id = PINGPONG_2, .base = 0x00072000,
- .features = PINGPONG_17X_MASK,
- .sblk = &p_p},
- {.id = PINGPONG_3, .base = 0x00072800,
- .features = PINGPONG_17X_MASK,
- .sblk = &p_p},
- },
- .cdm_count = 1,
- .cdm = {
- {.id = CDM_0, .base = 0x0007A200, .features = 0,
- .intf_connect = { BIT(INTF_3)},
- .wb_connect = { BIT(WB_2)},}
- },
- .intf_count = 4,
- .intf = {
- {.id = INTF_0, .base = 0x0006B000,
- .type = INTF_NONE, .controller_id = 0,
- .prog_fetch_lines_worst_case = 21},
- {.id = INTF_1, .base = 0x0006B800,
- .type = INTF_DSI, .controller_id = 0,
- .prog_fetch_lines_worst_case = 21},
- {.id = INTF_2, .base = 0x0006C000,
- .type = INTF_DSI, .controller_id = 1,
- .prog_fetch_lines_worst_case = 21},
- {.id = INTF_3, .base = 0x0006C800,
- .type = INTF_HDMI, .controller_id = 0,
- .prog_fetch_lines_worst_case = 21},
- },
- .wb_count = 3,
- .wb = {
- {.id = WB_0, .base = 0x00065000,
- .features = WB01_17X_MASK},
- {.id = WB_1, .base = 0x00065800,
- .features = WB01_17X_MASK},
- {.id = WB_2, .base = 0x00066000,
- .features = WB2_17X_MASK},
- },
- .ad_count = 2,
- .ad = {
- {.id = AD_0, .base = 0x00079000},
- {.id = AD_1, .base = 0x00079800},
- },
- };
- return 0;
-}
-
-/**
- * sde_mdp_cfg_170_init(): Populate the sde sub-blocks catalog information
- */
-struct sde_mdss_cfg *sde_mdss_cfg_170_init(u32 step)
-{
- struct sde_mdss_cfg *m = NULL;
-
- /*
- * This function, for each sub-block sets,
- * instance count, IO regions,
- * default capabilities and this version capabilities,
- * Additional catalog items
- */
-
- m = kzalloc(sizeof(*m), GFP_KERNEL);
- if (!m)
- return NULL;
-
- set_cfg_1xx_init(m);
- m->hwversion = SDE_HW_VER(1, 7, step);
-
- return m;
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
deleted file mode 100644
index 25fc55191045..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_cdm.h"
-
-#define CDM_CSC_10_OPMODE 0x000
-#define CDM_CSC_10_BASE 0x004
-
-#define CDM_CDWN2_OP_MODE 0x100
-#define CDM_CDWN2_CLAMP_OUT 0x104
-#define CDM_CDWN2_PARAMS_3D_0 0x108
-#define CDM_CDWN2_PARAMS_3D_1 0x10C
-#define CDM_CDWN2_COEFF_COSITE_H_0 0x110
-#define CDM_CDWN2_COEFF_COSITE_H_1 0x114
-#define CDM_CDWN2_COEFF_COSITE_H_2 0x118
-#define CDM_CDWN2_COEFF_OFFSITE_H_0 0x11C
-#define CDM_CDWN2_COEFF_OFFSITE_H_1 0x120
-#define CDM_CDWN2_COEFF_OFFSITE_H_2 0x124
-#define CDM_CDWN2_COEFF_COSITE_V 0x128
-#define CDM_CDWN2_COEFF_OFFSITE_V 0x12C
-#define CDM_CDWN2_OUT_SIZE 0x130
-
-#define CDM_HDMI_PACK_OP_MODE 0x200
-#define CDM_CSC_10_MATRIX_COEFF_0 0x204
-
-/**
- * Horizontal coeffiecients for cosite chroma downscale
- * s13 repesentation of coefficients
- */
-static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
-
-/**
- * Horizontal coefficients for offsite chroma downscale
- */
-static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
-
-/**
- * Vertical coefficients for cosite chroma downscale
- */
-static u32 cosite_v_coeff[] = {0x00080004};
-/**
- * Vertical coefficients for offsite chroma downscale
- */
-static u32 offsite_v_coeff[] = {0x00060002};
-
-/* Limited Range rgb2yuv coeff with clamp and bias values for CSC 10 module */
-static struct sde_csc_cfg rgb2yuv_cfg = {
- {
- 0x0083, 0x0102, 0x0032,
- 0x1fb5, 0x1f6c, 0x00e1,
- 0x00e1, 0x1f45, 0x1fdc
- },
- { 0x00, 0x00, 0x00 },
- { 0x0040, 0x0200, 0x0200 },
- { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
- { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
-};
-
-static struct sde_cdm_cfg *_cdm_offset(enum sde_cdm cdm,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->cdm_count; i++) {
- if (cdm == m->cdm[i].id) {
- b->base_off = addr;
- b->blk_off = m->cdm[i].base;
- b->hwversion = m->hwversion;
- return &m->cdm[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-static void sde_hw_cdm_setup_csc_10bit(struct sde_hw_cdm *ctx,
- struct sde_csc_cfg *data)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
-
- sde_hw_csc_setup(c, CDM_CSC_10_MATRIX_COEFF_0, data);
-}
-
-int sde_hw_cdm_setup_cdwn(struct sde_hw_cdm *ctx,
- struct sde_hw_cdm_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 opmode = 0;
- u32 out_size = 0;
-
- if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
- opmode &= ~BIT(7);
- else
- opmode |= BIT(7);
-
- /* ENABLE DWNS_H bit */
- opmode |= BIT(1);
-
- switch (cfg->h_cdwn_type) {
- case CDM_CDWN_DISABLE:
- /* CLEAR METHOD_H field */
- opmode &= ~(0x18);
- /* CLEAR DWNS_H bit */
- opmode &= ~BIT(1);
- break;
- case CDM_CDWN_PIXEL_DROP:
- /* Clear METHOD_H field (pixel drop is 0) */
- opmode &= ~(0x18);
- break;
- case CDM_CDWN_AVG:
- /* Clear METHOD_H field (Average is 0x1) */
- opmode &= ~(0x18);
- opmode |= (0x1 << 0x3);
- break;
- case CDM_CDWN_COSITE:
- /* Clear METHOD_H field (Average is 0x2) */
- opmode &= ~(0x18);
- opmode |= (0x2 << 0x3);
- /* Co-site horizontal coefficients */
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
- cosite_h_coeff[0]);
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
- cosite_h_coeff[1]);
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
- cosite_h_coeff[2]);
- break;
- case CDM_CDWN_OFFSITE:
- /* Clear METHOD_H field (Average is 0x3) */
- opmode &= ~(0x18);
- opmode |= (0x3 << 0x3);
-
- /* Off-site horizontal coefficients */
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
- offsite_h_coeff[0]);
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
- offsite_h_coeff[1]);
- SDE_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
- offsite_h_coeff[2]);
- break;
- default:
- pr_err("%s invalid horz down sampling type\n", __func__);
- return -EINVAL;
- }
-
- /* ENABLE DWNS_V bit */
- opmode |= BIT(2);
-
- switch (cfg->v_cdwn_type) {
- case CDM_CDWN_DISABLE:
- /* CLEAR METHOD_V field */
- opmode &= ~(0x60);
- /* CLEAR DWNS_V bit */
- opmode &= ~BIT(2);
- break;
- case CDM_CDWN_PIXEL_DROP:
- /* Clear METHOD_V field (pixel drop is 0) */
- opmode &= ~(0x60);
- break;
- case CDM_CDWN_AVG:
- /* Clear METHOD_V field (Average is 0x1) */
- opmode &= ~(0x60);
- opmode |= (0x1 << 0x5);
- break;
- case CDM_CDWN_COSITE:
- /* Clear METHOD_V field (Average is 0x2) */
- opmode &= ~(0x60);
- opmode |= (0x2 << 0x5);
- /* Co-site vertical coefficients */
- SDE_REG_WRITE(c,
- CDM_CDWN2_COEFF_COSITE_V,
- cosite_v_coeff[0]);
- break;
- case CDM_CDWN_OFFSITE:
- /* Clear METHOD_V field (Average is 0x3) */
- opmode &= ~(0x60);
- opmode |= (0x3 << 0x5);
-
- /* Off-site vertical coefficients */
- SDE_REG_WRITE(c,
- CDM_CDWN2_COEFF_OFFSITE_V,
- offsite_v_coeff[0]);
- break;
- default:
- return -EINVAL;
- }
-
- if (cfg->v_cdwn_type || cfg->h_cdwn_type)
- opmode |= BIT(0); /* EN CDWN module */
- else
- opmode &= ~BIT(0);
-
- out_size = (cfg->output_width & 0xFFFF) |
- ((cfg->output_height & 0xFFFF) << 16);
- SDE_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
- SDE_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
- SDE_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
- ((0x3FF << 16) | 0x0));
-
- return 0;
-}
-
-int sde_hw_cdm_enable(struct sde_hw_cdm *ctx,
- struct sde_hw_cdm_cfg *cdm)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- struct sde_mdp_format_params *fmt = cdm->output_fmt;
- u32 opmode = 0;
- u32 cdm_enable = 0;
- u32 csc = 0;
-
- if (!fmt->is_yuv)
- return 0;
-
- if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
- if (fmt->chroma_sample != SDE_MDP_CHROMA_H1V2)
- return -EINVAL; /*unsupported format */
- opmode = BIT(0);
- opmode |= (fmt->chroma_sample << 1);
- cdm_enable |= BIT(19);
- } else {
- opmode = 0;
- cdm_enable = BIT(24);
- }
-
- csc |= BIT(2);
- csc &= ~BIT(1);
- csc |= BIT(0);
-
- /* For this register we need to offset it to MDP TOP BLOCK */
- SDE_REG_WRITE(c, MDP_OUT_CTL_0, cdm_enable);
-
- SDE_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
- SDE_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
- return 0;
-}
-
-void sde_hw_cdm_disable(struct sde_hw_cdm *ctx)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
-
- /* mdp top block */
- SDE_REG_WRITE(c, MDP_OUT_CTL_0, 0); /* bypass mode */
-}
-
-static void _setup_cdm_ops(struct sde_hw_cdm_ops *ops,
- unsigned long features)
-{
- ops->setup_csc_data = sde_hw_cdm_setup_csc_10bit;
- ops->setup_cdwn = sde_hw_cdm_setup_cdwn;
- ops->enable = sde_hw_cdm_enable;
- ops->disable = sde_hw_cdm_disable;
-}
-
-struct sde_hw_cdm *sde_hw_cdm_init(enum sde_cdm idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_cdm *c;
- struct sde_cdm_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _cdm_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- c->idx = idx;
- c->cdm_hw_cap = cfg;
- _setup_cdm_ops(&c->ops, c->cdm_hw_cap->features);
-
- /*
- * Perform any default initialization for the chroma down module
- * @setup default csc coefficients
- */
- sde_hw_cdm_setup_csc_10bit(c, &rgb2yuv_cfg);
-
- return c;
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h b/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
deleted file mode 100644
index ea19dc208c7f..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_CDM_H
-#define _SDE_HW_CDM_H
-
-#include "sde_hw_mdss.h"
-
-struct sde_hw_cdm;
-
-struct sde_hw_cdm_cfg {
- u32 output_width;
- u32 output_height;
- u32 output_bit_depth;
- u32 h_cdwn_type;
- u32 v_cdwn_type;
- struct sde_mdp_format_params *output_fmt;
- u32 output_type;
- int flags;
-};
-
-enum sde_hw_cdwn_type {
- CDM_CDWN_DISABLE,
- CDM_CDWN_PIXEL_DROP,
- CDM_CDWN_AVG,
- CDM_CDWN_COSITE,
- CDM_CDWN_OFFSITE,
-};
-
-enum sde_hw_cdwn_output_type {
- CDM_CDWN_OUTPUT_HDMI,
- CDM_CDWN_OUTPUT_WB,
-};
-
-enum sde_hw_cdwn_output_bit_depth {
- CDM_CDWN_OUTPUT_8BIT,
- CDM_CDWN_OUTPUT_10BIT,
-};
-
-/**
- * struct sde_hw_cdm_ops : Interface to the chroma down Hw driver functions
- * Assumption is these functions will be called after
- * clocks are enabled
- * @setup_csc: Programs the csc matrix
- * @setup_cdwn: Sets up the chroma down sub module
- * @enable: Enables the output to interface and programs the
- * output packer
- * @disable: Puts the cdm in bypass mode
- */
-struct sde_hw_cdm_ops {
- /**
- * Programs the CSC matrix for conversion from RGB space to YUV space,
- * it is optinal to call this function as this matrix is automatically
- * set during initialization, user should call this if it wants
- * to program a different matrix than default matrix.
- * @cdm: Pointer to the chroma down context structure
- * @data Pointer to CSC configuration data
- */
- void (*setup_csc_data)(struct sde_hw_cdm *cdm,
- struct sde_csc_cfg *data);
-
- /**
- * Programs the Chroma downsample part.
- * @cdm Pointer to chroma down context
- */
- int (*setup_cdwn)(struct sde_hw_cdm *cdm,
- struct sde_hw_cdm_cfg *cfg);
-
- /**
- * Enable the CDM module
- * @cdm Pointer to chroma down context
- */
- int (*enable)(struct sde_hw_cdm *cdm,
- struct sde_hw_cdm_cfg *cfg);
-
- /**
- * Disable the CDM module
- * @cdm Pointer to chroma down context
- */
- void (*disable)(struct sde_hw_cdm *cdm);
-};
-
-struct sde_hw_cdm {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* chroma down */
- const struct sde_cdm_cfg *cdm_hw_cap;
- enum sde_cdm idx;
-
- /* ops */
- struct sde_hw_cdm_ops ops;
-};
-
-/**
- * sde_hw_cdm_init(): Initializes the cdm hw driver object.
- * should be called once before accessing every cdm.
- * @idx: cdm index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_cdm *sde_hw_cdm_init(enum sde_cdm idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-#endif /*_SDE_HW_CDM_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
deleted file mode 100644
index e87ca9570443..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_dspp.h"
-
-static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->dspp_count; i++) {
- if (dspp == m->dspp[i].id) {
- b->base_off = addr;
- b->blk_off = m->dspp[i].base;
- b->hwversion = m->hwversion;
- return &m->dspp[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-void sde_dspp_setup_histogram(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_read_histogram(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_update_igc(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_setup_pa(struct sde_hw_dspp *dspp, void *cfg)
-{
-}
-
-void sde_dspp_setup_pcc(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_setup_sharpening(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_setup_pa_memcolor(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_setup_sixzone(struct sde_hw_dspp *dspp)
-{
-}
-
-void sde_dspp_setup_danger_safe(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-void sde_dspp_setup_dither(struct sde_hw_dspp *ctx, void *cfg)
-{
-}
-
-static void _setup_dspp_ops(struct sde_hw_dspp_ops *ops,
- unsigned long features)
-{
-}
-struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_dspp *c;
- struct sde_dspp_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _dspp_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- /* Assign ops */
- c->idx = idx;
- c->cap = cfg;
- _setup_dspp_ops(&c->ops, c->cap->features);
-
- return c;
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
deleted file mode 100644
index eef4fbdff2a7..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_DSPP_H
-#define _SDE_HW_DSPP_H
-
-struct sde_hw_dspp;
-
-/**
- * struct sde_hw_dspp_ops - interface to the dspp hardware driver functions
- * Caller must call the init function to get the dspp context for each dspp
- * Assumption is these functions will be called after clocks are enabled
- */
-struct sde_hw_dspp_ops {
- /**
- * setup_histogram - setup dspp histogram
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_histogram)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * read_histogram - read dspp histogram
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*read_histogram)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * update_igc - update dspp igc
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*update_igc)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * setup_pa - setup dspp pa
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_pa)(struct sde_hw_dspp *dspp, void *cfg);
-
- /**
- * setup_pcc - setup dspp pcc
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_pcc)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * setup_sharpening - setup dspp sharpening
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_sharpening)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * setup_pa_memcolor - setup dspp memcolor
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_pa_memcolor)(struct sde_hw_dspp *ctx, void *cfg);
-
- /**
- * setup_sixzone - setup dspp six zone
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_sixzone)(struct sde_hw_dspp *dspp);
-
- /**
- * setup_danger_safe - setup danger safe LUTS
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_danger_safe)(struct sde_hw_dspp *ctx, void *cfg);
- /**
- * setup_dither - setup dspp dither
- * @ctx: Pointer to dspp context
- * @cfg: Pointer to configuration
- */
- void (*setup_dither)(struct sde_hw_dspp *ctx, void *cfg);
-};
-
-/**
- * struct sde_hw_dspp - dspp description
- * @base_off: MDP register mapped offset
- * @blk_off: DSPP offset relative to mdss offset
- * @length Length of register block offset
- * @hwversion Mdss hw version number
- * @idx: DSPP index
- * @dspp_hw_cap: Pointer to layer_cfg
- * @highest_bank_bit:
- * @ops: Pointer to operations possible for this dspp
- */
-struct sde_hw_dspp {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* dspp */
- enum sde_dspp idx;
- const struct sde_dspp_cfg *cap;
-
- /* Ops */
- struct sde_hw_dspp_ops ops;
-};
-
-/**
- * sde_hw_dspp_init - initializes the dspp hw driver object.
- * should be called once before accessing every dspp.
- * @idx: DSPP index for which driver object is required
- * @addr: Mapped register io address of MDP
- */
-struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-#endif /*_SDE_HW_DSPP_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
deleted file mode 100644
index 99aa2e59dd85..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include "sde_kms.h"
-#include "sde_hw_interrupts.h"
-#include "sde_hw_mdp_util.h"
-#include "sde_hw_mdss.h"
-
-/**
- * Register offsets in MDSS register file for the interrupt registers
- * w.r.t. to the MDSS base
- */
-#define HW_INTR_STATUS 0x0010
-#define MDP_SSPP_TOP0_OFF 0x1000
-#define MDP_INTF_0_OFF 0x6B000
-#define MDP_INTF_1_OFF 0x6B800
-#define MDP_INTF_2_OFF 0x6C000
-#define MDP_INTF_3_OFF 0x6C800
-#define MDP_INTF_4_OFF 0x6D000
-
-/**
- * WB interrupt status bit definitions
- */
-#define SDE_INTR_WB_0_DONE BIT(0)
-#define SDE_INTR_WB_1_DONE BIT(1)
-#define SDE_INTR_WB_2_DONE BIT(4)
-
-/**
- * WDOG timer interrupt status bit definitions
- */
-#define SDE_INTR_WD_TIMER_0_DONE BIT(2)
-#define SDE_INTR_WD_TIMER_1_DONE BIT(3)
-#define SDE_INTR_WD_TIMER_2_DONE BIT(5)
-#define SDE_INTR_WD_TIMER_3_DONE BIT(6)
-#define SDE_INTR_WD_TIMER_4_DONE BIT(7)
-
-/**
- * Pingpong interrupt status bit definitions
- */
-#define SDE_INTR_PING_PONG_0_DONE BIT(8)
-#define SDE_INTR_PING_PONG_1_DONE BIT(9)
-#define SDE_INTR_PING_PONG_2_DONE BIT(10)
-#define SDE_INTR_PING_PONG_3_DONE BIT(11)
-#define SDE_INTR_PING_PONG_0_RD_PTR BIT(12)
-#define SDE_INTR_PING_PONG_1_RD_PTR BIT(13)
-#define SDE_INTR_PING_PONG_2_RD_PTR BIT(14)
-#define SDE_INTR_PING_PONG_3_RD_PTR BIT(15)
-#define SDE_INTR_PING_PONG_0_WR_PTR BIT(16)
-#define SDE_INTR_PING_PONG_1_WR_PTR BIT(17)
-#define SDE_INTR_PING_PONG_2_WR_PTR BIT(18)
-#define SDE_INTR_PING_PONG_3_WR_PTR BIT(19)
-#define SDE_INTR_PING_PONG_0_AUTOREFRESH_DONE BIT(20)
-#define SDE_INTR_PING_PONG_1_AUTOREFRESH_DONE BIT(21)
-#define SDE_INTR_PING_PONG_2_AUTOREFRESH_DONE BIT(22)
-#define SDE_INTR_PING_PONG_3_AUTOREFRESH_DONE BIT(23)
-
-/**
- * Interface interrupt status bit definitions
- */
-#define SDE_INTR_INTF_0_UNDERRUN BIT(24)
-#define SDE_INTR_INTF_1_UNDERRUN BIT(26)
-#define SDE_INTR_INTF_2_UNDERRUN BIT(28)
-#define SDE_INTR_INTF_3_UNDERRUN BIT(30)
-#define SDE_INTR_INTF_0_VSYNC BIT(25)
-#define SDE_INTR_INTF_1_VSYNC BIT(27)
-#define SDE_INTR_INTF_2_VSYNC BIT(29)
-#define SDE_INTR_INTF_3_VSYNC BIT(31)
-
-/**
- * Pingpong Secondary interrupt status bit definitions
- */
-#define SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE BIT(0)
-#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
-#define SDE_INTR_PING_PONG_S0_RD_PTR BIT(8)
-#define SDE_INTR_PING_PONG_S0_TEAR_DETECTED BIT(22)
-#define SDE_INTR_PING_PONG_S0_TE_DETECTED BIT(28)
-
-/**
- * Pingpong TEAR detection interrupt status bit definitions
- */
-#define SDE_INTR_PING_PONG_0_TEAR_DETECTED BIT(16)
-#define SDE_INTR_PING_PONG_1_TEAR_DETECTED BIT(17)
-#define SDE_INTR_PING_PONG_2_TEAR_DETECTED BIT(18)
-#define SDE_INTR_PING_PONG_3_TEAR_DETECTED BIT(19)
-
-/**
- * Pingpong TE detection interrupt status bit definitions
- */
-#define SDE_INTR_PING_PONG_0_TE_DETECTED BIT(24)
-#define SDE_INTR_PING_PONG_1_TE_DETECTED BIT(25)
-#define SDE_INTR_PING_PONG_2_TE_DETECTED BIT(26)
-#define SDE_INTR_PING_PONG_3_TE_DETECTED BIT(27)
-
-/**
- * Concurrent WB overflow interrupt status bit definitions
- */
-#define SDE_INTR_CWB_2_OVERFLOW BIT(14)
-#define SDE_INTR_CWB_3_OVERFLOW BIT(15)
-
-/**
- * Histogram VIG done interrupt status bit definitions
- */
-#define SDE_INTR_HIST_VIG_0_DONE BIT(0)
-#define SDE_INTR_HIST_VIG_1_DONE BIT(4)
-#define SDE_INTR_HIST_VIG_2_DONE BIT(8)
-#define SDE_INTR_HIST_VIG_3_DONE BIT(10)
-
-/**
- * Histogram VIG reset Sequence done interrupt status bit definitions
- */
-#define SDE_INTR_HIST_VIG_0_RSTSEQ_DONE BIT(1)
-#define SDE_INTR_HIST_VIG_1_RSTSEQ_DONE BIT(5)
-#define SDE_INTR_HIST_VIG_2_RSTSEQ_DONE BIT(9)
-#define SDE_INTR_HIST_VIG_3_RSTSEQ_DONE BIT(11)
-
-/**
- * Histogram DSPP done interrupt status bit definitions
- */
-#define SDE_INTR_HIST_DSPP_0_DONE BIT(12)
-#define SDE_INTR_HIST_DSPP_1_DONE BIT(16)
-#define SDE_INTR_HIST_DSPP_2_DONE BIT(20)
-#define SDE_INTR_HIST_DSPP_3_DONE BIT(22)
-
-/**
- * Histogram DSPP reset Sequence done interrupt status bit definitions
- */
-#define SDE_INTR_HIST_DSPP_0_RSTSEQ_DONE BIT(13)
-#define SDE_INTR_HIST_DSPP_1_RSTSEQ_DONE BIT(17)
-#define SDE_INTR_HIST_DSPP_2_RSTSEQ_DONE BIT(21)
-#define SDE_INTR_HIST_DSPP_3_RSTSEQ_DONE BIT(23)
-
-/**
- * INTF interrupt status bit definitions
- */
-#define SDE_INTR_VIDEO_INTO_STATIC BIT(0)
-#define SDE_INTR_VIDEO_OUTOF_STATIC BIT(1)
-#define SDE_INTR_DSICMD_0_INTO_STATIC BIT(2)
-#define SDE_INTR_DSICMD_0_OUTOF_STATIC BIT(3)
-#define SDE_INTR_DSICMD_1_INTO_STATIC BIT(4)
-#define SDE_INTR_DSICMD_1_OUTOF_STATIC BIT(5)
-#define SDE_INTR_DSICMD_2_INTO_STATIC BIT(6)
-#define SDE_INTR_DSICMD_2_OUTOF_STATIC BIT(7)
-#define SDE_INTR_PROG_LINE BIT(8)
-
-/**
- * struct sde_intr_reg - array of SDE register sets
- * @clr_off: offset to CLEAR reg
- * @en_off: offset to ENABLE reg
- * @status_off: offset to STATUS reg
- */
-struct sde_intr_reg {
- u32 clr_off;
- u32 en_off;
- u32 status_off;
-};
-
-/**
- * struct sde_irq_type - maps each irq with i/f
- * @intr_type: type of interrupt listed in sde_intr_type
- * @instance_idx: instance index of the associated HW block in SDE
- * @irq_mask: corresponding bit in the interrupt status reg
- * @reg_idx: which reg set to use
- */
-struct sde_irq_type {
- u32 intr_type;
- u32 instance_idx;
- u32 irq_mask;
- u32 reg_idx;
-};
-
-/**
- * List of SDE interrupt registers
- */
-static const struct sde_intr_reg sde_intr_set[] = {
- {
- MDP_SSPP_TOP0_OFF+INTR_CLEAR,
- MDP_SSPP_TOP0_OFF+INTR_EN,
- MDP_SSPP_TOP0_OFF+INTR_STATUS
- },
- {
- MDP_SSPP_TOP0_OFF+INTR2_CLEAR,
- MDP_SSPP_TOP0_OFF+INTR2_EN,
- MDP_SSPP_TOP0_OFF+INTR2_STATUS
- },
- {
- MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR,
- MDP_SSPP_TOP0_OFF+HIST_INTR_EN,
- MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS
- },
- {
- MDP_INTF_0_OFF+INTF_INTR_CLEAR,
- MDP_INTF_0_OFF+INTF_INTR_EN,
- MDP_INTF_0_OFF+INTF_INTR_STATUS
- },
- {
- MDP_INTF_1_OFF+INTF_INTR_CLEAR,
- MDP_INTF_1_OFF+INTF_INTR_EN,
- MDP_INTF_1_OFF+INTF_INTR_STATUS
- },
- {
- MDP_INTF_2_OFF+INTF_INTR_CLEAR,
- MDP_INTF_2_OFF+INTF_INTR_EN,
- MDP_INTF_2_OFF+INTF_INTR_STATUS
- },
- {
- MDP_INTF_3_OFF+INTF_INTR_CLEAR,
- MDP_INTF_3_OFF+INTF_INTR_EN,
- MDP_INTF_3_OFF+INTF_INTR_STATUS
- },
- {
- MDP_INTF_4_OFF+INTF_INTR_CLEAR,
- MDP_INTF_4_OFF+INTF_INTR_EN,
- MDP_INTF_4_OFF+INTF_INTR_STATUS
- }
-};
-
-/**
- * IRQ mapping table - use for lookup an irq_idx in this table that have
- * a matching interface type and instance index.
- */
-static const struct sde_irq_type sde_irq_map[] = {
- /* BEGIN MAP_RANGE: 0-31, INTR */
- /* irq_idx: 0-3 */
- { SDE_IRQ_TYPE_WB_ROT_COMP, WB_0, SDE_INTR_WB_0_DONE, 0},
- { SDE_IRQ_TYPE_WB_ROT_COMP, WB_1, SDE_INTR_WB_1_DONE, 0},
- { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_0, SDE_INTR_WD_TIMER_0_DONE, 0},
- { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_1, SDE_INTR_WD_TIMER_1_DONE, 0},
- /* irq_idx: 4-7 */
- { SDE_IRQ_TYPE_WB_WFD_COMP, WB_2, SDE_INTR_WB_2_DONE, 0},
- { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_2, SDE_INTR_WD_TIMER_2_DONE, 0},
- { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_3, SDE_INTR_WD_TIMER_3_DONE, 0},
- { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_4, SDE_INTR_WD_TIMER_4_DONE, 0},
- /* irq_idx: 8-11 */
- { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_0,
- SDE_INTR_PING_PONG_0_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_1,
- SDE_INTR_PING_PONG_1_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_2,
- SDE_INTR_PING_PONG_2_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_3,
- SDE_INTR_PING_PONG_3_DONE, 0},
- /* irq_idx: 12-15 */
- { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_0,
- SDE_INTR_PING_PONG_0_RD_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_1,
- SDE_INTR_PING_PONG_1_RD_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_2,
- SDE_INTR_PING_PONG_2_RD_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_3,
- SDE_INTR_PING_PONG_3_RD_PTR, 0},
- /* irq_idx: 16-19 */
- { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_0,
- SDE_INTR_PING_PONG_0_WR_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_1,
- SDE_INTR_PING_PONG_1_WR_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_2,
- SDE_INTR_PING_PONG_2_WR_PTR, 0},
- { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_3,
- SDE_INTR_PING_PONG_3_WR_PTR, 0},
- /* irq_idx: 20-23 */
- { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_0,
- SDE_INTR_PING_PONG_0_AUTOREFRESH_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_1,
- SDE_INTR_PING_PONG_1_AUTOREFRESH_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_2,
- SDE_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0},
- { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_3,
- SDE_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0},
- /* irq_idx: 24-27 */
- { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_0, SDE_INTR_INTF_0_UNDERRUN, 0},
- { SDE_IRQ_TYPE_INTF_VSYNC, INTF_0, SDE_INTR_INTF_0_VSYNC, 0},
- { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_1, SDE_INTR_INTF_1_UNDERRUN, 0},
- { SDE_IRQ_TYPE_INTF_VSYNC, INTF_1, SDE_INTR_INTF_1_VSYNC, 0},
- /* irq_idx: 28-31 */
- { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_2, SDE_INTR_INTF_2_UNDERRUN, 0},
- { SDE_IRQ_TYPE_INTF_VSYNC, INTF_2, SDE_INTR_INTF_2_VSYNC, 0},
- { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_3, SDE_INTR_INTF_3_UNDERRUN, 0},
- { SDE_IRQ_TYPE_INTF_VSYNC, INTF_3, SDE_INTR_INTF_3_VSYNC, 0},
-
- /* BEGIN MAP_RANGE: 32-64, INTR2 */
- /* irq_idx: 32-35 */
- { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_S0,
- SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- /* irq_idx: 36-39 */
- { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_S0,
- SDE_INTR_PING_PONG_S0_WR_PTR, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- /* irq_idx: 40-43 */
- { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_S0,
- SDE_INTR_PING_PONG_S0_RD_PTR, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- /* irq_idx: 44-47 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_2, SDE_INTR_CWB_2_OVERFLOW, 1},
- { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_3, SDE_INTR_CWB_3_OVERFLOW, 1},
- /* irq_idx: 48-51 */
- { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_0,
- SDE_INTR_PING_PONG_0_TEAR_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_1,
- SDE_INTR_PING_PONG_1_TEAR_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_2,
- SDE_INTR_PING_PONG_2_TEAR_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_3,
- SDE_INTR_PING_PONG_3_TEAR_DETECTED, 1},
- /* irq_idx: 52-55 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_S0,
- SDE_INTR_PING_PONG_S0_TEAR_DETECTED, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- /* irq_idx: 56-59 */
- { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_0,
- SDE_INTR_PING_PONG_0_TE_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_1,
- SDE_INTR_PING_PONG_1_TE_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_2,
- SDE_INTR_PING_PONG_2_TE_DETECTED, 1},
- { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_3,
- SDE_INTR_PING_PONG_3_TE_DETECTED, 1},
- /* irq_idx: 60-63 */
- { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_S0,
- SDE_INTR_PING_PONG_S0_TE_DETECTED, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
-
- /* BEGIN MAP_RANGE: 64-95 HIST */
- /* irq_idx: 64-67 */
- { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG0, SDE_INTR_HIST_VIG_0_DONE, 2},
- { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG0,
- SDE_INTR_HIST_VIG_0_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 68-71 */
- { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG1, SDE_INTR_HIST_VIG_1_DONE, 2},
- { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG1,
- SDE_INTR_HIST_VIG_1_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 68-71 */
- { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG2, SDE_INTR_HIST_VIG_2_DONE, 2},
- { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG2,
- SDE_INTR_HIST_VIG_2_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG3, SDE_INTR_HIST_VIG_3_DONE, 2},
- { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG3,
- SDE_INTR_HIST_VIG_3_RSTSEQ_DONE, 2},
- /* irq_idx: 72-75 */
- { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_0, SDE_INTR_HIST_DSPP_0_DONE, 2},
- { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_0,
- SDE_INTR_HIST_DSPP_0_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 76-79 */
- { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_1, SDE_INTR_HIST_DSPP_1_DONE, 2},
- { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_1,
- SDE_INTR_HIST_DSPP_1_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 80-83 */
- { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_2, SDE_INTR_HIST_DSPP_2_DONE, 2},
- { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_2,
- SDE_INTR_HIST_DSPP_2_RSTSEQ_DONE, 2},
- { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_3, SDE_INTR_HIST_DSPP_3_DONE, 2},
- { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_3,
- SDE_INTR_HIST_DSPP_3_RSTSEQ_DONE, 2},
- /* irq_idx: 84-87 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 88-91 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 92-95 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
-
- /* BEGIN MAP_RANGE: 96-127 INTF_0_INTR */
- /* irq_idx: 96-99 */
- { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_0,
- SDE_INTR_VIDEO_INTO_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_0,
- SDE_INTR_VIDEO_OUTOF_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_0,
- SDE_INTR_DSICMD_0_INTO_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_0,
- SDE_INTR_DSICMD_0_OUTOF_STATIC, 3},
- /* irq_idx: 100-103 */
- { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_0,
- SDE_INTR_DSICMD_1_INTO_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_0,
- SDE_INTR_DSICMD_1_OUTOF_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_0,
- SDE_INTR_DSICMD_2_INTO_STATIC, 3},
- { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_0,
- SDE_INTR_DSICMD_2_OUTOF_STATIC, 3},
- /* irq_idx: 104-107 */
- { SDE_IRQ_TYPE_PROG_LINE, INTF_0, SDE_INTR_PROG_LINE, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- /* irq_idx: 108-111 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- /* irq_idx: 112-115 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- /* irq_idx: 116-119 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- /* irq_idx: 120-123 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- /* irq_idx: 124-127 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
-
- /* BEGIN MAP_RANGE: 128-159 INTF_1_INTR */
- /* irq_idx: 128-131 */
- { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_1,
- SDE_INTR_VIDEO_INTO_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_1,
- SDE_INTR_VIDEO_OUTOF_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_1,
- SDE_INTR_DSICMD_0_INTO_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_1,
- SDE_INTR_DSICMD_0_OUTOF_STATIC, 4},
- /* irq_idx: 132-135 */
- { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_1,
- SDE_INTR_DSICMD_1_INTO_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_1,
- SDE_INTR_DSICMD_1_OUTOF_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_1,
- SDE_INTR_DSICMD_2_INTO_STATIC, 4},
- { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_1,
- SDE_INTR_DSICMD_2_OUTOF_STATIC, 4},
- /* irq_idx: 136-139 */
- { SDE_IRQ_TYPE_PROG_LINE, INTF_1, SDE_INTR_PROG_LINE, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- /* irq_idx: 140-143 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- /* irq_idx: 144-147 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- /* irq_idx: 148-151 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- /* irq_idx: 152-155 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- /* irq_idx: 156-159 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
-
- /* BEGIN MAP_RANGE: 160-191 INTF_2_INTR */
- /* irq_idx: 160-163 */
- { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_2,
- SDE_INTR_VIDEO_INTO_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_2,
- SDE_INTR_VIDEO_OUTOF_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_2,
- SDE_INTR_DSICMD_0_INTO_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_2,
- SDE_INTR_DSICMD_0_OUTOF_STATIC, 5},
- /* irq_idx: 164-167 */
- { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_2,
- SDE_INTR_DSICMD_1_INTO_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_2,
- SDE_INTR_DSICMD_1_OUTOF_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_2,
- SDE_INTR_DSICMD_2_INTO_STATIC, 5},
- { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_2,
- SDE_INTR_DSICMD_2_OUTOF_STATIC, 5},
- /* irq_idx: 168-171 */
- { SDE_IRQ_TYPE_PROG_LINE, INTF_2, SDE_INTR_PROG_LINE, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- /* irq_idx: 172-175 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- /* irq_idx: 176-179 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- /* irq_idx: 180-183 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- /* irq_idx: 184-187 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- /* irq_idx: 188-191 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
-
- /* BEGIN MAP_RANGE: 192-223 INTF_3_INTR */
- /* irq_idx: 192-195 */
- { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_3,
- SDE_INTR_VIDEO_INTO_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_3,
- SDE_INTR_VIDEO_OUTOF_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_3,
- SDE_INTR_DSICMD_0_INTO_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_3,
- SDE_INTR_DSICMD_0_OUTOF_STATIC, 6},
- /* irq_idx: 196-199 */
- { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_3,
- SDE_INTR_DSICMD_1_INTO_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_3,
- SDE_INTR_DSICMD_1_OUTOF_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_3,
- SDE_INTR_DSICMD_2_INTO_STATIC, 6},
- { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_3,
- SDE_INTR_DSICMD_2_OUTOF_STATIC, 6},
- /* irq_idx: 200-203 */
- { SDE_IRQ_TYPE_PROG_LINE, INTF_3, SDE_INTR_PROG_LINE, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- /* irq_idx: 204-207 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- /* irq_idx: 208-211 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- /* irq_idx: 212-215 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- /* irq_idx: 216-219 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- /* irq_idx: 220-223 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
-
- /* BEGIN MAP_RANGE: 224-255 INTF_4_INTR */
- /* irq_idx: 224-227 */
- { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_4,
- SDE_INTR_VIDEO_INTO_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_4,
- SDE_INTR_VIDEO_OUTOF_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_4,
- SDE_INTR_DSICMD_0_INTO_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_4,
- SDE_INTR_DSICMD_0_OUTOF_STATIC, 7},
- /* irq_idx: 228-231 */
- { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_4,
- SDE_INTR_DSICMD_1_INTO_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_4,
- SDE_INTR_DSICMD_1_OUTOF_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_4,
- SDE_INTR_DSICMD_2_INTO_STATIC, 7},
- { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_4,
- SDE_INTR_DSICMD_2_OUTOF_STATIC, 7},
- /* irq_idx: 232-235 */
- { SDE_IRQ_TYPE_PROG_LINE, INTF_4, SDE_INTR_PROG_LINE, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- /* irq_idx: 236-239 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- /* irq_idx: 240-243 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- /* irq_idx: 244-247 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- /* irq_idx: 248-251 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- /* irq_idx: 252-255 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
-};
-
-static int sde_hw_intr_irqidx_lookup(enum sde_intr_type intr_type,
- u32 instance_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sde_irq_map); i++) {
- if (intr_type == sde_irq_map[i].intr_type &&
- instance_idx == sde_irq_map[i].instance_idx)
- return i;
- }
-
- pr_debug("IRQ lookup fail!! intr_type=%d, instance_idx=%d\n",
- intr_type, instance_idx);
- return -EINVAL;
-}
-
-static void sde_hw_intr_set_mask(struct sde_hw_intr *intr, uint32_t reg_off,
- uint32_t mask)
-{
- SDE_REG_WRITE(&intr->hw, reg_off, mask);
-}
-
-static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
- void (*cbfunc)(void *, int),
- void *arg)
-{
- int reg_idx;
- int irq_idx;
- int start_idx;
- int end_idx;
- u32 irq_status;
- unsigned long irq_flags;
-
- /*
- * The dispatcher will save the IRQ status before calling here.
- * Now need to go through each IRQ status and find matching
- * irq lookup index.
- */
- spin_lock_irqsave(&intr->status_lock, irq_flags);
- for (reg_idx = 0; reg_idx < ARRAY_SIZE(sde_intr_set); reg_idx++) {
- irq_status = intr->save_irq_status[reg_idx];
-
- /*
- * Each Interrupt register has a range of 32 indexes, and
- * that is static for sde_irq_map.
- */
- start_idx = reg_idx * 32;
- end_idx = start_idx + 32;
-
- /*
- * Search through matching intr status from irq map.
- * start_idx and end_idx defined the search range in
- * the sde_irq_map.
- */
- for (irq_idx = start_idx;
- (irq_idx < end_idx) && irq_status;
- irq_idx++)
- if ((irq_status & sde_irq_map[irq_idx].irq_mask) &&
- (sde_irq_map[irq_idx].reg_idx == reg_idx)) {
- /*
- * Once a match on irq mask, perform a callback
- * to the given cbfunc. cbfunc will take care
- * the interrupt status clearing. If cbfunc is
- * not provided, then the interrupt clearing
- * is here.
- */
- if (cbfunc)
- cbfunc(arg, irq_idx);
- else
- intr->ops.clear_interrupt_status(
- intr, irq_idx);
-
- /*
- * When callback finish, clear the irq_status
- * with the matching mask. Once irq_status
- * is all cleared, the search can be stopped.
- */
- irq_status &= ~sde_irq_map[irq_idx].irq_mask;
- }
- }
- spin_unlock_irqrestore(&intr->status_lock, irq_flags);
-}
-
-static int sde_hw_intr_enable_irq(struct sde_hw_intr *intr, int irq_idx)
-{
- int reg_idx;
- unsigned long irq_flags;
- const struct sde_intr_reg *reg;
- const struct sde_irq_type *irq;
- const char *dbgstr = NULL;
- uint32_t cache_irq_mask;
-
- if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
- pr_err("invalid IRQ index: [%d]\n", irq_idx);
- return -EINVAL;
- }
-
- irq = &sde_irq_map[irq_idx];
- reg_idx = irq->reg_idx;
- reg = &sde_intr_set[reg_idx];
-
- spin_lock_irqsave(&intr->mask_lock, irq_flags);
- cache_irq_mask = intr->cache_irq_mask[reg_idx];
- if (cache_irq_mask & irq->irq_mask) {
- dbgstr = "SDE IRQ already set:";
- } else {
- dbgstr = "SDE IRQ enabled:";
-
- cache_irq_mask |= irq->irq_mask;
- /* Cleaning any pending interrupt */
- SDE_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
- /* Enabling interrupts with the new mask */
- SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
-
- intr->cache_irq_mask[reg_idx] = cache_irq_mask;
- }
- spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
-
- pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
- irq->irq_mask, cache_irq_mask);
-
- return 0;
-}
-
-static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
-{
- int reg_idx;
- unsigned long irq_flags;
- const struct sde_intr_reg *reg;
- const struct sde_irq_type *irq;
- const char *dbgstr = NULL;
- uint32_t cache_irq_mask;
-
- if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
- pr_err("invalid IRQ index: [%d]\n", irq_idx);
- return -EINVAL;
- }
-
- irq = &sde_irq_map[irq_idx];
- reg_idx = irq->reg_idx;
- reg = &sde_intr_set[reg_idx];
-
- spin_lock_irqsave(&intr->mask_lock, irq_flags);
- cache_irq_mask = intr->cache_irq_mask[reg_idx];
- if ((cache_irq_mask & irq->irq_mask) == 0) {
- dbgstr = "SDE IRQ is already cleared:";
- } else {
- dbgstr = "SDE IRQ mask disable:";
-
- cache_irq_mask &= ~irq->irq_mask;
- /* Disable interrupts based on the new mask */
- SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
- /* Cleaning any pending interrupt */
- SDE_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
-
- intr->cache_irq_mask[reg_idx] = cache_irq_mask;
- }
- spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
-
- pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
- irq->irq_mask, cache_irq_mask);
-
- return 0;
-}
-
-static int sde_hw_intr_clear_irqs(struct sde_hw_intr *intr)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
- SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off, 0xffffffff);
-
- return 0;
-}
-
-static int sde_hw_intr_disable_irqs(struct sde_hw_intr *intr)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
- SDE_REG_WRITE(&intr->hw, sde_intr_set[i].en_off, 0x00000000);
-
- return 0;
-}
-
-static int sde_hw_intr_get_valid_interrupts(struct sde_hw_intr *intr,
- uint32_t *mask)
-{
- *mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1
- | IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP;
- return 0;
-}
-
-static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr,
- uint32_t *sources)
-{
- *sources = SDE_REG_READ(&intr->hw, HW_INTR_STATUS);
- return 0;
-}
-
-static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr)
-{
- int i;
- u32 enable_mask;
- unsigned long irq_flags;
-
- spin_lock_irqsave(&intr->status_lock, irq_flags);
- for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++) {
- /* Read interrupt status */
- intr->save_irq_status[i] = SDE_REG_READ(&intr->hw,
- sde_intr_set[i].status_off);
-
- /* Read enable mask */
- enable_mask = SDE_REG_READ(&intr->hw, sde_intr_set[i].en_off);
-
- /* and clear the interrupt */
- if (intr->save_irq_status[i])
- SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off,
- intr->save_irq_status[i]);
-
- /* Finally update IRQ status based on enable mask */
- intr->save_irq_status[i] &= enable_mask;
- }
- spin_unlock_irqrestore(&intr->status_lock, irq_flags);
-}
-
-static void sde_hw_intr_clear_interrupt_status(struct sde_hw_intr *intr,
- int irq_idx)
-{
- int reg_idx;
- unsigned long irq_flags;
-
- spin_lock_irqsave(&intr->mask_lock, irq_flags);
-
- reg_idx = sde_irq_map[irq_idx].reg_idx;
- SDE_REG_WRITE(&intr->hw, sde_intr_set[reg_idx].clr_off,
- sde_irq_map[irq_idx].irq_mask);
-
- spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
-}
-
-
-static void __setup_intr_ops(struct sde_hw_intr_ops *ops)
-{
- ops->set_mask = sde_hw_intr_set_mask;
- ops->irq_idx_lookup = sde_hw_intr_irqidx_lookup;
- ops->enable_irq = sde_hw_intr_enable_irq;
- ops->disable_irq = sde_hw_intr_disable_irq;
- ops->dispatch_irqs = sde_hw_intr_dispatch_irq;
- ops->clear_all_irqs = sde_hw_intr_clear_irqs;
- ops->disable_all_irqs = sde_hw_intr_disable_irqs;
- ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts;
- ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources;
- ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses;
- ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status;
-}
-
-static struct sde_mdss_base_cfg *__intr_offset(struct sde_mdss_cfg *m,
- void __iomem *addr, struct sde_hw_blk_reg_map *hw)
-{
- if (m->mdp_count == 0)
- return NULL;
-
- hw->base_off = addr;
- hw->blk_off = m->mdss[0].base;
- hw->hwversion = m->hwversion;
- return &m->mdss[0];
-}
-
-struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_intr *intr = kzalloc(sizeof(*intr), GFP_KERNEL);
- struct sde_mdss_base_cfg *cfg;
-
- if (!intr)
- return ERR_PTR(-ENOMEM);
-
- cfg = __intr_offset(m, addr, &intr->hw);
- if (!cfg) {
- kfree(intr);
- return ERR_PTR(-EINVAL);
- }
- __setup_intr_ops(&intr->ops);
-
- intr->irq_idx_tbl_size = ARRAY_SIZE(sde_irq_map);
-
- intr->cache_irq_mask = kcalloc(ARRAY_SIZE(sde_intr_set), sizeof(u32),
- GFP_KERNEL);
- if (intr->cache_irq_mask == NULL) {
- kfree(intr);
- return ERR_PTR(-ENOMEM);
- }
-
- intr->save_irq_status = kcalloc(ARRAY_SIZE(sde_intr_set), sizeof(u32),
- GFP_KERNEL);
- if (intr->save_irq_status == NULL) {
- kfree(intr->cache_irq_mask);
- kfree(intr);
- return ERR_PTR(-ENOMEM);
- }
-
- spin_lock_init(&intr->mask_lock);
- spin_lock_init(&intr->status_lock);
-
- return intr;
-}
-
-void sde_hw_intr_destroy(struct sde_hw_intr *intr)
-{
- if (intr) {
- kfree(intr->cache_irq_mask);
- kfree(intr->save_irq_status);
- kfree(intr);
- }
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
deleted file mode 100644
index 0ddb1e78a953..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_INTERRUPTS_H
-#define _SDE_HW_INTERRUPTS_H
-
-#include <linux/types.h>
-
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdp_util.h"
-#include "sde_hw_mdss.h"
-
-#define IRQ_SOURCE_MDP BIT(0)
-#define IRQ_SOURCE_DSI0 BIT(4)
-#define IRQ_SOURCE_DSI1 BIT(5)
-#define IRQ_SOURCE_HDMI BIT(8)
-#define IRQ_SOURCE_EDP BIT(12)
-#define IRQ_SOURCE_MHL BIT(16)
-
-/**
- * sde_intr_type - HW Interrupt Type
- * @SDE_IRQ_TYPE_WB_ROT_COMP: WB rotator done
- * @SDE_IRQ_TYPE_WB_WFD_COMP: WB WFD done
- * @SDE_IRQ_TYPE_PING_PONG_COMP: PingPong done
- * @SDE_IRQ_TYPE_PING_PONG_RD_PTR: PingPong read pointer
- * @SDE_IRQ_TYPE_PING_PONG_WR_PTR: PingPong write pointer
- * @SDE_IRQ_TYPE_PING_PONG_AUTO_REF: PingPong auto refresh
- * @SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK: PingPong Tear check
- * @SDE_IRQ_TYPE_PING_PONG_TE_CHECK: PingPong TE detection
- * @SDE_IRQ_TYPE_INTF_UNDER_RUN: INTF underrun
- * @SDE_IRQ_TYPE_INTF_VSYNC: INTF VSYNC
- * @SDE_IRQ_TYPE_CWB_OVERFLOW: Concurrent WB overflow
- * @SDE_IRQ_TYPE_HIST_VIG_DONE: VIG Histogram done
- * @SDE_IRQ_TYPE_HIST_VIG_RSTSEQ: VIG Histogram reset
- * @SDE_IRQ_TYPE_HIST_DSPP_DONE: DSPP Histogram done
- * @SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ: DSPP Histogram reset
- * @SDE_IRQ_TYPE_WD_TIMER: Watchdog timer
- * @SDE_IRQ_TYPE_SFI_VIDEO_IN: Video static frame INTR into static
- * @SDE_IRQ_TYPE_SFI_VIDEO_OUT: Video static frame INTR out-of static
- * @SDE_IRQ_TYPE_SFI_CMD_0_IN: DSI CMD0 static frame INTR into static
- * @SDE_IRQ_TYPE_SFI_CMD_0_OUT: DSI CMD0 static frame INTR out-of static
- * @SDE_IRQ_TYPE_SFI_CMD_1_IN: DSI CMD1 static frame INTR into static
- * @SDE_IRQ_TYPE_SFI_CMD_1_OUT: DSI CMD1 static frame INTR out-of static
- * @SDE_IRQ_TYPE_SFI_CMD_2_IN: DSI CMD2 static frame INTR into static
- * @SDE_IRQ_TYPE_SFI_CMD_2_OUT: DSI CMD2 static frame INTR out-of static
- * @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt
- * @SDE_IRQ_TYPE_RESERVED: Reserved for expansion
- */
-enum sde_intr_type {
- SDE_IRQ_TYPE_WB_ROT_COMP,
- SDE_IRQ_TYPE_WB_WFD_COMP,
- SDE_IRQ_TYPE_PING_PONG_COMP,
- SDE_IRQ_TYPE_PING_PONG_RD_PTR,
- SDE_IRQ_TYPE_PING_PONG_WR_PTR,
- SDE_IRQ_TYPE_PING_PONG_AUTO_REF,
- SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK,
- SDE_IRQ_TYPE_PING_PONG_TE_CHECK,
- SDE_IRQ_TYPE_INTF_UNDER_RUN,
- SDE_IRQ_TYPE_INTF_VSYNC,
- SDE_IRQ_TYPE_CWB_OVERFLOW,
- SDE_IRQ_TYPE_HIST_VIG_DONE,
- SDE_IRQ_TYPE_HIST_VIG_RSTSEQ,
- SDE_IRQ_TYPE_HIST_DSPP_DONE,
- SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ,
- SDE_IRQ_TYPE_WD_TIMER,
- SDE_IRQ_TYPE_SFI_VIDEO_IN,
- SDE_IRQ_TYPE_SFI_VIDEO_OUT,
- SDE_IRQ_TYPE_SFI_CMD_0_IN,
- SDE_IRQ_TYPE_SFI_CMD_0_OUT,
- SDE_IRQ_TYPE_SFI_CMD_1_IN,
- SDE_IRQ_TYPE_SFI_CMD_1_OUT,
- SDE_IRQ_TYPE_SFI_CMD_2_IN,
- SDE_IRQ_TYPE_SFI_CMD_2_OUT,
- SDE_IRQ_TYPE_PROG_LINE,
- SDE_IRQ_TYPE_RESERVED,
-};
-
-struct sde_hw_intr;
-
-/**
- * Interrupt operations.
- */
-struct sde_hw_intr_ops {
- /**
- * set_mask - Programs the given interrupt register with the
- * given interrupt mask. Register value will get overwritten.
- * @intr: HW interrupt handle
- * @reg_off: MDSS HW register offset
- * @irqmask: IRQ mask value
- */
- void (*set_mask)(
- struct sde_hw_intr *intr,
- uint32_t reg,
- uint32_t irqmask);
-
- /**
- * irq_idx_lookup - Lookup IRQ index on the HW interrupt type
- * Used for all irq related ops
- * @intr_type: Interrupt type defined in sde_intr_type
- * @instance_idx: HW interrupt block instance
- * @return: irq_idx or -EINVAL for lookup fail
- */
- int (*irq_idx_lookup)(
- enum sde_intr_type intr_type,
- u32 instance_idx);
-
- /**
- * enable_irq - Enable IRQ based on lookup IRQ index
- * @intr: HW interrupt handle
- * @irq_idx: Lookup irq index return from irq_idx_lookup
- * @return: 0 for success, otherwise failure
- */
- int (*enable_irq)(
- struct sde_hw_intr *intr,
- int irq_idx);
-
- /**
- * disable_irq - Disable IRQ based on lookup IRQ index
- * @intr: HW interrupt handle
- * @irq_idx: Lookup irq index return from irq_idx_lookup
- * @return: 0 for success, otherwise failure
- */
- int (*disable_irq)(
- struct sde_hw_intr *intr,
- int irq_idx);
-
- /**
- * clear_all_irqs - Clears all the interrupts (i.e. acknowledges
- * any asserted IRQs). Useful during reset.
- * @intr: HW interrupt handle
- * @return: 0 for success, otherwise failure
- */
- int (*clear_all_irqs)(
- struct sde_hw_intr *intr);
-
- /**
- * disable_all_irqs - Disables all the interrupts. Useful during reset.
- * @intr: HW interrupt handle
- * @return: 0 for success, otherwise failure
- */
- int (*disable_all_irqs)(
- struct sde_hw_intr *intr);
-
- /**
- * dispatch_irqs - IRQ dispatcher will call the given callback
- * function when a matching interrupt status bit is
- * found in the irq mapping table.
- * @intr: HW interrupt handle
- * @cbfunc: Callback function pointer
- * @arg: Argument to pass back during callback
- */
- void (*dispatch_irqs)(
- struct sde_hw_intr *intr,
- void (*cbfunc)(void *arg, int irq_idx),
- void *arg);
-
- /**
- * get_interrupt_statuses - Gets and store value from all interrupt
- * status registers that are currently fired.
- * @intr: HW interrupt handle
- */
- void (*get_interrupt_statuses)(
- struct sde_hw_intr *intr);
-
- /**
- * clear_interrupt_status - Clears HW interrupt status based on given
- * lookup IRQ index.
- * @intr: HW interrupt handle
- * @irq_idx: Lookup irq index return from irq_idx_lookup
- */
- void (*clear_interrupt_status)(
- struct sde_hw_intr *intr,
- int irq_idx);
-
- /**
- * get_valid_interrupts - Gets a mask of all valid interrupt sources
- * within SDE. These are actually status bits
- * within interrupt registers that specify the
- * source of the interrupt in IRQs. For example,
- * valid interrupt sources can be MDP, DSI,
- * HDMI etc.
- * @intr: HW interrupt handle
- * @mask: Returning the interrupt source MASK
- * @return: 0 for success, otherwise failure
- */
- int (*get_valid_interrupts)(
- struct sde_hw_intr *intr,
- uint32_t *mask);
-
- /**
- * get_interrupt_sources - Gets the bitmask of the SDE interrupt
- * source that are currently fired.
- * @intr: HW interrupt handle
- * @sources: Returning the SDE interrupt source status bit mask
- * @return: 0 for success, otherwise failure
- */
- int (*get_interrupt_sources)(
- struct sde_hw_intr *intr,
- uint32_t *sources);
-};
-
-/**
- * struct sde_hw_intr: hw interrupts handling data structure
- * @hw: virtual address mapping
- * @ops: function pointer mapping for IRQ handling
- * @cache_irq_mask: array of IRQ enable masks reg storage created during init
- * @save_irq_status: array of IRQ status reg storage created during init
- * @irq_idx_tbl_size: total number of irq_idx mapped in the hw_interrupts
- * @mask_lock: spinlock for accessing IRQ mask
- * @status_lock: spinlock for accessing IRQ status
- */
-struct sde_hw_intr {
- struct sde_hw_blk_reg_map hw;
- struct sde_hw_intr_ops ops;
- u32 *cache_irq_mask;
- u32 *save_irq_status;
- u32 irq_idx_tbl_size;
- spinlock_t mask_lock;
- spinlock_t status_lock;
-};
-
-/**
- * sde_hw_intr_init(): Initializes the interrupts hw object
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-/**
- * sde_hw_intr_destroy(): Cleanup interrutps hw object
- * @intr: pointer to interrupts hw object
- */
-void sde_hw_intr_destroy(struct sde_hw_intr *intr);
-#endif
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.c b/drivers/gpu/drm/msm/sde/sde_hw_intf.c
deleted file mode 100644
index 8dd306720e90..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_intf.h"
-#include "sde_hw_mdp_top.h"
-
-#define INTF_TIMING_ENGINE_EN 0x000
-#define INTF_CONFIG 0x004
-#define INTF_HSYNC_CTL 0x008
-#define INTF_VSYNC_PERIOD_F0 0x00C
-#define INTF_VSYNC_PERIOD_F1 0x010
-#define INTF_VSYNC_PULSE_WIDTH_F0 0x014
-#define INTF_VSYNC_PULSE_WIDTH_F1 0x018
-#define INTF_DISPLAY_V_START_F0 0x01C
-#define INTF_DISPLAY_V_START_F1 0x020
-#define INTF_DISPLAY_V_END_F0 0x024
-#define INTF_DISPLAY_V_END_F1 0x028
-#define INTF_ACTIVE_V_START_F0 0x02C
-#define INTF_ACTIVE_V_START_F1 0x030
-#define INTF_ACTIVE_V_END_F0 0x034
-#define INTF_ACTIVE_V_END_F1 0x038
-#define INTF_DISPLAY_HCTL 0x03C
-#define INTF_ACTIVE_HCTL 0x040
-#define INTF_BORDER_COLOR 0x044
-#define INTF_UNDERFLOW_COLOR 0x048
-#define INTF_HSYNC_SKEW 0x04C
-#define INTF_POLARITY_CTL 0x050
-#define INTF_TEST_CTL 0x054
-#define INTF_TP_COLOR0 0x058
-#define INTF_TP_COLOR1 0x05C
-#define INTF_FRAME_LINE_COUNT_EN 0x0A8
-#define INTF_FRAME_COUNT 0x0AC
-#define INTF_LINE_COUNT 0x0B0
-
-#define INTF_DEFLICKER_CONFIG 0x0F0
-#define INTF_DEFLICKER_STRNG_COEFF 0x0F4
-#define INTF_DEFLICKER_WEAK_COEFF 0x0F8
-
-#define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084
-#define INTF_PANEL_FORMAT 0x090
-#define INTF_TPG_ENABLE 0x100
-#define INTF_TPG_MAIN_CONTROL 0x104
-#define INTF_TPG_VIDEO_CONFIG 0x108
-#define INTF_TPG_COMPONENT_LIMITS 0x10C
-#define INTF_TPG_RECTANGLE 0x110
-#define INTF_TPG_INITIAL_VALUE 0x114
-#define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118
-#define INTF_TPG_RGB_MAPPING 0x11C
-#define INTF_PROG_FETCH_START 0x170
-
-#define INTF_FRAME_LINE_COUNT_EN 0x0A8
-#define INTF_FRAME_COUNT 0x0AC
-#define INTF_LINE_COUNT 0x0B0
-
-static struct sde_intf_cfg *_intf_offset(enum sde_intf intf,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->intf_count; i++) {
- if ((intf == m->intf[i].id) &&
- (m->intf[i].type != INTF_NONE)) {
- b->base_off = addr;
- b->blk_off = m->intf[i].base;
- b->hwversion = m->hwversion;
- return &m->intf[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-static void sde_hw_intf_setup_timing_engine(struct sde_hw_intf *ctx,
- struct intf_timing_params *p,
- struct sde_mdp_format_params *fmt)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 hsync_period, vsync_period;
- u32 display_v_start, display_v_end;
- u32 hsync_start_x, hsync_end_x;
- u32 active_h_start, active_h_end;
- u32 active_v_start, active_v_end;
- u32 active_hctl, display_hctl, hsync_ctl;
- u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity;
- u32 panel_format;
- u32 intf_cfg;
-
- /* read interface_cfg */
- intf_cfg = SDE_REG_READ(c, INTF_CONFIG);
- hsync_period = p->hsync_pulse_width + p->h_back_porch + p->width +
- p->h_front_porch;
- vsync_period = p->vsync_pulse_width + p->v_back_porch + p->height +
- p->v_front_porch;
-
- display_v_start = ((p->vsync_pulse_width + p->v_back_porch) *
- hsync_period) + p->hsync_skew;
- display_v_end = ((vsync_period - p->v_front_porch) * hsync_period) +
- p->hsync_skew - 1;
-
- if (ctx->cap->type == INTF_EDP) {
- display_v_start += p->hsync_pulse_width + p->h_back_porch;
- display_v_end -= p->h_front_porch;
- }
-
- hsync_start_x = p->h_back_porch + p->hsync_pulse_width;
- hsync_end_x = hsync_period - p->h_front_porch - 1;
-
- if (p->width != p->xres) {
- active_h_start = hsync_start_x;
- active_h_end = active_h_start + p->xres - 1;
- } else {
- active_h_start = 0;
- active_h_end = 0;
- }
-
- if (p->height != p->yres) {
- active_v_start = display_v_start;
- active_v_end = active_v_start + (p->yres * hsync_period) - 1;
- } else {
- active_v_start = 0;
- active_v_end = 0;
- }
-
- if (active_h_end) {
- active_hctl = (active_h_end << 16) | active_h_start;
- intf_cfg |= BIT(29); /* ACTIVE_H_ENABLE */
- } else {
- active_hctl = 0;
- }
-
- if (active_v_end)
- intf_cfg |= BIT(30); /* ACTIVE_V_ENABLE */
-
- hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width;
- display_hctl = (hsync_end_x << 16) | hsync_start_x;
-
- den_polarity = 0;
- if (ctx->cap->type == INTF_HDMI) {
- hsync_polarity = p->yres >= 720 ? 0 : 1;
- vsync_polarity = p->yres >= 720 ? 0 : 1;
- } else {
- hsync_polarity = 0;
- vsync_polarity = 0;
- }
- polarity_ctl = (den_polarity << 2) | /* DEN Polarity */
- (vsync_polarity << 1) | /* VSYNC Polarity */
- (hsync_polarity << 0); /* HSYNC Polarity */
-
- if (!fmt->is_yuv)
- panel_format = (fmt->bits[C0_G_Y] |
- (fmt->bits[C1_B_Cb] << 2) |
- (fmt->bits[C2_R_Cr] << 4) |
- (0x21 << 8));
- else
- /* Interface treats all the pixel data in RGB888 format */
- panel_format = (COLOR_8BIT |
- (COLOR_8BIT << 2) |
- (COLOR_8BIT << 4) |
- (0x21 << 8));
-
- SDE_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl);
- SDE_REG_WRITE(c, INTF_VSYNC_PERIOD_F0,
- vsync_period * hsync_period);
- SDE_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0,
- p->vsync_pulse_width * hsync_period);
- SDE_REG_WRITE(c, INTF_DISPLAY_HCTL, display_hctl);
- SDE_REG_WRITE(c, INTF_DISPLAY_V_START_F0,
- display_v_start);
- SDE_REG_WRITE(c, INTF_DISPLAY_V_END_F0,
- display_v_end);
- SDE_REG_WRITE(c, INTF_ACTIVE_HCTL, active_hctl);
- SDE_REG_WRITE(c, INTF_ACTIVE_V_START_F0,
- active_v_start);
- SDE_REG_WRITE(c, INTF_ACTIVE_V_END_F0,
- active_v_end);
-
- SDE_REG_WRITE(c, INTF_BORDER_COLOR, p->border_clr);
- SDE_REG_WRITE(c, INTF_UNDERFLOW_COLOR,
- p->underflow_clr);
- SDE_REG_WRITE(c, INTF_HSYNC_SKEW, p->hsync_skew);
- SDE_REG_WRITE(c, INTF_POLARITY_CTL, polarity_ctl);
- SDE_REG_WRITE(c, INTF_FRAME_LINE_COUNT_EN, 0x3);
- SDE_REG_WRITE(c, INTF_CONFIG, intf_cfg);
- SDE_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format);
-}
-
-static void sde_hw_intf_enable_timing_engine(
- struct sde_hw_intf *intf,
- u8 enable)
-{
- struct sde_hw_blk_reg_map *c = &intf->hw;
- u32 intf_sel;
-
- /* Display interface select */
- if (enable) {
- /* top block */
- struct sde_hw_mdp *mdp = sde_hw_mdptop_init(MDP_TOP,
- c->base_off,
- intf->mdss);
- struct sde_hw_blk_reg_map *top = &mdp->hw;
-
- intf_sel = SDE_REG_READ(top, DISP_INTF_SEL);
-
- intf_sel |= (intf->cap->type << ((intf->idx - INTF_0) * 8));
- SDE_REG_WRITE(top, DISP_INTF_SEL, intf_sel);
- }
-
- SDE_REG_WRITE(c, INTF_TIMING_ENGINE_EN,
- enable & 0x1);
-}
-
-static void sde_hw_intf_setup_prg_fetch(
- struct sde_hw_intf *intf,
- struct intf_prog_fetch *fetch)
-{
- struct sde_hw_blk_reg_map *c = &intf->hw;
- int fetch_enable;
-
- /*
- * Fetch should always be outside the active lines. If the fetching
- * is programmed within active region, hardware behavior is unknown.
- */
-
- fetch_enable = SDE_REG_READ(c, INTF_CONFIG);
- if (fetch->enable) {
- fetch_enable |= BIT(31);
- SDE_REG_WRITE(c, INTF_PROG_FETCH_START,
- fetch->fetch_start);
- } else {
- fetch_enable &= ~BIT(31);
- }
-
- SDE_REG_WRITE(c, INTF_CONFIG, fetch_enable);
-}
-
-static void sde_hw_intf_get_timing_config(
- struct sde_hw_intf *intf,
- struct intf_timing_params *cfg)
-{
- struct sde_hw_blk_reg_map *c = &intf->hw;
- u32 vsync_period;
- u32 display_v_start, display_v_end;
- u32 hsync_start_x, hsync_end_x;
- u32 active_v_start, active_v_end;
- u32 active_hctl, display_hctl, hsync_ctl;
- u32 polarity_ctl;
- u32 pulse_width;
- u32 htotal, vtotal;
- u32 intf_cfg;
-
- hsync_ctl = SDE_REG_READ(c, INTF_HSYNC_CTL);
- vsync_period = SDE_REG_READ(c, INTF_VSYNC_PERIOD_F0);
- pulse_width = SDE_REG_READ(c, INTF_VSYNC_PULSE_WIDTH_F0);
- display_hctl = SDE_REG_READ(c, INTF_DISPLAY_HCTL);
- display_v_start = SDE_REG_READ(c, INTF_DISPLAY_V_START_F0);
- display_v_end = SDE_REG_READ(c, INTF_DISPLAY_V_END_F0);
- active_hctl = SDE_REG_READ(c, INTF_ACTIVE_HCTL);
- active_v_start = SDE_REG_READ(c, INTF_ACTIVE_V_START_F0);
- active_v_end = SDE_REG_READ(c, INTF_ACTIVE_V_END_F0);
- intf_cfg = SDE_REG_READ(c, INTF_CONFIG);
- cfg->border_clr = SDE_REG_READ(c, INTF_BORDER_COLOR);
- cfg->underflow_clr = SDE_REG_READ(c, INTF_UNDERFLOW_COLOR);
- cfg->hsync_skew = SDE_REG_READ(c, INTF_HSYNC_SKEW);
- polarity_ctl = SDE_REG_READ(c, INTF_POLARITY_CTL);
-
- hsync_start_x = (display_hctl & 0xffff);
- hsync_end_x = (display_hctl & 0xffff0000) >> 16;
- cfg->hsync_pulse_width = (hsync_ctl & 0xffff);
- htotal = (hsync_ctl & 0xffff0000) >> 16;
-
- if (htotal != 0) {
- vtotal = vsync_period / htotal;
- cfg->vsync_pulse_width = pulse_width/htotal;
-
- /* porches */
- cfg->h_front_porch = htotal - hsync_end_x - 1;
- cfg->h_back_porch = hsync_start_x - cfg->hsync_pulse_width;
- cfg->v_front_porch = vsync_period - display_v_end;
- cfg->v_back_porch = display_v_start - cfg->vsync_pulse_width;
-
- /* active resolution */
- cfg->width = htotal - cfg->hsync_pulse_width -
- cfg->h_back_porch -
- cfg->h_front_porch;
- cfg->height = vtotal - cfg->vsync_pulse_width -
- cfg->v_back_porch - cfg->v_front_porch;
-
- /* display panel resolution */
- if (intf_cfg & BIT(29))
- cfg->xres = ((active_hctl & 0xffff0000) >> 16) -
- (active_hctl & 0xffff) + 1;
- else
- cfg->xres = cfg->width;
-
- if (intf_cfg & BIT(30))
- cfg->yres = (active_v_end - active_v_start + 1
- )/htotal;
- else
- cfg->yres = cfg->height;
- } else {
- cfg->vsync_pulse_width = 0;
- cfg->h_front_porch = 0;
- cfg->h_back_porch = 0;
- cfg->v_front_porch = 0;
- cfg->v_back_porch = 0;
- cfg->width = 0;
- cfg->height = 0;
- }
-
- cfg->hsync_polarity = polarity_ctl & 1;
- cfg->vsync_polarity = (polarity_ctl & 2) >> 1;
-}
-
-static void sde_hw_intf_get_status(
- struct sde_hw_intf *intf,
- struct intf_status *s)
-{
- struct sde_hw_blk_reg_map *c = &intf->hw;
-
- s->is_en = SDE_REG_READ(c, INTF_TIMING_ENGINE_EN);
- if (s->is_en) {
- s->frame_count = SDE_REG_READ(c, INTF_FRAME_COUNT);
- s->line_count = SDE_REG_READ(c, INTF_LINE_COUNT);
- } else {
- s->line_count = 0;
- s->frame_count = 0;
- }
-}
-
-static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
- unsigned long cap)
-{
- ops->setup_timing_gen = sde_hw_intf_setup_timing_engine;
- ops->setup_prg_fetch = sde_hw_intf_setup_prg_fetch;
- ops->get_timing_gen = sde_hw_intf_get_timing_config;
- ops->get_status = sde_hw_intf_get_status;
- ops->enable_timing = sde_hw_intf_enable_timing_engine;
-}
-
-struct sde_hw_intf *sde_hw_intf_init(enum sde_intf idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_intf *c;
- struct sde_intf_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _intf_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- pr_err("Error Panic\n");
- return ERR_PTR(-EINVAL);
- }
-
- /*
- * Assign ops
- */
- c->idx = idx;
- c->cap = cfg;
- c->mdss = m;
- _setup_intf_ops(&c->ops, c->cap->features);
-
- /*
- * Perform any default initialization for the intf
- */
- return c;
-}
-
-void sde_hw_intf_deinit(struct sde_hw_intf *intf)
-{
- kfree(intf);
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.h b/drivers/gpu/drm/msm/sde/sde_hw_intf.h
deleted file mode 100644
index 2de57868901a..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_INTF_H
-#define _SDE_HW_INTF_H
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-
-struct sde_hw_intf;
-
-/* intf timing settings */
-struct intf_timing_params {
- u32 width; /* active width */
- u32 height; /* active height */
- u32 xres; /* Display panel width */
- u32 yres; /* Display panel height */
-
- u32 h_back_porch;
- u32 h_front_porch;
- u32 v_back_porch;
- u32 v_front_porch;
- u32 hsync_pulse_width;
- u32 vsync_pulse_width;
- u32 hsync_polarity;
- u32 vsync_polarity;
- u32 border_clr;
- u32 underflow_clr;
- u32 hsync_skew;
-};
-
-struct intf_prog_fetch {
- u8 enable;
- /* vsync counter for the front porch pixel line */
- u32 fetch_start;
-};
-
-struct intf_status {
- u8 is_en; /* interface timing engine is enabled or not */
- u32 frame_count; /* frame count since timing engine enabled */
- u32 line_count; /* current line count including blanking */
-};
-
-/**
- * struct sde_hw_intf_ops : Interface to the interface Hw driver functions
- * Assumption is these functions will be called after clocks are enabled
- * @ setup_timing_gen : programs the timing engine
- * @ setup_prog_fetch : enables/disables the programmable fetch logic
- * @ enable_timing: enable/disable timing engine
- * @ get_timing_gen: get timing generator programmed configuration
- * @ get_status: returns if timing engine is enabled or not
- */
-struct sde_hw_intf_ops {
- void (*setup_timing_gen)(struct sde_hw_intf *intf,
- struct intf_timing_params *p,
- struct sde_mdp_format_params *fmt);
-
- void (*setup_prg_fetch)(struct sde_hw_intf *intf,
- struct intf_prog_fetch *fetch);
-
- void (*enable_timing)(struct sde_hw_intf *intf,
- u8 enable);
-
- void (*get_timing_gen)(struct sde_hw_intf *intf,
- struct intf_timing_params *cfg);
-
- void (*get_status)(struct sde_hw_intf *intf,
- struct intf_status *status);
-};
-
-struct sde_hw_intf {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* intf */
- enum sde_intf idx;
- const struct sde_intf_cfg *cap;
- const struct sde_mdss_cfg *mdss;
-
- /* ops */
- struct sde_hw_intf_ops ops;
-};
-
-/**
- * sde_hw_intf_init(): Initializes the intf driver for the passed
- * interface idx.
- * @idx: interface index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_intf *sde_hw_intf_init(enum sde_intf idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-void sde_hw_intf_deinit(struct sde_hw_intf *intf);
-
-#endif /*_SDE_HW_INTF_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_lm.c b/drivers/gpu/drm/msm/sde/sde_hw_lm.c
deleted file mode 100644
index 56ebe8fa05b5..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_lm.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_catalog.h"
-#include "sde_hwio.h"
-#include "sde_hw_lm.h"
-#include "sde_hw_mdss.h"
-
-#define LM_OP_MODE 0x00
-#define LM_OUT_SIZE 0x04
-#define LM_BORDER_COLOR_0 0x08
-#define LM_BORDER_COLOR_1 0x010
-
-/* These register are offset to mixer base + stage base */
-#define LM_BLEND0_OP 0x00
-#define LM_BLEND0_FG_ALPHA 0x04
-#define LM_BLEND0_BG_ALPHA 0x08
-
-static struct sde_lm_cfg *_lm_offset(enum sde_lm mixer,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->mixer_count; i++) {
- if (mixer == m->mixer[i].id) {
- b->base_off = addr;
- b->blk_off = m->mixer[i].base;
- b->hwversion = m->hwversion;
- return &m->mixer[i];
- }
- }
-
- return ERR_PTR(-ENOMEM);
-}
-
-/**
- * _stage_offset(): returns the relative offset of the blend registers
- * for the stage to be setup
- * @c: mixer ctx contains the mixer to be programmed
- * @stage: stage index to setup
- */
-static inline int _stage_offset(struct sde_hw_mixer *ctx, enum sde_stage stage)
-{
- const struct sde_lm_sub_blks *sblk = ctx->cap->sblk;
-
- if (WARN_ON(stage == SDE_STAGE_BASE))
- return -EINVAL;
-
- if ((stage - SDE_STAGE_0) <= sblk->maxblendstages)
- return sblk->blendstage_base[stage - 1];
- else
- return -EINVAL;
-}
-
-static void sde_hw_lm_setup_out(struct sde_hw_mixer *ctx,
- struct sde_hw_mixer_cfg *mixer)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 outsize;
- u32 opmode;
-
- opmode = SDE_REG_READ(c, LM_OP_MODE);
-
- outsize = mixer->out_height << 16 | mixer->out_width;
- SDE_REG_WRITE(c, LM_OUT_SIZE, outsize);
-
- /* SPLIT_LEFT_RIGHT */
- opmode = (opmode & ~(1 << 31)) | ((mixer->right_mixer) ? (1 << 31) : 0);
- SDE_REG_WRITE(c, LM_OP_MODE, opmode);
-}
-
-static void sde_hw_lm_setup_border_color(struct sde_hw_mixer *ctx,
- struct sde_mdss_color *color,
- u8 border_en)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
-
- if (border_en) {
- SDE_REG_WRITE(c, LM_BORDER_COLOR_0,
- (color->color_0 & 0xFFF) |
- ((color->color_1 & 0xFFF) << 0x10));
- SDE_REG_WRITE(c, LM_BORDER_COLOR_1,
- (color->color_2 & 0xFFF) |
- ((color->color_3 & 0xFFF) << 0x10));
- }
-}
-
-static void sde_hw_lm_setup_blendcfg(struct sde_hw_mixer *ctx,
- int stage,
- struct sde_hw_blend_cfg *blend)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 blend_op;
- struct sde_hw_alpha_cfg *fg, *bg;
- int stage_off;
-
- stage_off = _stage_offset(ctx, stage);
- if (WARN_ON(stage_off < 0))
- return;
-
- fg = &(blend->fg);
- bg = &(blend->bg);
-
- /* fg */
- blend_op = (fg->alpha_sel & 3);
- blend_op |= (fg->inv_alpha_sel & 1) << 2;
- blend_op |= (fg->mod_alpha & 1) << 3;
- blend_op |= (fg->inv_mode_alpha & 1) << 4;
-
- /* bg */
- blend_op |= (bg->alpha_sel & 3) << 8;
- blend_op |= (bg->inv_alpha_sel & 1) << 2;
- blend_op |= (bg->mod_alpha & 1) << 3;
- blend_op |= (bg->inv_mode_alpha & 1) << 4;
-
- SDE_REG_WRITE(c, LM_BLEND0_FG_ALPHA + stage_off,
- fg->const_alpha);
- SDE_REG_WRITE(c, LM_BLEND0_BG_ALPHA + stage_off,
- bg->const_alpha);
- SDE_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
-}
-
-static void sde_hw_lm_setup_color3(struct sde_hw_mixer *ctx,
- struct sde_hw_color3_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- int maxblendstages = ctx->cap->sblk->maxblendstages;
- int i;
- int op_mode;
-
- /* read the existing op_mode configuration */
- op_mode = SDE_REG_READ(c, LM_OP_MODE);
-
- for (i = 0; i < maxblendstages; i++)
- op_mode |= ((cfg->keep_fg[i] & 0x1) << i);
-
- SDE_REG_WRITE(c, LM_OP_MODE, op_mode);
-}
-
-static void sde_hw_lm_gammacorrection(struct sde_hw_mixer *mixer,
- void *cfg)
-{
-}
-
-static void _setup_mixer_ops(struct sde_hw_lm_ops *ops,
- unsigned long cap)
-{
- ops->setup_mixer_out = sde_hw_lm_setup_out;
- ops->setup_blend_config = sde_hw_lm_setup_blendcfg;
- ops->setup_alpha_out = sde_hw_lm_setup_color3;
- ops->setup_border_color = sde_hw_lm_setup_border_color;
- ops->setup_gammcorrection = sde_hw_lm_gammacorrection;
-};
-
-struct sde_hw_mixer *sde_hw_lm_init(enum sde_lm idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_mixer *c;
- struct sde_lm_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _lm_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- /* Assign ops */
- c->idx = idx;
- c->cap = cfg;
- _setup_mixer_ops(&c->ops, c->cap->features);
-
- /*
- * Perform any default initialization for the sspp blocks
- */
- return c;
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_lm.h b/drivers/gpu/drm/msm/sde/sde_hw_lm.h
deleted file mode 100644
index b48e8e1b8e94..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_lm.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_LM_H
-#define _SDE_HW_LM_H
-
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-
-struct sde_hw_mixer;
-
-struct sde_hw_mixer_cfg {
- u32 out_width;
- u32 out_height;
- bool right_mixer;
- int flags;
-};
-
-struct sde_hw_color3_cfg {
- u8 keep_fg[SDE_STAGE_MAX];
-};
-
-/**
- *
- * struct sde_hw_lm_ops : Interface to the mixer Hw driver functions
- * Assumption is these functions will be called after clocks are enabled
- */
-struct sde_hw_lm_ops {
- /*
- * Sets up mixer output width and height
- * and border color if enabled
- */
- void (*setup_mixer_out)(struct sde_hw_mixer *ctx,
- struct sde_hw_mixer_cfg *cfg);
-
- /*
- * Alpha blending configuration
- * for the specified stage
- */
- void (*setup_blend_config)(struct sde_hw_mixer *ctx,
- int stage,
- struct sde_hw_blend_cfg *blend);
-
- /*
- * Alpha color component selection from either fg or bg
- */
- void (*setup_alpha_out)(struct sde_hw_mixer *ctx,
- struct sde_hw_color3_cfg *cfg);
-
- /**
- * setup_border_color : enable/disable border color
- */
- void (*setup_border_color)(struct sde_hw_mixer *ctx,
- struct sde_mdss_color *color,
- u8 border_en);
-
- void (*setup_gammcorrection)(struct sde_hw_mixer *mixer,
- void *cfg);
-
-};
-
-struct sde_hw_mixer {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* lm */
- enum sde_lm idx;
- const struct sde_lm_cfg *cap;
- const struct sde_mdp_cfg *mdp;
- const struct sde_ctl_cfg *ctl;
-
- /* ops */
- struct sde_hw_lm_ops ops;
-};
-
-/**
- * sde_hw_lm_init(): Initializes the mixer hw driver object.
- * should be called once before accessing every mixer.
- * @idx: mixer index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_mixer *sde_hw_lm_init(enum sde_lm idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-#endif /*_SDE_HW_LM_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.c
deleted file mode 100644
index f7181ab9ed3d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include "sde_hwio.h"
-#include "sde_hw_mdp_ctl.h"
-
-#define CTL_LAYER(lm) \
- (((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
-#define CTL_LAYER_EXT(lm) \
- (0x40 + (((lm) - LM_0) * 0x004))
-#define CTL_TOP 0x014
-#define CTL_FLUSH 0x018
-#define CTL_START 0x01C
-#define CTL_PACK_3D 0x020
-#define CTL_SW_RESET 0x030
-#define CTL_LAYER_EXTN_OFFSET 0x40
-
-#define SDE_REG_RESET_TIMEOUT_COUNT 20
-
-static struct sde_ctl_cfg *_ctl_offset(enum sde_ctl ctl,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->ctl_count; i++) {
- if (ctl == m->ctl[i].id) {
- b->base_off = addr;
- b->blk_off = m->ctl[i].base;
- b->hwversion = m->hwversion;
- return &m->ctl[i];
- }
- }
- return ERR_PTR(-ENOMEM);
-}
-
-static int _mixer_stages(const struct sde_lm_cfg *mixer, int count,
- enum sde_lm lm)
-{
- int i;
- int stages = -EINVAL;
-
- for (i = 0; i < count; i++) {
- if (lm == mixer[i].id) {
- stages = mixer[i].sblk->maxblendstages;
- break;
- }
- }
-
- return stages;
-}
-
-static inline void sde_hw_ctl_force_start(struct sde_hw_ctl *ctx)
-{
- SDE_REG_WRITE(&ctx->hw, CTL_START, 0x1);
-}
-
-static inline void sde_hw_ctl_setup_flush(struct sde_hw_ctl *ctx, u32 flushbits)
-{
- SDE_REG_WRITE(&ctx->hw, CTL_FLUSH, flushbits);
-}
-
-static inline int sde_hw_ctl_get_bitmask_sspp(struct sde_hw_ctl *ctx,
- u32 *flushbits, enum sde_sspp sspp)
-{
- switch (sspp) {
- case SSPP_VIG0:
- *flushbits |= BIT(0);
- break;
- case SSPP_VIG1:
- *flushbits |= BIT(1);
- break;
- case SSPP_VIG2:
- *flushbits |= BIT(2);
- break;
- case SSPP_VIG3:
- *flushbits |= BIT(18);
- break;
- case SSPP_RGB0:
- *flushbits |= BIT(3);
- break;
- case SSPP_RGB1:
- *flushbits |= BIT(4);
- break;
- case SSPP_RGB2:
- *flushbits |= BIT(5);
- break;
- case SSPP_RGB3:
- *flushbits |= BIT(19);
- break;
- case SSPP_DMA0:
- *flushbits |= BIT(11);
- break;
- case SSPP_DMA1:
- *flushbits |= BIT(12);
- break;
- case SSPP_CURSOR0:
- *flushbits |= BIT(22);
- break;
- case SSPP_CURSOR1:
- *flushbits |= BIT(23);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static inline int sde_hw_ctl_get_bitmask_mixer(struct sde_hw_ctl *ctx,
- u32 *flushbits, enum sde_lm lm)
-{
- switch (lm) {
- case LM_0:
- *flushbits |= BIT(6);
- break;
- case LM_1:
- *flushbits |= BIT(7);
- break;
- case LM_2:
- *flushbits |= BIT(8);
- break;
- case LM_3:
- *flushbits |= BIT(9);
- break;
- case LM_4:
- *flushbits |= BIT(10);
- break;
- case LM_5:
- *flushbits |= BIT(20);
- break;
- default:
- return -EINVAL;
- }
- *flushbits |= BIT(17); /* CTL */
- return 0;
-}
-
-static inline int sde_hw_ctl_get_bitmask_dspp(struct sde_hw_ctl *ctx,
- u32 *flushbits, enum sde_dspp dspp)
-{
- switch (dspp) {
- case DSPP_0:
- *flushbits |= BIT(13);
- break;
- case DSPP_1:
- *flushbits |= BIT(14);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static inline int sde_hw_ctl_get_bitmask_intf(struct sde_hw_ctl *ctx,
- u32 *flushbits, enum sde_intf intf)
-{
- switch (intf) {
- case INTF_0:
- *flushbits |= BIT(31);
- break;
- case INTF_1:
- *flushbits |= BIT(30);
- break;
- case INTF_2:
- *flushbits |= BIT(29);
- break;
- case INTF_3:
- *flushbits |= BIT(28);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx,
- u32 *flushbits, enum sde_cdm cdm)
-{
- switch (cdm) {
- case CDM_0:
- *flushbits |= BIT(26);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- int count = SDE_REG_RESET_TIMEOUT_COUNT;
- int reset;
-
- SDE_REG_WRITE(c, CTL_SW_RESET, 0x1);
-
- for (; count > 0; count--) {
- /* insert small delay to avoid spinning the cpu while waiting */
- usleep_range(20, 50);
- reset = SDE_REG_READ(c, CTL_SW_RESET);
- if (reset == 0)
- return 0;
- }
-
- return -EINVAL;
-}
-
-static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
- enum sde_lm lm,
- struct sde_hw_stage_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 mixercfg, mixercfg_ext = 0;
- int i, j;
- u8 stages;
- int pipes_per_stage;
-
- stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
- if (WARN_ON(stages < 0))
- return;
-
- if (test_bit(SDE_MIXER_SOURCESPLIT,
- &ctx->mixer_hw_caps->features))
- pipes_per_stage = PIPES_PER_STAGE;
- else
- pipes_per_stage = 1;
-
- mixercfg = cfg->border_enable << 24; /* BORDER_OUT */
-
- for (i = 0; i <= stages; i++) {
- for (j = 0; j < pipes_per_stage; j++) {
- switch (cfg->stage[i][j]) {
- case SSPP_VIG0:
- mixercfg |= (i + 1) << 0;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
- break;
- case SSPP_VIG1:
- mixercfg |= (i + 1) << 3;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 2;
- break;
- case SSPP_VIG2:
- mixercfg |= (i + 1) << 6;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 4;
- break;
- case SSPP_VIG3:
- mixercfg |= (i + 1) << 26;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 4;
- break;
- case SSPP_RGB0:
- mixercfg |= (i + 1) << 9;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 8;
- break;
- case SSPP_RGB1:
- mixercfg |= (i + 1) << 12;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 10;
- break;
- case SSPP_RGB2:
- mixercfg |= (i + 1) << 15;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 12;
- break;
- case SSPP_RGB3:
- mixercfg |= (i + 1) << 29;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 14;
- break;
- case SSPP_DMA0:
- mixercfg |= (i + 1) << 0;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
- break;
- case SSPP_DMA1:
- mixercfg |= (i + 1) << 0;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
- break;
- case SSPP_CURSOR0:
- mixercfg_ext |= (i + 1) << 20;
- break;
- case SSPP_CURSOR1:
- mixercfg_ext |= (i + 1) << 26;
- break;
- default:
- break;
- }
- }
- }
-
- SDE_REG_WRITE(c, CTL_LAYER(lm), mixercfg);
- SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext);
-}
-
-static void sde_hw_ctl_intf_cfg(struct sde_hw_ctl *ctx,
- struct sde_hw_intf_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 intf_cfg = 0;
-
- intf_cfg |= (cfg->intf & 0xF) << 4;
-
- if (cfg->wb)
- intf_cfg |= (cfg->wb & 0x3) + 2;
-
- if (cfg->mode_3d) {
- intf_cfg |= BIT(19);
- intf_cfg |= (cfg->mode_3d - 1) << 20;
- }
-
- SDE_REG_WRITE(c, CTL_TOP, intf_cfg);
-}
-
-static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
- unsigned long cap)
-{
- ops->setup_flush = sde_hw_ctl_setup_flush;
- ops->setup_start = sde_hw_ctl_force_start;
- ops->setup_intf_cfg = sde_hw_ctl_intf_cfg;
- ops->reset = sde_hw_ctl_reset_control;
- ops->setup_blendstage = sde_hw_ctl_setup_blendstage;
- ops->get_bitmask_sspp = sde_hw_ctl_get_bitmask_sspp;
- ops->get_bitmask_mixer = sde_hw_ctl_get_bitmask_mixer;
- ops->get_bitmask_dspp = sde_hw_ctl_get_bitmask_dspp;
- ops->get_bitmask_intf = sde_hw_ctl_get_bitmask_intf;
- ops->get_bitmask_cdm = sde_hw_ctl_get_bitmask_cdm;
-};
-
-struct sde_hw_ctl *sde_hw_ctl_init(enum sde_ctl idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_ctl *c;
- struct sde_ctl_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _ctl_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- pr_err("Error Panic\n");
- return ERR_PTR(-EINVAL);
- }
-
- c->caps = cfg;
- _setup_ctl_ops(&c->ops, c->caps->features);
- c->idx = idx;
- c->mixer_count = m->mixer_count;
- c->mixer_hw_caps = m->mixer;
-
- return c;
-}
-
-void sde_hw_ctl_destroy(struct sde_hw_ctl *ctx)
-{
- kfree(ctx);
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h
deleted file mode 100644
index e914abd69906..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_MDP_CTL_H
-#define _SDE_HW_MDP_CTL_H
-
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-#include "sde_hw_catalog.h"
-
-struct sde_hw_ctl;
-/**
- * struct sde_hw_stage_cfg - blending stage cfg
- * @stage
- * @border_enable
- */
-struct sde_hw_stage_cfg {
- enum sde_sspp stage[SDE_STAGE_MAX][PIPES_PER_STAGE];
- u8 border_enable;
-};
-
-/**
- * struct sde_hw_intf_cfg :Desbribes how the mdp writes data to
- * output interface
- * @intf : Interface id
- * @wb: writeback id
- * @mode_3d: 3d mux configuration
- */
-struct sde_hw_intf_cfg {
- enum sde_intf intf;
- enum sde_wb wb;
- enum sde_3d_blend_mode mode_3d;
-};
-
-/**
- * struct sde_hw_ctl_ops - Interface to the wb Hw driver functions
- * Assumption is these functions will be called after clocks are enabled
- */
-struct sde_hw_ctl_ops {
- /**
- * kickoff hw operation for Sw controlled interfaces
- * DSI cmd mode and WB interface are SW controlled
- * @ctx : ctl path ctx pointer
- */
- void (*setup_start)(struct sde_hw_ctl *ctx);
-
- /**
- * FLUSH the modules for this control path
- * @ctx : ctl path ctx pointer
- * @flushbits : module flushmask
- */
- void (*setup_flush)(struct sde_hw_ctl *ctx,
- u32 flushbits);
-
- /**
- * Setup ctl_path interface config
- * @ctx
- * @cfg : interface config structure pointer
- */
- void (*setup_intf_cfg)(struct sde_hw_ctl *ctx,
- struct sde_hw_intf_cfg *cfg);
-
- int (*reset)(struct sde_hw_ctl *c);
-
- int (*get_bitmask_sspp)(struct sde_hw_ctl *ctx,
- u32 *flushbits,
- enum sde_sspp blk);
-
- int (*get_bitmask_mixer)(struct sde_hw_ctl *ctx,
- u32 *flushbits,
- enum sde_lm blk);
-
- int (*get_bitmask_dspp)(struct sde_hw_ctl *ctx,
- u32 *flushbits,
- enum sde_dspp blk);
-
- int (*get_bitmask_intf)(struct sde_hw_ctl *ctx,
- u32 *flushbits,
- enum sde_intf blk);
-
- int (*get_bitmask_cdm)(struct sde_hw_ctl *ctx,
- u32 *flushbits,
- enum sde_cdm blk);
-
- void (*setup_blendstage)(struct sde_hw_ctl *ctx,
- enum sde_lm lm,
- struct sde_hw_stage_cfg *cfg);
-};
-
-/**
- * struct sde_hw_ctl : CTL PATH driver object
- * @struct sde_hw_blk_reg_map *hw;
- * @idx
- * @ctl_hw_caps
- * @mixer_hw_caps
- * @ops
- */
-struct sde_hw_ctl {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* ctl path */
- int idx;
- const struct sde_ctl_cfg *caps;
- int mixer_count;
- const struct sde_lm_cfg *mixer_hw_caps;
-
- /* ops */
- struct sde_hw_ctl_ops ops;
-};
-
-/**
- * sde_hw_ctl_init(): Initializes the ctl_path hw driver object.
- * should be called before accessing every ctl path registers.
- * @idx: ctl_path index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_ctl *sde_hw_ctl_init(enum sde_ctl idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-/**
- * sde_hw_ctl_destroy(): Destroys ctl driver context
- * should be called to free the context
- */
-void sde_hw_ctl_destroy(struct sde_hw_ctl *ctx);
-
-#endif /*_SDE_HW_MDP_CTL_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_hwio.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_hwio.h
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_hwio.h
+++ /dev/null
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
deleted file mode 100644
index 92c08fff2031..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdp_top.h"
-
-#define SPLIT_DISPLAY_ENABLE 0x2F4
-#define LOWER_PIPE_CTRL 0x2F8
-#define UPPER_PIPE_CTRL 0x3F0
-#define TE_LINE_INTERVAL 0x3F4
-
-static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp,
- struct split_pipe_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
- u32 upper_pipe;
- u32 lower_pipe;
-
- if (cfg->en) {
- upper_pipe = BIT(8);
- lower_pipe = BIT(8);
-
- if (cfg->mode == INTF_MODE_CMD) {
- upper_pipe |= BIT(0);
- lower_pipe |= BIT(0);
- }
-
- SDE_REG_WRITE(c, LOWER_PIPE_CTRL, lower_pipe);
- SDE_REG_WRITE(c, UPPER_PIPE_CTRL, upper_pipe);
- }
-
- SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1);
-}
-
-static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
- unsigned long cap)
-{
- ops->setup_split_pipe = sde_hw_setup_split_pipe_control;
-}
-
-static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp,
- const struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->mdp_count; i++) {
- if (mdp == m->mdp[i].id) {
- b->base_off = addr;
- b->blk_off = m->mdp[i].base;
- b->hwversion = m->hwversion;
- return &m->mdp[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
- void __iomem *addr,
- const struct sde_mdss_cfg *m)
-{
- static struct sde_hw_mdp *c;
- const struct sde_mdp_cfg *cfg;
-
- /* mdp top is singleton */
- if (c) {
- pr_err(" %s returning %pK", __func__, c);
- return c;
- }
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- pr_err(" %s returning %pK", __func__, c);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _top_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- /*
- * Assign ops
- */
- c->idx = idx;
- c->cap = cfg;
- _setup_mdp_ops(&c->ops, c->cap->features);
-
- /*
- * Perform any default initialization for the intf
- */
- return c;
-}
-
-void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp)
-{
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
deleted file mode 100644
index 216a27e93d46..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_MDP_TOP_H
-#define _SDE_HW_MDP_TOP_H
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-
-struct sde_hw_mdp;
-
-/**
- * struct split_pipe_cfg - pipe configuration for dual display panels
- * @en : Enable/disable dual pipe confguration
- * @mode : Panel interface mode
- */
-struct split_pipe_cfg {
- bool en;
- enum sde_intf_mode mode;
-};
-
-/**
- * struct sde_hw_mdp_ops - interface to the MDP TOP Hw driver functions
- * Assumption is these functions will be called after clocks are enabled.
- * @setup_split_pipe : Programs the pipe control registers
- */
-struct sde_hw_mdp_ops {
- void (*setup_split_pipe)(struct sde_hw_mdp *mdp,
- struct split_pipe_cfg *p);
-};
-
-struct sde_hw_mdp {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* intf */
- enum sde_mdp idx;
- const struct sde_mdp_cfg *cap;
-
- /* ops */
- struct sde_hw_mdp_ops ops;
-};
-
-/**
- * sde_hw_intf_init - initializes the intf driver for the passed interface idx
- * @idx: Interface index for which driver object is required
- * @addr: Mapped register io address of MDP
- * @m: Pointer to mdss catalog data
- */
-struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
- void __iomem *addr,
- const struct sde_mdss_cfg *m);
-
-void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp);
-
-#endif /*_SDE_HW_MDP_TOP_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c
deleted file mode 100644
index 6be57b06a7cf..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_mdp_util.h"
-
-void sde_hw_reg_write(void __iomem *base, u32 blk_off, u32 reg_off, u32 val)
-{
- writel_relaxed(val, base + blk_off + reg_off);
-}
-
-u32 sde_hw_reg_read(void __iomem *base, u32 blk_off, u32 reg_off)
-{
- return readl_relaxed(base + blk_off + reg_off);
-}
-
-void sde_hw_csc_setup(struct sde_hw_blk_reg_map *c,
- u32 csc_reg_off,
- struct sde_csc_cfg *data)
-{
- u32 val;
-
- /* Matrix coeff */
- val = (data->csc_mv[0] & 0x1FF) |
- ((data->csc_mv[1] & 0x1FF) << 16);
- SDE_REG_WRITE(c, csc_reg_off, val);
- val = (data->csc_mv[2] & 0x1FF) |
- ((data->csc_mv[3] & 0x1FF) << 16);
- SDE_REG_WRITE(c, csc_reg_off + 0x4, val);
- val = (data->csc_mv[4] & 0x1FF) |
- ((data->csc_mv[5] & 0x1FF) >> 16);
- SDE_REG_WRITE(c, csc_reg_off + 0x8, val);
- val = (data->csc_mv[6] & 0x1FF) |
- ((data->csc_mv[7] & 0x1FF) << 16);
- SDE_REG_WRITE(c, csc_reg_off + 0xc, val);
- val = data->csc_mv[8] & 0x1FF;
- SDE_REG_WRITE(c, csc_reg_off + 0x10, val);
-
- /* Pre clamp */
- val = (data->csc_pre_lv[0] << 8) | data->csc_pre_lv[1];
- SDE_REG_WRITE(c, csc_reg_off + 0x14, val);
- val = (data->csc_pre_lv[2] << 8) | data->csc_pre_lv[3];
- SDE_REG_WRITE(c, csc_reg_off + 0x18, val);
- val = (data->csc_pre_lv[4] << 8) | data->csc_pre_lv[5];
- SDE_REG_WRITE(c, csc_reg_off + 0x1c, val);
-
- /* Post clamp */
- val = (data->csc_post_lv[0] << 8) | data->csc_post_lv[1];
- SDE_REG_WRITE(c, csc_reg_off + 0x20, val);
- val = (data->csc_post_lv[2] << 8) | data->csc_post_lv[3];
- SDE_REG_WRITE(c, csc_reg_off + 0x24, val);
- val = (data->csc_post_lv[4] << 8) | data->csc_post_lv[5];
- SDE_REG_WRITE(c, csc_reg_off + 0x28, val);
-
- /* Pre-Bias */
- SDE_REG_WRITE(c, csc_reg_off + 0x2c, data->csc_pre_bv[0]);
- SDE_REG_WRITE(c, csc_reg_off + 0x30, data->csc_pre_bv[1]);
- SDE_REG_WRITE(c, csc_reg_off + 0x34, data->csc_pre_bv[2]);
-
- /* Post-Bias */
- SDE_REG_WRITE(c, csc_reg_off + 0x38, data->csc_post_bv[0]);
- SDE_REG_WRITE(c, csc_reg_off + 0x3c, data->csc_post_bv[1]);
- SDE_REG_WRITE(c, csc_reg_off + 0x40, data->csc_post_bv[2]);
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.h
deleted file mode 100644
index b57e64eba423..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_MDP_UTIL_H
-#define _SDE_HW_MDP_UTIL_H
-
-#include <linux/io.h>
-#include <linux/slab.h>
-#include "sde_hw_mdss.h"
-
-/*
- * This is the common struct maintained by each sub block
- * for mapping the register offsets in this block to the
- * absoulute IO address
- * @base_off: mdp register mapped offset
- * @blk_off: pipe offset relative to mdss offset
- * @length length of register block offset
- * @hwversion mdss hw version number
- */
-struct sde_hw_blk_reg_map {
- void __iomem *base_off;
- u32 blk_off;
- u32 length;
- u32 hwversion;
-};
-
-void sde_hw_reg_write(void __iomem *base, u32 blk_offset, u32 reg, u32 val);
-
-u32 sde_hw_reg_read(void __iomem *base, u32 blk_offset, u32 reg);
-
-static inline void SDE_REG_WRITE(struct sde_hw_blk_reg_map *c, u32 reg_off,
- u32 val)
-{
- sde_hw_reg_write(c->base_off, c->blk_off, reg_off, val);
-}
-
-static inline int SDE_REG_READ(struct sde_hw_blk_reg_map *c, u32 reg_off)
-{
- return sde_hw_reg_read(c->base_off, c->blk_off, reg_off);
-}
-
-void sde_hw_csc_setup(struct sde_hw_blk_reg_map *c,
- u32 csc_reg_off,
- struct sde_csc_cfg *data);
-
-#endif /* _SDE_HW_MDP_UTIL_H */
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
deleted file mode 100644
index 075e78042f17..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ /dev/null
@@ -1,358 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_MDSS_H
-#define _SDE_HW_MDSS_H
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-
-#define SDE_NONE 0
-#define SDE_CSC_MATRIX_COEFF_SIZE 9
-#define SDE_CSC_CLAMP_SIZE 6
-#define SDE_CSC_BIAS_SIZE 3
-
-#define SDE_MAX_PLANES 4
-#define PIPES_PER_STAGE 2
-#define VALID_ROT_WB_FORMAT BIT(0)
-
-enum sde_mdp {
- MDP_TOP = 0x1,
- MDP_MAX,
-};
-
-enum sde_sspp {
- SSPP_NONE,
- SSPP_VIG0,
- SSPP_VIG1,
- SSPP_VIG2,
- SSPP_VIG3,
- SSPP_RGB0,
- SSPP_RGB1,
- SSPP_RGB2,
- SSPP_RGB3,
- SSPP_DMA0,
- SSPP_DMA1,
- SSPP_DMA2,
- SSPP_DMA3,
- SSPP_CURSOR0,
- SSPP_CURSOR1,
- SSPP_MAX
-};
-
-enum sde_sspp_type {
- SSPP_TYPE_VIG,
- SSPP_TYPE_RGB,
- SSPP_TYPE_DMA,
- SSPP_TYPE_CURSOR,
- SSPP_TYPE_MAX
-};
-
-enum sde_lm {
- LM_0 = 1,
- LM_1,
- LM_2,
- LM_3,
- LM_4,
- LM_5,
- LM_6,
- LM_MAX
-};
-
-enum sde_stage {
- SDE_STAGE_BASE = 0,
- SDE_STAGE_0,
- SDE_STAGE_1,
- SDE_STAGE_2,
- SDE_STAGE_3,
- SDE_STAGE_4,
- SDE_STAGE_5,
- SDE_STAGE_6,
- SDE_STAGE_MAX
-};
-enum sde_dspp {
- DSPP_0 = 1,
- DSPP_1,
- DSPP_2,
- DSPP_3,
- DSPP_MAX
-};
-
-enum sde_ctl {
- CTL_0 = 1,
- CTL_1,
- CTL_2,
- CTL_3,
- CTL_4,
- CTL_MAX
-};
-
-enum sde_cdm {
- CDM_0 = 1,
- CDM_1,
- CDM_MAX
-};
-
-enum sde_pingpong {
- PINGPONG_0 = 1,
- PINGPONG_1,
- PINGPONG_2,
- PINGPONG_3,
- PINGPONG_4,
- PINGPONG_S0,
- PINGPONG_MAX
-};
-
-enum sde_intf {
- INTF_0 = 1,
- INTF_1,
- INTF_2,
- INTF_3,
- INTF_4,
- INTF_5,
- INTF_6,
- INTF_MAX
-};
-
-enum sde_intf_type {
- INTF_NONE = 0x0,
- INTF_DSI = 0x1,
- INTF_HDMI = 0x3,
- INTF_LCDC = 0x5,
- INTF_EDP = 0x9,
- INTF_TYPE_MAX
-};
-
-enum sde_intf_mode {
- INTF_MODE_NONE = 0,
- INTF_MODE_CMD,
- INTF_MODE_VIDEO,
- INTF_MODE_WB_BLOCK,
- INTF_MODE_WB_LINE,
- INTF_MODE_MAX
-};
-
-enum sde_wb {
- WB_0 = 1,
- WB_1,
- WB_2,
- WB_3,
- WB_MAX
-};
-
-enum sde_ad {
- AD_0 = 0x1,
- AD_1,
- AD_MAX
-};
-
-enum sde_cwb {
- CWB_0 = 0x1,
- CWB_1,
- CWB_2,
- CWB_3,
- CWB_MAX
-};
-
-enum sde_wd_timer {
- WD_TIMER_0 = 0x1,
- WD_TIMER_1,
- WD_TIMER_2,
- WD_TIMER_3,
- WD_TIMER_4,
- WD_TIMER_5,
- WD_TIMER_MAX
-};
-
-/**
- * MDP HW,Component order color map
- */
-enum {
- C0_G_Y = 0,
- C1_B_Cb = 1,
- C2_R_Cr = 2,
- C3_ALPHA = 3
-};
-
-/**
- * enum sde_mdp_plane_type - defines how the color component pixel packing
- * @SDE_MDP_PLANE_INTERLEAVED : Color components in single plane
- * @SDE_MDP_PLANE_PLANAR : Color component in separate planes
- * @SDE_MDP_PLANE_PSEUDO_PLANAR : Chroma components interleaved in separate
- * plane
- */
-enum sde_mdp_plane_type {
- SDE_MDP_PLANE_INTERLEAVED,
- SDE_MDP_PLANE_PLANAR,
- SDE_MDP_PLANE_PSEUDO_PLANAR,
-};
-
-/**
- * enum sde_mdp_chroma_samp_type - chroma sub-samplng type
- * @SDE_MDP_CHROMA_RGB : no chroma subsampling
- * @SDE_MDP_CHROMA_H2V1 : chroma pixels are horizontally subsampled
- * @SDE_MDP_CHROMA_H1V2 : chroma pixels are vertically subsampled
- * @SDE_MDP_CHROMA_420 : 420 subsampling
- */
-enum sde_mdp_chroma_samp_type {
- SDE_MDP_CHROMA_RGB,
- SDE_MDP_CHROMA_H2V1,
- SDE_MDP_CHROMA_H1V2,
- SDE_MDP_CHROMA_420
-};
-
-/**
- * enum sde_mdp_fetch_type - format id, used by drm-driver only to map drm forcc
- * Defines How MDP HW fetches data
- * @SDE_MDP_FETCH_LINEAR : fetch is line by line
- * @SDE_MDP_FETCH_TILE : fetches data in Z order from a tile
- * @SDE_MDP_FETCH_UBWC : fetch and decompress data
- */
-enum sde_mdp_fetch_type {
- SDE_MDP_FETCH_LINEAR,
- SDE_MDP_FETCH_TILE,
- SDE_MDP_FETCH_UBWC
-};
-
-/**
- * Value of enum chosen to fit the number of bits
- * expected by the HW programming.
- */
-enum {
- COLOR_1BIT = 0,
- COLOR_5BIT = 1,
- COLOR_6BIT = 2,
- COLOR_8BIT = 3,
-};
-
-enum sde_alpha_blend_type {
- ALPHA_FG_CONST = 0,
- ALPHA_BG_CONST,
- ALPHA_FG_PIXEL,
- ALPHA_BG_PIXEL,
- ALPHA_MAX
-};
-
-
-/**
- * enum sde_3d_blend_mode
- * Desribes how the 3d data is blended
- * @BLEND_3D_NONE : 3d blending not enabled
- * @BLEND_3D_FRAME_INT : Frame interleaving
- * @BLEND_3D_H_ROW_INT : Horizontal row interleaving
- * @BLEND_3D_V_ROW_INT : vertical row interleaving
- * @BLEND_3D_COL_INT : column interleaving
- * @BLEND_3D_MAX :
- */
-enum sde_3d_blend_mode {
- BLEND_3D_NONE = 0,
- BLEND_3D_FRAME_INT,
- BLEND_3D_H_ROW_INT,
- BLEND_3D_V_ROW_INT,
- BLEND_3D_COL_INT,
- BLEND_3D_MAX
-};
-
-struct addr_info {
- u32 plane[SDE_MAX_PLANES];
-};
-
-/**
- * struct sde_mdp_format_params - defines the format configuration which
- * allows MDP HW to correctly fetch and decode the format
- * @format : format id, used by drm-driver only to map drm forcc
- * @flag
- * @chroma_sample
- * @fetch_planes
- * @unpack_align_msb
- * @unpack_tight
- * @unpack_count
- * @bpp
- * @alpha_enable
- * @fetch_mode
- * @bits
- * @element
- */
-struct sde_mdp_format_params {
- u32 format;
- enum sde_mdp_plane_type fetch_planes;
- u8 element[SDE_MAX_PLANES];
- u8 bits[SDE_MAX_PLANES];
- enum sde_mdp_chroma_samp_type chroma_sample;
- u8 unpack_align_msb; /* 0 to LSB, 1 to MSB */
- u8 unpack_tight; /* 0 for loose, 1 for tight */
- u8 unpack_count; /* 0 = 1 component, 1 = 2 component ... */
- u8 bpp; /* Bytes per pixel */
- u8 alpha_enable; /* source has alpha */
- enum sde_mdp_fetch_type fetch_mode;
- u8 is_yuv;
- u32 flag;
-};
-
-/**
- * struct sde_hw_source_info - format information of the source pixel data
- * @format : pixel format parameters
- * @width : image width @height: image height
- * @num_planes : number of planes including the meta data planes for the
- * compressed formats @plane: per plane information
- */
-struct sde_hw_source_info {
- struct sde_mdp_format_params *format;
- u32 width;
- u32 height;
- u32 num_planes;
- u32 ystride[SDE_MAX_PLANES];
-};
-
-struct sde_rect {
- u16 x;
- u16 y;
- u16 w;
- u16 h;
-};
-
-struct sde_hw_alpha_cfg {
- u32 const_alpha;
- enum sde_alpha_blend_type alpha_sel;
- u8 inv_alpha_sel;
- u8 mod_alpha;
- u8 inv_mode_alpha;
-};
-
-struct sde_hw_blend_cfg {
- struct sde_hw_alpha_cfg fg;
- struct sde_hw_alpha_cfg bg;
-};
-
-struct sde_csc_cfg {
- uint32_t csc_mv[SDE_CSC_MATRIX_COEFF_SIZE];
- uint32_t csc_pre_bv[SDE_CSC_BIAS_SIZE];
- uint32_t csc_post_bv[SDE_CSC_BIAS_SIZE];
- uint32_t csc_pre_lv[SDE_CSC_CLAMP_SIZE];
- uint32_t csc_post_lv[SDE_CSC_CLAMP_SIZE];
-};
-
-/**
- * struct sde_mdss_color - mdss color description
- * color 0 : green
- * color 1 : blue
- * color 2 : red
- * color 3 : alpha
- */
-struct sde_mdss_color {
- u32 color_0;
- u32 color_1;
- u32 color_2;
- u32 color_3;
-};
-
-#endif /* _SDE_HW_MDSS_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c
deleted file mode 100644
index 6bee52fd670d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_pingpong.h"
-
-#define PP_TEAR_CHECK_EN 0x000
-#define PP_SYNC_CONFIG_VSYNC 0x004
-#define PP_SYNC_CONFIG_HEIGHT 0x008
-#define PP_SYNC_WRCOUNT 0x00C
-#define PP_VSYNC_INIT_VAL 0x010
-#define PP_INT_COUNT_VAL 0x014
-#define PP_SYNC_THRESH 0x018
-#define PP_START_POS 0x01C
-#define PP_RD_PTR_IRQ 0x020
-#define PP_WR_PTR_IRQ 0x024
-#define PP_OUT_LINE_COUNT 0x028
-#define PP_LINE_COUNT 0x02C
-#define PP_AUTOREFRESH_CONFIG 0x030
-
-#define PP_FBC_MODE 0x034
-#define PP_FBC_BUDGET_CTL 0x038
-#define PP_FBC_LOSSY_MODE 0x03C
-#define PP_DSC_MODE 0x0a0
-#define PP_DCE_DATA_IN_SWAP 0x0ac
-#define PP_DCE_DATA_OUT_SWAP 0x0c8
-
-static struct sde_pingpong_cfg *_pingpong_offset(enum sde_pingpong pp,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->pingpong_count; i++) {
- if (pp == m->pingpong[i].id) {
- b->base_off = addr;
- b->blk_off = m->pingpong[i].base;
- b->hwversion = m->hwversion;
- return &m->pingpong[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-static int sde_hw_pp_setup_te_config(struct sde_hw_pingpong *pp,
- struct sde_hw_tear_check *te)
-{
- struct sde_hw_blk_reg_map *c = &pp->hw;
- int cfg;
-
- cfg = BIT(19); /*VSYNC_COUNTER_EN */
- if (te->hw_vsync_mode)
- cfg |= BIT(20);
-
- cfg |= te->vsync_count;
-
- SDE_REG_WRITE(c, PP_SYNC_CONFIG_VSYNC, cfg);
- SDE_REG_WRITE(c, PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
- SDE_REG_WRITE(c, PP_VSYNC_INIT_VAL, te->vsync_init_val);
- SDE_REG_WRITE(c, PP_RD_PTR_IRQ, te->rd_ptr_irq);
- SDE_REG_WRITE(c, PP_START_POS, te->start_pos);
- SDE_REG_WRITE(c, PP_SYNC_THRESH,
- ((te->sync_threshold_continue << 16) |
- te->sync_threshold_start));
- SDE_REG_WRITE(c, PP_SYNC_WRCOUNT,
- (te->start_pos + te->sync_threshold_start + 1));
-
- return 0;
-}
-
-int sde_hw_pp_setup_autorefresh_config(struct sde_hw_pingpong *pp,
- struct sde_hw_autorefresh *cfg)
-{
- struct sde_hw_blk_reg_map *c = &pp->hw;
- u32 refresh_cfg;
-
- if (cfg->enable)
- refresh_cfg = BIT(31) | cfg->frame_count;
- else
- refresh_cfg = 0;
-
- SDE_REG_WRITE(c, PP_AUTOREFRESH_CONFIG,
- refresh_cfg);
-
- return 0;
-}
-
-int sde_hw_pp_setup_dsc_compression(struct sde_hw_pingpong *pp,
- struct sde_hw_dsc_cfg *cfg)
-{
- return 0;
-}
-int sde_hw_pp_enable_te(struct sde_hw_pingpong *pp, bool enable)
-{
- struct sde_hw_blk_reg_map *c = &pp->hw;
-
- SDE_REG_WRITE(c, PP_TEAR_CHECK_EN, enable);
- return 0;
-}
-
-int sde_hw_pp_get_vsync_info(struct sde_hw_pingpong *pp,
- struct sde_hw_pp_vsync_info *info)
-{
- struct sde_hw_blk_reg_map *c = &pp->hw;
-
- info->init_val = SDE_REG_READ(c, PP_VSYNC_INIT_VAL) & 0xffff;
- info->vsync_count = SDE_REG_READ(c, PP_SYNC_CONFIG_HEIGHT) & 0xffff;
- info->line_count = SDE_REG_READ(c, PP_INT_COUNT_VAL) & 0xffff;
-
- return 0;
-}
-
-static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops,
- unsigned long cap)
-{
- ops->setup_tearcheck = sde_hw_pp_setup_te_config;
- ops->enable_tearcheck = sde_hw_pp_enable_te;
- ops->get_vsync_info = sde_hw_pp_get_vsync_info;
- ops->setup_autorefresh = sde_hw_pp_setup_autorefresh_config;
- ops->setup_dsc = sde_hw_pp_setup_dsc_compression;
-};
-
-struct sde_hw_pingpong *sde_hw_pingpong_init(enum sde_pingpong idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_pingpong *c;
- struct sde_pingpong_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _pingpong_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- c->idx = idx;
- c->pingpong_hw_cap = cfg;
- _setup_pingpong_ops(&c->ops, c->pingpong_hw_cap->features);
-
- return c;
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.h b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.h
deleted file mode 100644
index 7cb4cf184e48..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_PINGPONG_H
-#define _SDE_HW_PINGPONG_H
-
-struct sde_hw_pingpong;
-
-struct sde_hw_tear_check {
- /*
- * This is ratio of MDP VSYNC clk freq(Hz) to
- * refresh rate divided by no of lines
- */
- u32 vsync_count;
- u32 sync_cfg_height;
- u32 vsync_init_val;
- u32 sync_threshold_start;
- u32 sync_threshold_continue;
- u32 start_pos;
- u32 rd_ptr_irq;
- u8 hw_vsync_mode;
-};
-
-struct sde_hw_autorefresh {
- bool enable;
- u32 frame_count;
-};
-
-struct sde_hw_pp_vsync_info {
- u32 init_val; /* value of rd pointer at vsync edge */
- u32 vsync_count; /* mdp clocks to complete one line */
- u32 line_count; /* current line count */
-};
-
-struct sde_hw_dsc_cfg {
- u8 enable;
-};
-
-/**
- *
- * struct sde_hw_pingpong_ops : Interface to the pingpong Hw driver functions
- * Assumption is these functions will be called after clocks are enabled
- * @setup_tearcheck :
- * @enable_tearcheck :
- * @get_vsync_info :
- * @setup_autorefresh :
- * #setup_dsc :
- */
-struct sde_hw_pingpong_ops {
- /**
- * enables vysnc generation and sets up init value of
- * read pointer and programs the tear check cofiguration
- */
- int (*setup_tearcheck)(struct sde_hw_pingpong *pp,
- struct sde_hw_tear_check *cfg);
-
- /**
- * enables tear check block
- */
- int (*enable_tearcheck)(struct sde_hw_pingpong *pp,
- bool enable);
-
- /**
- * provides the programmed and current
- * line_count
- */
- int (*get_vsync_info)(struct sde_hw_pingpong *pp,
- struct sde_hw_pp_vsync_info *info);
-
- /**
- * configure and enable the autorefresh config
- */
- int (*setup_autorefresh)(struct sde_hw_pingpong *pp,
- struct sde_hw_autorefresh *cfg);
-
- /**
- * Program the dsc compression block
- */
- int (*setup_dsc)(struct sde_hw_pingpong *pp,
- struct sde_hw_dsc_cfg *cfg);
-};
-
-struct sde_hw_pingpong {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* pingpong */
- enum sde_pingpong idx;
- const struct sde_pingpong_cfg *pingpong_hw_cap;
-
- /* ops */
- struct sde_hw_pingpong_ops ops;
-};
-
-/**
- * sde_hw_pingpong_init(): Initializes the pingpong driver for the passed
- * pingpong idx.
- * @idx: pingpong index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_pingpong *sde_hw_pingpong_init(enum sde_pingpong idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-#endif /*_SDE_HW_PINGPONG_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
deleted file mode 100644
index 8180078ac950..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_sspp.h"
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_lm.h"
-
-#define SDE_MDP_FETCH_CONFIG_RESET_VALUE 0x00000087
-
-/* SDE_SSPP_SRC */
-#define SSPP_SRC_SIZE 0x00
-#define SSPP_SRC_XY 0x08
-#define SSPP_OUT_SIZE 0x0c
-#define SSPP_OUT_XY 0x10
-#define SSPP_SRC0_ADDR 0x14
-#define SSPP_SRC1_ADDR 0x18
-#define SSPP_SRC2_ADDR 0x1C
-#define SSPP_SRC3_ADDR 0x20
-#define SSPP_SRC_YSTRIDE0 0x24
-#define SSPP_SRC_YSTRIDE1 0x28
-#define SSPP_SRC_FORMAT 0x30
-#define SSPP_SRC_UNPACK_PATTERN 0x34
-#define SSPP_SRC_OP_MODE 0x38
-#define MDSS_MDP_OP_DEINTERLACE BIT(22)
-
-#define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23)
-#define MDSS_MDP_OP_IGC_ROM_1 BIT(18)
-#define MDSS_MDP_OP_IGC_ROM_0 BIT(17)
-#define MDSS_MDP_OP_IGC_EN BIT(16)
-#define MDSS_MDP_OP_FLIP_UD BIT(14)
-#define MDSS_MDP_OP_FLIP_LR BIT(13)
-#define MDSS_MDP_OP_BWC_EN BIT(0)
-#define MDSS_MDP_OP_PE_OVERRIDE BIT(31)
-#define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1)
-#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
-#define MDSS_MDP_OP_BWC_Q_MED (2 << 1)
-
-#define SSPP_SRC_CONSTANT_COLOR 0x3c
-#define SSPP_FETCH_CONFIG 0x048
-#define SSPP_DANGER_LUT 0x60
-#define SSPP_SAFE_LUT 0x64
-#define SSPP_CREQ_LUT 0x68
-#define SSPP_DECIMATION_CONFIG 0xB4
-#define SSPP_SRC_ADDR_SW_STATUS 0x70
-#define SSPP_SW_PIX_EXT_C0_LR 0x100
-#define SSPP_SW_PIX_EXT_C0_TB 0x104
-#define SSPP_SW_PIX_EXT_C0_REQ_PIXELS 0x108
-#define SSPP_SW_PIX_EXT_C1C2_LR 0x110
-#define SSPP_SW_PIX_EXT_C1C2_TB 0x114
-#define SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS 0x118
-#define SSPP_SW_PIX_EXT_C3_LR 0x120
-#define SSPP_SW_PIX_EXT_C3_TB 0x124
-#define SSPP_SW_PIX_EXT_C3_REQ_PIXELS 0x128
-#define SSPP_UBWC_ERROR_STATUS 0x138
-#define SSPP_VIG_OP_MODE 0x200
-
-/* SDE_SSPP_SCALAR_QSEED2 */
-#define SCALE_CONFIG 0x04
-#define COMP0_3_PHASE_STEP_X 0x10
-#define COMP0_3_PHASE_STEP_Y 0x14
-#define COMP1_2_PHASE_STEP_X 0x18
-#define COMP1_2_PHASE_STEP_Y 0x1c
-#define COMP0_3_INIT_PHASE_X 0x20
-#define COMP0_3_INIT_PHASE_Y 0x24
-#define COMP1_2_INIT_PHASE_X 0x28
-#define COMP1_2_INIT_PHASE_Y 0x2C
-#define VIG_0_QSEED2_SHARP 0x30
-
-#define VIG_0_CSC_1_MATRIX_COEFF_0 0x20
-#define VIG_0_CSC_1_COMP_0_PRE_CLAMP 0x34
-#define VIG_0_CSC_1_COMP_0_POST_CLAMP 0x40
-#define VIG_0_CSC_1_COMP_0_PRE_BIAS 0x4C
-#define VIG_0_CSC_1_COMP_0_POST_BIAS 0x60
-
-/*
- * MDP Solid fill configuration
- * argb8888
- */
-#define SSPP_SOLID_FILL 0x4037ff
-
-enum {
- CSC = 0x1,
- PA,
- HIST,
- SKIN_COL,
- FOIL,
- SKY_COL,
- MEM_PROT_HUE,
- MEM_PROT_SAT,
- MEM_PROT_VAL,
- MEM_PROT_CONT,
- MEM_PROT_BLEND,
- PA_SAT_ADJ
-};
-
-static inline int _sspp_subblk_offset(struct sde_hw_pipe *ctx,
- int s_id,
- u32 *idx)
-{
- int rc = 0;
- const struct sde_sspp_sub_blks *sblk = ctx->cap->sblk;
-
- switch (s_id) {
- case SDE_SSPP_SRC:
- *idx = sblk->src_blk.base;
- break;
- case SDE_SSPP_SCALAR_QSEED2:
- case SDE_SSPP_SCALAR_QSEED3:
- case SDE_SSPP_SCALAR_RGB:
- *idx = sblk->scalar_blk.base;
- break;
- case SDE_SSPP_CSC:
- *idx = sblk->csc_blk.base;
- break;
- case SDE_SSPP_PA_V1:
- *idx = sblk->pa_blk.base;
- break;
- case SDE_SSPP_HIST_V1:
- *idx = sblk->hist_lut.base;
- break;
- case SDE_SSPP_PCC:
- *idx = sblk->pcc_blk.base;
- break;
- default:
- rc = -EINVAL;
- pr_err("Unsupported SSPP sub-blk for this hw\n");
- }
-
- return rc;
-}
-
-static void _sspp_setup_opmode(struct sde_hw_pipe *ctx,
- u32 op, u8 en)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 idx;
- u32 opmode;
-
- if (ctx->cap->features == SDE_SSPP_PA_V1) {
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- opmode = SDE_REG_READ(c, SSPP_VIG_OP_MODE + idx);
-
- /* ops */
- switch (op) {
- case CSC:
- if (en)
- /* CSC_1_EN and CSC_SRC_DATA_FORMAT*/
- opmode |= BIT(18) | BIT(17);
- else
- opmode &= ~BIT(17);
- break;
- default:
- pr_err(" Unsupported operation\n");
- }
- SDE_REG_WRITE(c, SSPP_VIG_OP_MODE + idx, opmode);
- }
-}
-/**
- * Setup source pixel format, flip,
- */
-static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- u32 flags)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- struct sde_mdp_format_params *fmt;
- u32 chroma_samp, unpack, src_format;
- u32 secure = 0;
- u32 opmode = 0;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- opmode = SDE_REG_READ(c, SSPP_SRC_OP_MODE + idx);
-
- /* format info */
- fmt = cfg->src.format;
- if (WARN_ON(!fmt))
- return;
-
- if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
- secure = 0xF;
-
- if (flags & SDE_SSPP_FLIP_LR)
- opmode |= MDSS_MDP_OP_FLIP_LR;
- if (flags & SDE_SSPP_FLIP_UD)
- opmode |= MDSS_MDP_OP_FLIP_UD;
-
- chroma_samp = fmt->chroma_sample;
- if (flags & SDE_SSPP_SOURCE_ROTATED_90) {
- if (chroma_samp == SDE_MDP_CHROMA_H2V1)
- chroma_samp = SDE_MDP_CHROMA_H1V2;
- else if (chroma_samp == SDE_MDP_CHROMA_H1V2)
- chroma_samp = SDE_MDP_CHROMA_H2V1;
- }
-
- src_format = (chroma_samp << 23) | (fmt->fetch_planes << 19) |
- (fmt->bits[C3_ALPHA] << 6) | (fmt->bits[C2_R_Cr] << 4) |
- (fmt->bits[C1_B_Cb] << 2) | (fmt->bits[C0_G_Y] << 0);
-
- if (flags & SDE_SSPP_ROT_90)
- src_format |= BIT(11); /* ROT90 */
-
- if (fmt->alpha_enable &&
- fmt->fetch_planes != SDE_MDP_PLANE_INTERLEAVED)
- src_format |= BIT(8); /* SRCC3_EN */
-
- unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
- (fmt->element[1] << 8) | (fmt->element[0] << 0);
- src_format |= ((fmt->unpack_count - 1) << 12) |
- (fmt->unpack_tight << 17) |
- (fmt->unpack_align_msb << 18) |
- ((fmt->bpp - 1) << 9);
-
- if (fmt->fetch_mode != SDE_MDP_FETCH_LINEAR) {
- opmode |= MDSS_MDP_OP_BWC_EN;
- src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
- SDE_REG_WRITE(c, SSPP_FETCH_CONFIG,
- SDE_MDP_FETCH_CONFIG_RESET_VALUE |
- ctx->highest_bank_bit << 18);
- }
-
- /* if this is YUV pixel format, enable CSC */
- if (fmt->is_yuv)
- src_format |= BIT(15);
- _sspp_setup_opmode(ctx, CSC, fmt->is_yuv);
-
- opmode |= MDSS_MDP_OP_PE_OVERRIDE;
-
- SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
- SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
- SDE_REG_WRITE(c, SSPP_SRC_OP_MODE + idx, opmode);
- SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
-
- /* clear previous UBWC error */
- SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
-}
-
-static void sde_hw_sspp_setup_pe_config(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- struct sde_hw_pixel_ext *pe_ext)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u8 color;
- u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
- const u32 bytemask = 0xff;
- const u32 shortmask = 0xffff;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- /* program SW pixel extension override for all pipes*/
- for (color = 0; color < 4; color++) {
- /* color 2 has the same set of registers as color 1 */
- if (color == 2)
- continue;
-
- lr_pe[color] = ((pe_ext->right_ftch[color] & bytemask) << 24)|
- ((pe_ext->right_rpt[color] & bytemask) << 16)|
- ((pe_ext->left_ftch[color] & bytemask) << 8)|
- (pe_ext->left_rpt[color] & bytemask);
-
- tb_pe[color] = ((pe_ext->btm_ftch[color] & bytemask) << 24)|
- ((pe_ext->btm_rpt[color] & bytemask) << 16)|
- ((pe_ext->top_ftch[color] & bytemask) << 8)|
- (pe_ext->top_rpt[color] & bytemask);
-
- tot_req_pixels[color] = (((pe_ext->roi_h[color] +
- pe_ext->num_ext_pxls_top[color] +
- pe_ext->num_ext_pxls_btm[color]) & shortmask) << 16) |
- ((pe_ext->roi_w[color] +
- pe_ext->num_ext_pxls_left[color] +
- pe_ext->num_ext_pxls_right[color]) & shortmask);
- }
-
- /* color 0 */
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR + idx, lr_pe[0]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB + idx, tb_pe[0]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS + idx,
- tot_req_pixels[0]);
-
- /* color 1 and color 2 */
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR + idx, lr_pe[1]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB + idx, tb_pe[1]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS + idx,
- tot_req_pixels[1]);
-
- /* color 3 */
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR + idx, lr_pe[3]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB + idx, lr_pe[3]);
- SDE_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS + idx,
- tot_req_pixels[3]);
-}
-
-static void sde_hw_sspp_setup_scalar(struct sde_hw_pipe *ctx,
- struct sde_hw_pixel_ext *pe_ext)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- int scale_config;
- const u8 mask = 0x3;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALAR_QSEED2, &idx))
- return;
-
- scale_config = BIT(0) | BIT(1);
- /* RGB/YUV config */
- scale_config |= (pe_ext->horz_filter[SDE_SSPP_COMP_LUMA] & mask) << 8;
- scale_config |= (pe_ext->vert_filter[SDE_SSPP_COMP_LUMA] & mask) << 10;
- /* Aplha config*/
- scale_config |= (pe_ext->horz_filter[SDE_SSPP_COMP_ALPHA] & mask) << 16;
- scale_config |= (pe_ext->vert_filter[SDE_SSPP_COMP_ALPHA] & mask) << 18;
-
- SDE_REG_WRITE(c, SCALE_CONFIG + idx, scale_config);
- SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_X + idx,
- pe_ext->init_phase_x[SDE_SSPP_COMP_LUMA]);
- SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_Y + idx,
- pe_ext->init_phase_y[SDE_SSPP_COMP_LUMA]);
- SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_X + idx,
- pe_ext->phase_step_x[SDE_SSPP_COMP_LUMA]);
- SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_Y + idx,
- pe_ext->phase_step_y[SDE_SSPP_COMP_LUMA]);
-
- SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_X + idx,
- pe_ext->init_phase_x[SDE_SSPP_COMP_CHROMA]);
- SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_Y + idx,
- pe_ext->init_phase_y[SDE_SSPP_COMP_CHROMA]);
- SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_X + idx,
- pe_ext->phase_step_x[SDE_SSPP_COMP_CHROMA]);
- SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_Y + idx,
- pe_ext->phase_step_y[SDE_SSPP_COMP_CHROMA]);
-}
-
-/**
- * sde_hw_sspp_setup_rects()
- */
-static void sde_hw_sspp_setup_rects(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- struct sde_hw_pixel_ext *pe_ext)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
- u32 decimation = 0;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- /* program pixel extension override */
- if (pe_ext)
- sde_hw_sspp_setup_pe_config(ctx, cfg, pe_ext);
-
- /* src and dest rect programming */
- src_xy = (cfg->src_rect.y << 16) |
- (cfg->src_rect.x);
- src_size = (cfg->src_rect.h << 16) |
- (cfg->src_rect.w);
- dst_xy = (cfg->dst_rect.y << 16) |
- (cfg->dst_rect.x);
- dst_size = (cfg->dst_rect.h << 16) |
- (cfg->dst_rect.w);
-
- ystride0 = (cfg->src.ystride[0]) |
- (cfg->src.ystride[1] << 16);
- ystride1 = (cfg->src.ystride[2]) |
- (cfg->src.ystride[3] << 16);
-
- /* program scalar, phase registers, if pipes supporting scaling */
- if (src_size != dst_size) {
- if (test_bit(SDE_SSPP_SCALAR_RGB, &ctx->cap->features) ||
- test_bit(SDE_SSPP_SCALAR_QSEED2, &ctx->cap->features)) {
- /* program decimation */
- decimation = ((1 << cfg->horz_decimation) - 1) << 8;
- decimation |= ((1 << cfg->vert_decimation) - 1);
-
- sde_hw_sspp_setup_scalar(ctx, pe_ext);
- }
- }
-
- /* Rectangle Register programming */
- SDE_REG_WRITE(c, SSPP_SRC_SIZE + idx, src_size);
- SDE_REG_WRITE(c, SSPP_SRC_XY + idx, src_xy);
- SDE_REG_WRITE(c, SSPP_OUT_SIZE + idx, dst_size);
- SDE_REG_WRITE(c, SSPP_OUT_XY + idx, dst_xy);
-
- SDE_REG_WRITE(c, SSPP_SRC_YSTRIDE0 + idx, ystride0);
- SDE_REG_WRITE(c, SSPP_SRC_YSTRIDE1 + idx, ystride1);
- SDE_REG_WRITE(c, SSPP_DECIMATION_CONFIG + idx, decimation);
-}
-
-static void sde_hw_sspp_setup_sourceaddress(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- int i;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- for (i = 0; i < cfg->src.num_planes; i++)
- SDE_REG_WRITE(c, SSPP_SRC0_ADDR + idx + i*0x4,
- cfg->addr.plane[i]);
-}
-
-static void sde_hw_sspp_setup_csc_8bit(struct sde_hw_pipe *ctx,
- struct sde_csc_cfg *data)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
-
- sde_hw_csc_setup(c, VIG_0_CSC_1_MATRIX_COEFF_0, data);
-}
-
-static void sde_hw_sspp_setup_sharpening(struct sde_hw_pipe *ctx,
- struct sde_hw_sharp_cfg *cfg)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx, cfg->strength);
- SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x4, cfg->edge_thr);
- SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x8, cfg->smooth_thr);
- SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0xC, cfg->noise_thr);
-}
-
-static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx,
- u32 const_color,
- u32 flags)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 secure = 0;
- u32 unpack, src_format, opmode = 0;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- /* format info */
- src_format = SSPP_SOLID_FILL;
- unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
- (C1_B_Cb << 8) | (C0_G_Y << 0);
- secure = (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) ? 0xF : 0x00;
- opmode = MDSS_MDP_OP_PE_OVERRIDE;
-
- SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
- SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
- SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
- SDE_REG_WRITE(c, SSPP_SRC_CONSTANT_COLOR + idx, const_color);
- SDE_REG_WRITE(c, SSPP_SRC_OP_MODE + idx, opmode);
-}
-
-static void sde_hw_sspp_setup_histogram_v1(struct sde_hw_pipe *ctx,
- void *cfg)
-{
-}
-
-static void sde_hw_sspp_setup_memcolor(struct sde_hw_pipe *ctx,
- u32 memcolortype, u8 en)
-{
-}
-
-static void sde_hw_sspp_setup_igc(struct sde_hw_pipe *ctx)
-{
-}
-
-void sde_sspp_setup_pa(struct sde_hw_pipe *c)
-{
-}
-
-static void sde_hw_sspp_setup_danger_safe(struct sde_hw_pipe *ctx,
- u32 danger_lut, u32 safe_lut)
-{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
- return;
-
- SDE_REG_WRITE(c, SSPP_DANGER_LUT + idx, danger_lut);
- SDE_REG_WRITE(c, SSPP_SAFE_LUT + idx, safe_lut);
-}
-
-static void sde_hw_sspp_qseed2_coeff(void *ctx)
-{
-}
-
-static void _setup_layer_ops(struct sde_hw_sspp_ops *ops,
- unsigned long features)
-{
- if (test_bit(SDE_SSPP_SRC, &features)) {
- ops->setup_sourceformat = sde_hw_sspp_setup_format;
- ops->setup_rects = sde_hw_sspp_setup_rects;
- ops->setup_sourceaddress = sde_hw_sspp_setup_sourceaddress;
- ops->setup_solidfill = sde_hw_sspp_setup_solidfill;
- ops->setup_danger_safe = sde_hw_sspp_setup_danger_safe;
- }
- if (test_bit(SDE_SSPP_CSC, &features))
- ops->setup_csc = sde_hw_sspp_setup_csc_8bit;
-
- if (test_bit(SDE_SSPP_PA_V1, &features)) {
- ops->setup_sharpening = sde_hw_sspp_setup_sharpening;
- ops->setup_pa_memcolor = sde_hw_sspp_setup_memcolor;
- }
- if (test_bit(SDE_SSPP_HIST_V1, &features))
- ops->setup_histogram = sde_hw_sspp_setup_histogram_v1;
-
- if (test_bit(SDE_SSPP_IGC, &features))
- ops->setup_igc = sde_hw_sspp_setup_igc;
-}
-
-static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->sspp_count; i++) {
- if (sspp == m->sspp[i].id) {
- b->base_off = addr;
- b->blk_off = m->sspp[i].base;
- b->hwversion = m->hwversion;
- return &m->sspp[i];
- }
- }
-
- return ERR_PTR(-ENOMEM);
-}
-
-struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_pipe *c;
- struct sde_sspp_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _sspp_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- /* Assign ops */
- c->idx = idx;
- c->cap = cfg;
- _setup_layer_ops(&c->ops, c->cap->features);
- c->highest_bank_bit = m->mdp[0].highest_bank_bit;
-
- /*
- * Perform any default initialization for the sspp blocks
- */
- if (test_bit(SDE_SSPP_SCALAR_QSEED2, &cfg->features))
- sde_hw_sspp_qseed2_coeff(c);
-
- if (test_bit(SDE_MDP_PANIC_PER_PIPE, &m->mdp[0].features))
- sde_hw_sspp_setup_danger_safe(c,
- cfg->sblk->danger_lut,
- cfg->sblk->safe_lut);
-
- return c;
-}
-
-void sde_hw_sspp_destroy(struct sde_hw_pipe *ctx)
-{
- kfree(ctx);
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
deleted file mode 100644
index 0e78c52cde56..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_SSPP_H
-#define _SDE_HW_SSPP_H
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-
-struct sde_hw_pipe;
-
-/**
- * Flags
- */
-#define SDE_SSPP_SECURE_OVERLAY_SESSION 0x1
-#define SDE_SSPP_FLIP_LR 0x2
-#define SDE_SSPP_FLIP_UD 0x4
-#define SDE_SSPP_SOURCE_ROTATED_90 0x8
-#define SDE_SSPP_ROT_90 0x10
-
-/**
- * Component indices
- */
-enum {
- SDE_SSPP_COMP_LUMA = 0,
- SDE_SSPP_COMP_CHROMA = 1,
- SDE_SSPP_COMP_ALPHA = 3
-};
-
-enum {
- SDE_MDP_FRAME_LINEAR,
- SDE_MDP_FRAME_TILE_A4X,
- SDE_MDP_FRAME_TILE_A5X,
-};
-
-enum sde_hw_filter {
- SDE_MDP_SCALE_FILTER_NEAREST = 0,
- SDE_MDP_SCALE_FILTER_BIL,
- SDE_MDP_SCALE_FILTER_PCMN,
- SDE_MDP_SCALE_FILTER_CA,
- SDE_MDP_SCALE_FILTER_MAX
-};
-
-struct sde_hw_sharp_cfg {
- u32 strength;
- u32 edge_thr;
- u32 smooth_thr;
- u32 noise_thr;
-};
-
-struct sde_hw_pixel_ext {
- /* scaling factors are enabled for this input layer */
- uint8_t enable_pxl_ext;
-
- int init_phase_x[SDE_MAX_PLANES];
- int phase_step_x[SDE_MAX_PLANES];
- int init_phase_y[SDE_MAX_PLANES];
- int phase_step_y[SDE_MAX_PLANES];
-
- /*
- * Number of pixels extension in left, right, top and bottom direction
- * for all color components. This pixel value for each color component
- * should be sum of fetch + repeat pixels.
- */
- int num_ext_pxls_left[SDE_MAX_PLANES];
- int num_ext_pxls_right[SDE_MAX_PLANES];
- int num_ext_pxls_top[SDE_MAX_PLANES];
- int num_ext_pxls_btm[SDE_MAX_PLANES];
-
- /*
- * Number of pixels needs to be overfetched in left, right, top and
- * bottom directions from source image for scaling.
- */
- int left_ftch[SDE_MAX_PLANES];
- int right_ftch[SDE_MAX_PLANES];
- int top_ftch[SDE_MAX_PLANES];
- int btm_ftch[SDE_MAX_PLANES];
-
- /*
- * Number of pixels needs to be repeated in left, right, top and
- * bottom directions for scaling.
- */
- int left_rpt[SDE_MAX_PLANES];
- int right_rpt[SDE_MAX_PLANES];
- int top_rpt[SDE_MAX_PLANES];
- int btm_rpt[SDE_MAX_PLANES];
-
- uint32_t roi_w[SDE_MAX_PLANES];
- uint32_t roi_h[SDE_MAX_PLANES];
-
- /*
- * Filter type to be used for scaling in horizontal and vertical
- * directions
- */
- enum sde_hw_filter horz_filter[SDE_MAX_PLANES];
- enum sde_hw_filter vert_filter[SDE_MAX_PLANES];
-
-};
-
-/**
- * struct sde_hw_pipe_cfg : Pipe description
- * @src: source surface information
- * @src_rect: src ROI, caller takes into account the different operations
- * such as decimation, flip etc to program this field
- * @dest_rect: destination ROI.
- * @ horz_decimation : horizontal decimation factor( 0, 2, 4, 8, 16)
- * @ vert_decimation : vertical decimation factor( 0, 2, 4, 8, 16)
- * 2: Read 1 line/pixel drop 1 line/pixel
- * 4: Read 1 line/pixel drop 3 lines/pixels
- * 8: Read 1 line/pixel drop 7 lines/pixels
- * 16: Read 1 line/pixel drop 15 line/pixels
- * @addr: source surface address
- */
-struct sde_hw_pipe_cfg {
- struct sde_hw_source_info src;
- struct sde_rect src_rect;
- struct sde_rect dst_rect;
- u8 horz_decimation;
- u8 vert_decimation;
- struct addr_info addr;
-};
-
-/**
- * struct danger_safe_cfg:
- * @danger_lut:
- * @safe_lut:
- */
-struct danger_safe_cfg {
- u32 danger_lut;
- u32 safe_lut;
-};
-
-/**
- * struct sde_hw_sspp_ops - interface to the SSPP Hw driver functions
- * Caller must call the init function to get the pipe context for each pipe
- * Assumption is these functions will be called after clocks are enabled
- */
-struct sde_hw_sspp_ops {
- /**
- * setup_sourceformat - setup pixel format cropping rectangle, flip
- * @ctx: Pointer to pipe context
- * @cfg: Pointer to pipe config structure
- * @flags: Format flags
- */
- void (*setup_sourceformat)(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- u32 flags);
-
- /**
- * setup_rects - setup pipe ROI rectangles
- * @ctx: Pointer to pipe context
- * @cfg: Pointer to pipe config structure
- * @pe_ext: Pointer to pixel ext settings
- */
- void (*setup_rects)(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- struct sde_hw_pixel_ext *pe_ext);
-
- /**
- * setup_sourceaddress - setup pipe source addresses
- * @ctx: Pointer to pipe context
- * @cfg: Pointer to pipe config structure
- */
- void (*setup_sourceaddress)(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg);
-
- /**
- * setup_csc - setup color space coversion
- * @ctx: Pointer to pipe context
- * @data: Pointer to config structure
- */
- void (*setup_csc)(struct sde_hw_pipe *ctx,
- struct sde_csc_cfg *data);
-
- /**
- * setup_solidfill - enable/disable colorfill
- * @ctx: Pointer to pipe context
- * @const_color: Fill color value
- * @flags: Pipe flags
- */
- void (*setup_solidfill)(struct sde_hw_pipe *ctx,
- u32 const_color,
- u32 flags);
-
- /**
- * setup_sharpening - setup sharpening
- * @ctx: Pointer to pipe context
- * @cfg: Pointer to config structure
- */
- void (*setup_sharpening)(struct sde_hw_pipe *ctx,
- struct sde_hw_sharp_cfg *cfg);
-
- /**
- * setup_pa_memcolor - setup source color processing
- * @ctx: Pointer to pipe context
- * @memcolortype: Memcolor type
- * @en: PA enable
- */
- void (*setup_pa_memcolor)(struct sde_hw_pipe *ctx,
- u32 memcolortype, u8 en);
-
- /**
- * setup_igc - setup inverse gamma correction
- * @ctx: Pointer to pipe context
- */
- void (*setup_igc)(struct sde_hw_pipe *ctx);
-
- /**
- * setup_danger_safe - setup danger safe LUTS
- * @ctx: Pointer to pipe context
- * @danger_lut: Danger LUT setting
- * @safe_lut: Safe LUT setting
- */
- void (*setup_danger_safe)(struct sde_hw_pipe *ctx,
- u32 danger_lut,
- u32 safe_lut);
-
- /**
- * setup_histogram - setup histograms
- * @ctx: Pointer to pipe context
- * @cfg: Pointer to histogram configuration
- */
- void (*setup_histogram)(struct sde_hw_pipe *ctx,
- void *cfg);
-};
-
-/**
- * struct sde_hw_pipe - pipe description
- * @base_off: mdp register mapped offset
- * @blk_off: pipe offset relative to mdss offset
- * @length length of register block offset
- * @hwversion mdss hw version number
- * @idx: pipe index
- * @type : pipe type, VIG/DMA/RGB/CURSOR, certain operations are not
- * supported for each pipe type
- * @pipe_hw_cap: pointer to layer_cfg
- * @highest_bank_bit:
- * @ops: pointer to operations possible for this pipe
- */
-struct sde_hw_pipe {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* Pipe */
- enum sde_sspp idx;
- const struct sde_sspp_cfg *cap;
- u32 highest_bank_bit;
-
- /* Ops */
- struct sde_hw_sspp_ops ops;
-};
-
-/**
- * sde_hw_sspp_init - initializes the sspp hw driver object.
- * Should be called once before accessing every pipe.
- * @idx: Pipe index for which driver object is required
- * @addr: Mapped register io address of MDP
- * @m: pointer to mdss catalog data @ops:
- */
-struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-/**
- * sde_hw_sspp_destroy(): Destroys SSPP driver context
- * should be called during Hw pipe cleanup.
- * @ctx: Pointer to SSPP driver context returned by sde_hw_sspp_init
- */
-void sde_hw_sspp_destroy(struct sde_hw_pipe *ctx);
-
-#endif /*_SDE_HW_SSPP_H */
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.c b/drivers/gpu/drm/msm/sde/sde_hw_wb.c
deleted file mode 100644
index 9ed3f8586fd1..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_wb.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_wb.h"
-
-static struct sde_wb_cfg *_wb_offset(enum sde_wb wb,
- struct sde_mdss_cfg *m,
- void __iomem *addr,
- struct sde_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->wb_count; i++) {
- if (wb == m->wb[i].id) {
- b->base_off = addr;
- b->blk_off = m->wb[i].base;
- b->hwversion = m->hwversion;
- return &m->wb[i];
- }
- }
- return ERR_PTR(-EINVAL);
-}
-
-static void sde_hw_wb_setup_csc_8bit(struct sde_hw_wb *ctx,
- struct sde_csc_cfg *data)
-{
-}
-
-static void sde_hw_wb_setup_outaddress(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-
-static void sde_hw_wb_setup_format(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-
-static void sde_hw_wb_setup_rotator(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-
-static void sde_hw_setup_dither(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-
-static void sde_hw_wb_setup_cdwn(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-static void sde_hw_wb_traffic_shaper(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *data)
-{
-}
-
-static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
- unsigned long features)
-{
- if (test_bit(SDE_WB_CSC, &features))
- ops->setup_csc_data = sde_hw_wb_setup_csc_8bit;
-
- ops->setup_outaddress = sde_hw_wb_setup_outaddress;
- ops->setup_outformat = sde_hw_wb_setup_format;
-
- if (test_bit(SDE_WB_BLOCK_MODE, &features))
- ops->setup_rotator = sde_hw_wb_setup_rotator;
-
- if (test_bit(SDE_WB_DITHER, &features))
- ops->setup_dither = sde_hw_setup_dither;
-
- if (test_bit(SDE_WB_CHROMA_DOWN, &features))
- ops->setup_cdwn = sde_hw_wb_setup_cdwn;
-
- if (test_bit(SDE_WB_TRAFFIC_SHAPER, &features))
- ops->setup_trafficshaper = sde_hw_wb_traffic_shaper;
-}
-
-struct sde_hw_wb *sde_hw_wb_init(enum sde_wb idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m)
-{
- struct sde_hw_wb *c;
- struct sde_wb_cfg *cfg;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _wb_offset(idx, m, addr, &c->hw);
- if (!cfg) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- /* Assign ops */
- c->idx = idx;
- c->caps = cfg;
- _setup_wb_ops(&c->ops, c->caps->features);
-
- /*
- * Perform any default initialization for the chroma down module
- */
-
- return c;
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.h b/drivers/gpu/drm/msm/sde/sde_hw_wb.h
deleted file mode 100644
index 32e2ee87ef7f..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_wb.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HW_WB_H
-#define _SDE_HW_WB_H
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_mdp_util.h"
-
-struct sde_hw_wb;
-
-struct sde_hw_wb_cfg {
- struct sde_hw_source_info dest;
-};
-
-/**
- *
- * struct sde_hw_wb_ops : Interface to the wb Hw driver functions
- * Assumption is these functions will be called after clocks are enabled
- */
-struct sde_hw_wb_ops {
- void (*setup_csc_data)(struct sde_hw_wb *ctx,
- struct sde_csc_cfg *data);
-
- void (*setup_outaddress)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-
- void (*setup_outformat)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-
- void (*setup_rotator)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-
- void (*setup_dither)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-
- void (*setup_cdwn)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-
- void (*setup_trafficshaper)(struct sde_hw_wb *ctx,
- struct sde_hw_wb_cfg *wb);
-};
-
-/**
- * struct sde_hw_wb : WB driver object
- * @struct sde_hw_blk_reg_map *hw;
- * @idx
- * @wb_hw_caps
- * @mixer_hw_caps
- * @ops
- */
-struct sde_hw_wb {
- /* base */
- struct sde_hw_blk_reg_map hw;
-
- /* wb path */
- int idx;
- const struct sde_wb_cfg *caps;
-
- /* ops */
- struct sde_hw_wb_ops ops;
-};
-
-/**
- * sde_hw_wb_init(): Initializes the wb_path hw driver object.
- * should be called before accessing every mixer.
- * @idx: wb_path index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- */
-struct sde_hw_wb *sde_hw_wb_init(enum sde_wb idx,
- void __iomem *addr,
- struct sde_mdss_cfg *m);
-
-#endif /*_SDE_HW_WB_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hwio.h b/drivers/gpu/drm/msm/sde/sde_hwio.h
deleted file mode 100644
index 2531463b654e..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_hwio.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_HWIO_H
-#define _SDE_HWIO_H
-
-#include "sde_hw_mdp_util.h"
-
-/**
- * MDP TOP block Register and bit fields and defines
- */
-#define DISP_INTF_SEL 0x004
-#define INTR_EN 0x010
-#define INTR_STATUS 0x014
-#define INTR_CLEAR 0x018
-#define INTR2_EN 0x008
-#define INTR2_STATUS 0x00c
-#define INTR2_CLEAR 0x02c
-#define HIST_INTR_EN 0x01c
-#define HIST_INTR_STATUS 0x020
-#define HIST_INTR_CLEAR 0x024
-#define INTF_INTR_EN 0x1C0
-#define INTF_INTR_STATUS 0x1C4
-#define INTF_INTR_CLEAR 0x1C8
-#define SPLIT_DISPLAY_EN 0x2F4
-#define SPLIT_DISPLAY_UPPER_PIPE_CTRL 0x2F8
-#define DSPP_IGC_COLOR0_RAM_LUTN 0x300
-#define DSPP_IGC_COLOR1_RAM_LUTN 0x304
-#define DSPP_IGC_COLOR2_RAM_LUTN 0x308
-#define PPB0_CNTL 0x330
-#define PPB0_CONFIG 0x334
-#define PPB1_CNTL 0x338
-#define PPB1_CONFIG 0x33C
-#define HW_EVENTS_CTL 0x37C
-#define CLK_CTRL3 0x3A8
-#define CLK_STATUS3 0x3AC
-#define CLK_CTRL4 0x3B0
-#define CLK_STATUS4 0x3B4
-#define CLK_CTRL5 0x3B8
-#define CLK_STATUS5 0x3BC
-#define CLK_CTRL7 0x3D0
-#define CLK_STATUS7 0x3D4
-#define SPLIT_DISPLAY_LOWER_PIPE_CTRL 0x3F0
-#define SPLIT_DISPLAY_TE_LINE_INTERVAL 0x3F4
-#define INTF_SW_RESET_MASK 0x3FC
-#define MDP_OUT_CTL_0 0x410
-#define MDP_VSYNC_SEL 0x414
-#define DCE_SEL 0x450
-
-#endif /*_SDE_HWIO_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_irq.c b/drivers/gpu/drm/msm/sde/sde_irq.c
deleted file mode 100644
index 722845df3d0b..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_irq.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/kthread.h>
-
-#include "msm_drv.h"
-#include "sde_kms.h"
-
-static void sde_irq_callback_handler(void *arg, int irq_idx)
-{
- struct sde_kms *sde_kms = arg;
- struct sde_irq *irq_obj = &sde_kms->irq_obj;
-
- /*
- * Perform registered function callback
- */
- if (irq_obj->irq_cb_tbl && irq_obj->irq_cb_tbl[irq_idx].func)
- irq_obj->irq_cb_tbl[irq_idx].func(
- irq_obj->irq_cb_tbl[irq_idx].arg,
- irq_idx);
-
- /*
- * Clear pending interrupt status in HW.
- * NOTE: sde_irq_callback_handler is protected by top-level
- * spinlock, so it is safe to clear any interrupt status here.
- */
- sde_kms->hw_intr->ops.clear_interrupt_status(
- sde_kms->hw_intr,
- irq_idx);
-}
-
-static void sde_irq_intf_error_handler(void *arg, int irq_idx)
-{
- DRM_ERROR("INTF underrun detected, irq_idx=%d\n", irq_idx);
-}
-
-void sde_set_irqmask(struct sde_kms *sde_kms, uint32_t reg, uint32_t irqmask)
-{
- if (!sde_kms || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.set_mask)
- return;
-
- sde_kms->hw_intr->ops.set_mask(sde_kms->hw_intr, reg, irqmask);
-}
-
-int sde_irq_idx_lookup(struct sde_kms *sde_kms, enum sde_intr_type intr_type,
- u32 instance_idx)
-{
- if (!sde_kms || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.irq_idx_lookup)
- return -EINVAL;
-
- return sde_kms->hw_intr->ops.irq_idx_lookup(intr_type,
- instance_idx);
-}
-
-int sde_enable_irq(struct sde_kms *sde_kms, int *irq_idxs, u32 irq_count)
-{
- int i;
- int ret = 0;
-
- if (!sde_kms || !irq_idxs || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.enable_irq)
- return -EINVAL;
-
- for (i = 0; i < irq_count; i++) {
- ret = sde_kms->hw_intr->ops.enable_irq(
- sde_kms->hw_intr,
- irq_idxs[i]);
- if (ret) {
- DRM_ERROR("Fail to enable IRQ for irq_idx:%d\n",
- irq_idxs[i]);
- return ret;
- }
- }
-
- return ret;
-}
-
-int sde_disable_irq(struct sde_kms *sde_kms, int *irq_idxs, u32 irq_count)
-{
- int i;
- int ret = 0;
-
- if (!sde_kms || !irq_idxs || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.disable_irq)
- return -EINVAL;
-
- for (i = 0; i < irq_count; i++) {
- ret = sde_kms->hw_intr->ops.disable_irq(
- sde_kms->hw_intr,
- irq_idxs[i]);
- if (ret) {
- DRM_ERROR("Fail to disable IRQ for irq_idx:%d\n",
- irq_idxs[i]);
- return ret;
- }
- }
-
- return ret;
-}
-
-int sde_register_irq_callback(struct sde_kms *sde_kms, int irq_idx,
- struct sde_irq_callback *register_irq_cb)
-{
- struct sde_irq_callback *irq_cb_tbl;
- unsigned long irq_flags;
-
- /*
- * We allow NULL register_irq_cb as input for callback registration
- */
- if (!sde_kms || !sde_kms->irq_obj.irq_cb_tbl)
- return -EINVAL;
-
- if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
- DRM_ERROR("invalid IRQ index: [%d]\n", irq_idx);
- return -EINVAL;
- }
-
- irq_cb_tbl = sde_kms->irq_obj.irq_cb_tbl;
- spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
- irq_cb_tbl[irq_idx].func = register_irq_cb ?
- register_irq_cb->func : NULL;
- irq_cb_tbl[irq_idx].arg = register_irq_cb ?
- register_irq_cb->arg : NULL;
- spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags);
-
- return 0;
-}
-
-void sde_clear_all_irqs(struct sde_kms *sde_kms)
-{
- if (!sde_kms || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.clear_all_irqs)
- return;
-
- sde_kms->hw_intr->ops.clear_all_irqs(sde_kms->hw_intr);
-}
-
-void sde_disable_all_irqs(struct sde_kms *sde_kms)
-{
- if (!sde_kms || !sde_kms->hw_intr ||
- !sde_kms->hw_intr->ops.disable_all_irqs)
- return;
-
- sde_kms->hw_intr->ops.disable_all_irqs(sde_kms->hw_intr);
-}
-
-void sde_irq_preinstall(struct msm_kms *kms)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
-
- sde_enable(sde_kms);
- sde_clear_all_irqs(sde_kms);
- sde_disable_all_irqs(sde_kms);
- sde_disable(sde_kms);
-
- spin_lock_init(&sde_kms->irq_obj.cb_lock);
-
- /* Create irq callbacks for all possible irq_idx */
- sde_kms->irq_obj.total_irqs = sde_kms->hw_intr->irq_idx_tbl_size;
- sde_kms->irq_obj.irq_cb_tbl = kcalloc(sde_kms->irq_obj.total_irqs,
- sizeof(struct sde_irq_callback), GFP_KERNEL);
- if (!sde_kms->irq_obj.irq_cb_tbl)
- DRM_ERROR("Fail to allocate memory of IRQ callback list\n");
-}
-
-int sde_irq_postinstall(struct msm_kms *kms)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- struct sde_irq_callback irq_cb;
- int irq_idx;
- int i;
-
- irq_cb.func = sde_irq_intf_error_handler;
- irq_cb.arg = sde_kms;
-
- /* Register interface underrun callback */
- sde_enable(sde_kms);
- for (i = 0; i < sde_kms->catalog->intf_count; i++) {
- irq_idx = sde_irq_idx_lookup(sde_kms,
- SDE_IRQ_TYPE_INTF_UNDER_RUN, i+INTF_0);
- sde_register_irq_callback(sde_kms, irq_idx, &irq_cb);
- sde_enable_irq(sde_kms, &irq_idx, 1);
- }
- sde_disable(sde_kms);
-
- return 0;
-}
-
-void sde_irq_uninstall(struct msm_kms *kms)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
-
- sde_enable(sde_kms);
- sde_clear_all_irqs(sde_kms);
- sde_disable_all_irqs(sde_kms);
- sde_disable(sde_kms);
-
- kfree(sde_kms->irq_obj.irq_cb_tbl);
-}
-
-static void _sde_irq_mdp_done(struct sde_kms *sde_kms)
-{
- /*
- * Read interrupt status from all sources. Interrupt status are
- * stored within hw_intr.
- * Function will also clear the interrupt status after reading.
- * Individual interrupt status bit will only get stored if it
- * is enabled.
- */
- sde_kms->hw_intr->ops.get_interrupt_statuses(sde_kms->hw_intr);
-
- /*
- * Dispatch to HW driver to handle interrupt lookup that is being
- * fired. When matching interrupt is located, HW driver will call to
- * sde_irq_callback_handler with the irq_idx from the lookup table.
- * sde_irq_callback_handler will perform the registered function
- * callback, and do the interrupt status clearing once the registered
- * callback is finished.
- */
- sde_kms->hw_intr->ops.dispatch_irqs(
- sde_kms->hw_intr,
- sde_irq_callback_handler,
- sde_kms);
-}
-
-irqreturn_t sde_irq(struct msm_kms *kms)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- u32 interrupts;
-
- sde_kms->hw_intr->ops.get_interrupt_sources(sde_kms->hw_intr,
- &interrupts);
-
- /*
- * Taking care of MDP interrupt
- */
- if (interrupts & IRQ_SOURCE_MDP) {
- interrupts &= ~IRQ_SOURCE_MDP;
- _sde_irq_mdp_done(sde_kms);
- }
-
- /*
- * Routing all other interrupts to external drivers
- */
- while (interrupts) {
- irq_hw_number_t hwirq = fls(interrupts) - 1;
-
- generic_handle_irq(irq_find_mapping(
- sde_kms->irqcontroller.domain, hwirq));
- interrupts &= ~(1 << hwirq);
- }
-
- return IRQ_HANDLED;
-}
-
-int sde_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
- return sde_crtc_vblank(crtc);
-}
-
-void sde_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
-}
-
-static void sde_hw_irq_mask(struct irq_data *irqd)
-{
- struct sde_kms *sde_kms = irq_data_get_irq_chip_data(irqd);
-
- smp_mb__before_atomic();
- clear_bit(irqd->hwirq, &sde_kms->irqcontroller.enabled_mask);
- smp_mb__after_atomic();
-}
-
-static void sde_hw_irq_unmask(struct irq_data *irqd)
-{
- struct sde_kms *sde_kms = irq_data_get_irq_chip_data(irqd);
-
- smp_mb__before_atomic();
- set_bit(irqd->hwirq, &sde_kms->irqcontroller.enabled_mask);
- smp_mb__after_atomic();
-}
-
-static struct irq_chip sde_hw_irq_chip = {
- .name = "sde",
- .irq_mask = sde_hw_irq_mask,
- .irq_unmask = sde_hw_irq_unmask,
-};
-
-static int sde_hw_irqdomain_map(struct irq_domain *d,
- unsigned int irq, irq_hw_number_t hwirq)
-{
- struct sde_kms *sde_kms = d->host_data;
- uint32_t valid_irqs;
-
- sde_kms->hw_intr->ops.get_valid_interrupts(sde_kms->hw_intr,
- &valid_irqs);
-
- if (!(valid_irqs & (1 << hwirq)))
- return -EPERM;
-
- irq_set_chip_and_handler(irq, &sde_hw_irq_chip, handle_level_irq);
- irq_set_chip_data(irq, sde_kms);
-
- return 0;
-}
-
-static struct irq_domain_ops sde_hw_irqdomain_ops = {
- .map = sde_hw_irqdomain_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
-int sde_irq_domain_init(struct sde_kms *sde_kms)
-{
- struct device *dev = sde_kms->dev->dev;
- struct irq_domain *d;
-
- d = irq_domain_add_linear(dev->of_node, 32,
- &sde_hw_irqdomain_ops, sde_kms);
-
- if (!d)
- return -ENXIO;
-
- sde_kms->irqcontroller.enabled_mask = 0;
- sde_kms->irqcontroller.domain = d;
-
- return 0;
-}
-
-int sde_irq_domain_fini(struct sde_kms *sde_kms)
-{
- if (sde_kms->irqcontroller.domain) {
- irq_domain_remove(sde_kms->irqcontroller.domain);
- sde_kms->irqcontroller.domain = NULL;
- }
- return 0;
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
deleted file mode 100644
index 7fba38b9e60d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <drm/drm_crtc.h>
-#include "msm_drv.h"
-#include "msm_mmu.h"
-#include "sde_kms.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_intf.h"
-
-static const char * const iommu_ports[] = {
- "mdp_0",
-};
-
-static const struct sde_hw_res_map res_table[INTF_MAX] = {
- { SDE_NONE, SDE_NONE, SDE_NONE, SDE_NONE},
- { INTF_0, SDE_NONE, SDE_NONE, SDE_NONE},
- { INTF_1, LM_0, PINGPONG_0, CTL_0},
- { INTF_2, LM_1, PINGPONG_1, CTL_1},
- { INTF_3, SDE_NONE, SDE_NONE, CTL_2},
-};
-
-
-#define DEFAULT_MDP_SRC_CLK 200000000
-
-int sde_disable(struct sde_kms *sde_kms)
-{
- DBG("");
-
- return 0;
-}
-
-int sde_enable(struct sde_kms *sde_kms)
-{
- DBG("");
-
- clk_prepare_enable(sde_kms->ahb_clk);
- clk_prepare_enable(sde_kms->axi_clk);
- clk_prepare_enable(sde_kms->core_clk);
- if (sde_kms->lut_clk)
- clk_prepare_enable(sde_kms->lut_clk);
-
- return 0;
-}
-
-static void sde_prepare_commit(struct msm_kms *kms,
- struct drm_atomic_state *state)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- sde_enable(sde_kms);
-}
-
-static void sde_complete_commit(struct msm_kms *kms,
- struct drm_atomic_state *state)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- sde_disable(sde_kms);
-}
-
-static void sde_wait_for_crtc_commit_done(struct msm_kms *kms,
- struct drm_crtc *crtc)
-{
- sde_crtc_wait_for_commit_done(crtc);
-}
-static int modeset_init(struct sde_kms *sde_kms)
-{
- struct msm_drm_private *priv = sde_kms->dev->dev_private;
- int i;
- int ret;
- struct sde_mdss_cfg *catalog = sde_kms->catalog;
- struct drm_device *dev = sde_kms->dev;
- struct drm_plane *primary_planes[MAX_PLANES];
- int primary_planes_idx = 0;
-
- int num_private_planes = catalog->mixer_count;
-
- ret = sde_irq_domain_init(sde_kms);
- if (ret)
- goto fail;
-
- /* Create the planes */
- for (i = 0; i < catalog->sspp_count; i++) {
- struct drm_plane *plane;
- bool primary = true;
-
- if (catalog->sspp[i].features & BIT(SDE_SSPP_CURSOR)
- || !num_private_planes)
- primary = false;
-
- plane = sde_plane_init(dev, catalog->sspp[i].id, primary);
- if (IS_ERR(plane)) {
- pr_err("%s: sde_plane_init failed", __func__);
- ret = PTR_ERR(plane);
- goto fail;
- }
- priv->planes[priv->num_planes++] = plane;
-
- if (primary)
- primary_planes[primary_planes_idx++] = plane;
- if (primary && num_private_planes)
- num_private_planes--;
- }
-
- /* Need enough primary planes to assign one per mixer (CRTC) */
- if (primary_planes_idx < catalog->mixer_count) {
- ret = -EINVAL;
- goto fail;
- }
-
- /*
- * Enumerate displays supported
- */
- sde_encoders_init(dev);
-
- /* Create one CRTC per display */
- for (i = 0; i < priv->num_encoders; i++) {
- /*
- * Each CRTC receives a private plane. We start
- * with first RGB, and then DMA and then VIG.
- */
- struct drm_crtc *crtc;
-
- crtc = sde_crtc_init(dev, priv->encoders[i],
- primary_planes[i], i);
- if (IS_ERR(crtc)) {
- ret = PTR_ERR(crtc);
- goto fail;
- }
- priv->crtcs[priv->num_crtcs++] = crtc;
- }
-
- /*
- * Iterate through the list of encoders and
- * set the possible CRTCs
- */
- for (i = 0; i < priv->num_encoders; i++)
- priv->encoders[i]->possible_crtcs = (1 << priv->num_crtcs) - 1;
-
- return 0;
-fail:
- return ret;
-}
-
-static int sde_hw_init(struct msm_kms *kms)
-{
- return 0;
-}
-
-static long sde_round_pixclk(struct msm_kms *kms, unsigned long rate,
- struct drm_encoder *encoder)
-{
- return rate;
-}
-
-static void sde_preclose(struct msm_kms *kms, struct drm_file *file)
-{
-}
-
-static void sde_destroy(struct msm_kms *kms)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
-
- sde_irq_domain_fini(sde_kms);
- sde_hw_intr_destroy(sde_kms->hw_intr);
- kfree(sde_kms);
-}
-
-static const struct msm_kms_funcs kms_funcs = {
- .hw_init = sde_hw_init,
- .irq_preinstall = sde_irq_preinstall,
- .irq_postinstall = sde_irq_postinstall,
- .irq_uninstall = sde_irq_uninstall,
- .irq = sde_irq,
- .prepare_commit = sde_prepare_commit,
- .complete_commit = sde_complete_commit,
- .wait_for_crtc_commit_done = sde_wait_for_crtc_commit_done,
- .enable_vblank = sde_enable_vblank,
- .disable_vblank = sde_disable_vblank,
- .get_format = mdp_get_format,
- .round_pixclk = sde_round_pixclk,
- .preclose = sde_preclose,
- .destroy = sde_destroy,
-};
-
-static int get_clk(struct platform_device *pdev, struct clk **clkp,
- const char *name, bool mandatory)
-{
- struct device *dev = &pdev->dev;
- struct clk *clk = devm_clk_get(dev, name);
-
- if (IS_ERR(clk) && mandatory) {
- dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk));
- return PTR_ERR(clk);
- }
- if (IS_ERR(clk))
- DBG("skipping %s", name);
- else
- *clkp = clk;
-
- return 0;
-}
-
-struct sde_kms *sde_hw_setup(struct platform_device *pdev)
-{
- struct sde_kms *sde_kms;
- struct msm_kms *kms = NULL;
- int ret;
-
- sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
- if (!sde_kms)
- return NULL;
-
- msm_kms_init(&sde_kms->base, &kms_funcs);
-
- kms = &sde_kms->base;
-
- sde_kms->mmio = msm_ioremap(pdev, "mdp_phys", "SDE");
- if (IS_ERR(sde_kms->mmio)) {
- ret = PTR_ERR(sde_kms->mmio);
- goto fail;
- }
- pr_err("Mapped Mdp address space @%pK", sde_kms->mmio);
-
- sde_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
- if (IS_ERR(sde_kms->vbif)) {
- ret = PTR_ERR(sde_kms->vbif);
- goto fail;
- }
-
- sde_kms->venus = devm_regulator_get_optional(&pdev->dev, "gdsc-venus");
- if (IS_ERR(sde_kms->venus)) {
- ret = PTR_ERR(sde_kms->venus);
- DBG("failed to get Venus GDSC regulator: %d\n", ret);
- sde_kms->venus = NULL;
- }
-
- if (sde_kms->venus) {
- ret = regulator_enable(sde_kms->venus);
- if (ret) {
- DBG("failed to enable venus GDSC: %d\n", ret);
- goto fail;
- }
- }
-
- sde_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
- if (IS_ERR(sde_kms->vdd)) {
- ret = PTR_ERR(sde_kms->vdd);
- goto fail;
- }
-
- ret = regulator_enable(sde_kms->vdd);
- if (ret) {
- DBG("failed to enable regulator vdd: %d\n", ret);
- goto fail;
- }
-
- sde_kms->mmagic = devm_regulator_get_optional(&pdev->dev, "mmagic");
- if (IS_ERR(sde_kms->mmagic)) {
- ret = PTR_ERR(sde_kms->mmagic);
- DBG("failed to get mmagic GDSC regulator: %d\n", ret);
- sde_kms->mmagic = NULL;
- }
-
- /* mandatory clocks: */
- ret = get_clk(pdev, &sde_kms->axi_clk, "bus_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->ahb_clk, "iface_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->src_clk, "core_clk_src", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->core_clk, "core_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->vsync_clk, "vsync_clk", true);
- if (ret)
- goto fail;
-
- /* optional clocks: */
- get_clk(pdev, &sde_kms->lut_clk, "lut_clk", false);
- get_clk(pdev, &sde_kms->mmagic_clk, "mmagic_clk", false);
- get_clk(pdev, &sde_kms->iommu_clk, "iommu_clk", false);
-
- if (sde_kms->mmagic) {
- ret = regulator_enable(sde_kms->mmagic);
- if (ret) {
- dev_err(sde_kms->dev->dev,
- "failed to enable mmagic GDSC: %d\n", ret);
- goto fail;
- }
- }
- if (sde_kms->mmagic_clk) {
- clk_prepare_enable(sde_kms->mmagic_clk);
- if (ret) {
- dev_err(sde_kms->dev->dev, "failed to enable mmagic_clk\n");
- goto undo_gdsc;
- }
- }
-
- return sde_kms;
-
-undo_gdsc:
- if (sde_kms->mmagic)
- regulator_disable(sde_kms->mmagic);
-fail:
- if (kms)
- sde_destroy(kms);
-
- return ERR_PTR(ret);
-}
-
-static int sde_translation_ctrl_pwr(struct sde_kms *sde_kms, bool on)
-{
- struct device *dev = sde_kms->dev->dev;
- int ret;
-
- if (on) {
- if (sde_kms->iommu_clk) {
- ret = clk_prepare_enable(sde_kms->iommu_clk);
- if (ret) {
- dev_err(dev, "failed to enable iommu_clk\n");
- goto undo_mmagic_clk;
- }
- }
- } else {
- if (sde_kms->iommu_clk)
- clk_disable_unprepare(sde_kms->iommu_clk);
- if (sde_kms->mmagic_clk)
- clk_disable_unprepare(sde_kms->mmagic_clk);
- if (sde_kms->mmagic)
- regulator_disable(sde_kms->mmagic);
- }
-
- return 0;
-
-undo_mmagic_clk:
- if (sde_kms->mmagic_clk)
- clk_disable_unprepare(sde_kms->mmagic_clk);
-
- return ret;
-}
-int sde_mmu_init(struct sde_kms *sde_kms)
-{
- struct sde_mdss_cfg *catalog = sde_kms->catalog;
- struct sde_hw_intf *intf = NULL;
- struct iommu_domain *iommu;
- struct msm_mmu *mmu;
- int i, ret;
-
- /*
- * Make sure things are off before attaching iommu (bootloader could
- * have left things on, in which case we'll start getting faults if
- * we don't disable):
- */
- sde_enable(sde_kms);
- for (i = 0; i < catalog->intf_count; i++) {
- intf = sde_hw_intf_init(catalog->intf[i].id,
- sde_kms->mmio,
- catalog);
- if (!IS_ERR_OR_NULL(intf)) {
- intf->ops.enable_timing(intf, 0x0);
- sde_hw_intf_deinit(intf);
- }
- }
- sde_disable(sde_kms);
- msleep(20);
-
- iommu = iommu_domain_alloc(&platform_bus_type);
-
- if (!IS_ERR_OR_NULL(iommu)) {
- mmu = msm_smmu_new(sde_kms->dev->dev, MSM_SMMU_DOMAIN_UNSECURE);
- if (IS_ERR(mmu)) {
- ret = PTR_ERR(mmu);
- dev_err(sde_kms->dev->dev,
- "failed to init iommu: %d\n", ret);
- iommu_domain_free(iommu);
- goto fail;
- }
-
- ret = sde_translation_ctrl_pwr(sde_kms, true);
- if (ret) {
- dev_err(sde_kms->dev->dev,
- "failed to power iommu: %d\n", ret);
- mmu->funcs->destroy(mmu);
- goto fail;
- }
-
- ret = mmu->funcs->attach(mmu, (const char **)iommu_ports,
- ARRAY_SIZE(iommu_ports));
- if (ret) {
- dev_err(sde_kms->dev->dev,
- "failed to attach iommu: %d\n", ret);
- mmu->funcs->destroy(mmu);
- goto fail;
- }
- } else {
- dev_info(sde_kms->dev->dev,
- "no iommu, fallback to phys contig buffers for scanout\n");
- mmu = NULL;
- }
- sde_kms->mmu = mmu;
-
- sde_kms->mmu_id = msm_register_mmu(sde_kms->dev, mmu);
- if (sde_kms->mmu_id < 0) {
- ret = sde_kms->mmu_id;
- dev_err(sde_kms->dev->dev,
- "failed to register sde iommu: %d\n", ret);
- goto fail;
- }
-
- return 0;
-fail:
- return ret;
-
-}
-
-struct msm_kms *sde_kms_init(struct drm_device *dev)
-{
- struct platform_device *pdev = dev->platformdev;
- struct sde_mdss_cfg *catalog;
- struct sde_kms *sde_kms;
- struct msm_kms *msm_kms;
- int ret = 0;
-
- sde_kms = sde_hw_setup(pdev);
- if (IS_ERR(sde_kms)) {
- ret = PTR_ERR(sde_kms);
- goto fail;
- }
-
- sde_kms->dev = dev;
- msm_kms = &sde_kms->base;
-
- /*
- * Currently hardcoding to MDSS version 1.7.0 (8996)
- */
- catalog = sde_hw_catalog_init(1, 7, 0);
- if (!catalog)
- goto fail;
-
- sde_kms->catalog = catalog;
-
- /* we need to set a default rate before enabling.
- * Set a safe rate first, before initializing catalog
- * later set more optimal rate based on bandwdith/clock
- * requirements
- */
-
- clk_set_rate(sde_kms->src_clk, DEFAULT_MDP_SRC_CLK);
- sde_enable(sde_kms);
- sde_kms->hw_res.res_table = res_table;
-
- /*
- * Now we need to read the HW catalog and initialize resources such as
- * clocks, regulators, GDSC/MMAGIC, ioremap the register ranges etc
- */
- sde_mmu_init(sde_kms);
-
- /*
- * modeset_init should create the DRM related objects i.e. CRTCs,
- * planes, encoders, connectors and so forth
- */
- modeset_init(sde_kms);
-
- dev->mode_config.min_width = 0;
- dev->mode_config.min_height = 0;
-
- /*
- * we can assume the max crtc width is equal to the max supported
- * by LM_0
- * Also fixing the max height to 4k
- */
- dev->mode_config.max_width = catalog->mixer[0].sblk->maxwidth;
- dev->mode_config.max_height = 4096;
-
- sde_kms->hw_intr = sde_rm_acquire_intr(sde_kms);
-
- if (IS_ERR_OR_NULL(sde_kms->hw_intr))
- goto fail;
-
- return msm_kms;
-
-fail:
- if (msm_kms)
- sde_destroy(msm_kms);
-
- return ERR_PTR(ret);
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
deleted file mode 100644
index 7ac1b6b827bc..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __SDE_KMS_H__
-#define __SDE_KMS_H__
-
-#include "msm_drv.h"
-#include "msm_kms.h"
-#include "mdp/mdp_kms.h"
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdp_ctl.h"
-#include "sde_hw_lm.h"
-#include "sde_hw_interrupts.h"
-
-/*
- * struct sde_irq_callback - IRQ callback handlers
- * @func: intr handler
- * @arg: argument for the handler
- */
-struct sde_irq_callback {
- void (*func)(void *arg, int irq_idx);
- void *arg;
-};
-
-/**
- * struct sde_irq: IRQ structure contains callback registration info
- * @total_irq: total number of irq_idx obtained from HW interrupts mapping
- * @irq_cb_tbl: array of IRQ callbacks setting
- * @cb_lock: callback lock
- */
-struct sde_irq {
- u32 total_irqs;
- struct sde_irq_callback *irq_cb_tbl;
- spinlock_t cb_lock;
-};
-
-/**
- * struct sde_hw_res_map : Default resource table identifying default
- * hw resource map. Primarily used for forcing DSI to use CTL_0/1
- * and Pingpong 0/1, if the field is set to SDE_NONE means any HW
- * intstance for that tpye is allowed as long as it is unused.
- */
-struct sde_hw_res_map {
- enum sde_intf intf;
- enum sde_lm lm;
- enum sde_pingpong pp;
- enum sde_ctl ctl;
-};
-
-/* struct sde_hw_resource_manager : Resource mananger maintains the current
- * platform configuration and manages shared
- * hw resources ex:ctl_path hw driver context
- * is needed by CRTCs/PLANEs/ENCODERs
- * @ctl : table of control path hw driver contexts allocated
- * @mixer : list of mixer hw drivers contexts allocated
- * @intr : pointer to hw interrupt context
- * @res_table : pointer to default hw_res table for this platform
- * @feature_map :BIT map for default enabled features ex:specifies if PP_SPLIT
- * is enabled/disabled by defalt for this platform
- */
-struct sde_hw_resource_manager {
- struct sde_hw_ctl *ctl[CTL_MAX];
- struct sde_hw_mixer *mixer[LM_MAX];
- struct sde_hw_intr *intr;
- const struct sde_hw_res_map *res_table;
- bool feature_map;
-};
-
-struct sde_kms {
- struct msm_kms base;
- struct drm_device *dev;
- int rev;
- struct sde_mdss_cfg *catalog;
-
- struct msm_mmu *mmu;
- int mmu_id;
-
- /* io/register spaces: */
- void __iomem *mmio, *vbif;
-
- struct regulator *vdd;
- struct regulator *mmagic;
- struct regulator *venus;
-
- struct clk *axi_clk;
- struct clk *ahb_clk;
- struct clk *src_clk;
- struct clk *core_clk;
- struct clk *lut_clk;
- struct clk *mmagic_clk;
- struct clk *iommu_clk;
- struct clk *vsync_clk;
-
- struct {
- unsigned long enabled_mask;
- struct irq_domain *domain;
- } irqcontroller;
-
- struct sde_hw_intr *hw_intr;
- struct sde_irq irq_obj;
- struct sde_hw_resource_manager hw_res;
-};
-
-struct vsync_info {
- u32 frame_count;
- u32 line_count;
-};
-
-#define to_sde_kms(x) container_of(x, struct sde_kms, base)
-
-struct sde_plane_state {
- struct drm_plane_state base;
-
- /* aligned with property */
- uint8_t premultiplied;
- uint8_t zpos;
- uint8_t alpha;
-
- /* assigned by crtc blender */
- enum sde_stage stage;
-
- /* some additional transactional status to help us know in the
- * apply path whether we need to update SMP allocation, and
- * whether current update is still pending:
- */
- bool mode_changed : 1;
- bool pending : 1;
-};
-
-#define to_sde_plane_state(x) \
- container_of(x, struct sde_plane_state, base)
-
-int sde_disable(struct sde_kms *sde_kms);
-int sde_enable(struct sde_kms *sde_kms);
-
-/**
- * HW resource manager functions
- * @sde_rm_acquire_ctl_path : Allocates control path
- * @sde_rm_get_ctl_path : returns control path driver context for already
- * acquired ctl path
- * @sde_rm_release_ctl_path : Frees control path driver context
- * @sde_rm_acquire_mixer : Allocates mixer hw driver context
- * @sde_rm_get_mixer : returns mixer context for already
- * acquired mixer
- * @sde_rm_release_mixer : Frees mixer hw driver context
- * @sde_rm_get_hw_res_map : Returns map for the passed INTF
- */
-struct sde_hw_ctl *sde_rm_acquire_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-struct sde_hw_ctl *sde_rm_get_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-void sde_rm_release_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-struct sde_hw_mixer *sde_rm_acquire_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-struct sde_hw_mixer *sde_rm_get_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-void sde_rm_release_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-struct sde_hw_intr *sde_rm_acquire_intr(struct sde_kms *sde_kms);
-struct sde_hw_intr *sde_rm_get_intr(struct sde_kms *sde_kms);
-
-const struct sde_hw_res_map *sde_rm_get_res_map(struct sde_kms *sde_kms,
- enum sde_intf idx);
-
-/**
- * IRQ functions
- */
-int sde_irq_domain_init(struct sde_kms *sde_kms);
-int sde_irq_domain_fini(struct sde_kms *sde_kms);
-void sde_irq_preinstall(struct msm_kms *kms);
-int sde_irq_postinstall(struct msm_kms *kms);
-void sde_irq_uninstall(struct msm_kms *kms);
-irqreturn_t sde_irq(struct msm_kms *kms);
-
-/**
- * sde_set_irqmask - IRQ helper function for writing IRQ mask
- * to SDE HW interrupt register.
- * @sde_kms: SDE handle
- * @reg_off: SDE HW interrupt register offset
- * @irqmask: IRQ mask
- */
-void sde_set_irqmask(
- struct sde_kms *sde_kms,
- uint32_t reg_off,
- uint32_t irqmask);
-
-/**
- * sde_irq_idx_lookup - IRQ helper function for lookup irq_idx from HW
- * interrupt mapping table.
- * @sde_kms: SDE handle
- * @intr_type: SDE HW interrupt type for lookup
- * @instance_idx: SDE HW block instance defined in sde_hw_mdss.h
- * @return: irq_idx or -EINVAL when fail to lookup
- */
-int sde_irq_idx_lookup(
- struct sde_kms *sde_kms,
- enum sde_intr_type intr_type,
- uint32_t instance_idx);
-
-/**
- * sde_enable_irq - IRQ helper function for enabling one or more IRQs
- * @sde_kms: SDE handle
- * @irq_idxs: Array of irq index
- * @irq_count: Number of irq_idx provided in the array
- * @return: 0 for success enabling IRQ, otherwise failure
- */
-int sde_enable_irq(
- struct sde_kms *sde_kms,
- int *irq_idxs,
- uint32_t irq_count);
-
-/**
- * sde_disable_irq - IRQ helper function for diabling one of more IRQs
- * @sde_kms: SDE handle
- * @irq_idxs: Array of irq index
- * @irq_count: Number of irq_idx provided in the array
- * @return: 0 for success disabling IRQ, otherwise failure
- */
-int sde_disable_irq(
- struct sde_kms *sde_kms,
- int *irq_idxs,
- uint32_t irq_count);
-
-/**
- * sde_register_irq_callback - For registering callback function on IRQ
- * interrupt
- * @sde_kms: SDE handle
- * @irq_idx: irq index
- * @irq_cb: IRQ callback structure, containing callback function
- * and argument. Passing NULL for irq_cb will unregister
- * the callback for the given irq_idx
- * @return: 0 for success registering callback, otherwise failure
- */
-int sde_register_irq_callback(
- struct sde_kms *sde_kms,
- int irq_idx,
- struct sde_irq_callback *irq_cb);
-
-/**
- * sde_clear_all_irqs - Clearing all SDE IRQ interrupt status
- * @sde_kms: SDE handle
- */
-void sde_clear_all_irqs(struct sde_kms *sde_kms);
-
-/**
- * sde_disable_all_irqs - Diabling all SDE IRQ interrupt
- * @sde_kms: SDE handle
- */
-void sde_disable_all_irqs(struct sde_kms *sde_kms);
-
-/**
- * Vblank enable/disable functions
- */
-int sde_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-void sde_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-
-/**
- * Plane functions
- */
-enum sde_sspp sde_plane_pipe(struct drm_plane *plane);
-struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe,
- bool private_plane);
-
-/**
- * CRTC functions
- */
-uint32_t sde_crtc_vblank(struct drm_crtc *crtc);
-void sde_crtc_wait_for_commit_done(struct drm_crtc *crtc);
-void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
-struct drm_crtc *sde_crtc_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- struct drm_plane *plane, int id);
-
-/**
- * Encoder functions and data types
- */
-struct sde_encoder_hw_resources {
- enum sde_intf_mode intfs[INTF_MAX];
- bool pingpongs[PINGPONG_MAX];
- bool ctls[CTL_MAX];
- bool pingpongsplit;
-};
-
-void sde_encoder_get_hw_resources(struct drm_encoder *encoder,
- struct sde_encoder_hw_resources *hw_res);
-void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
- void (*cb)(void *), void *data);
-void sde_encoders_init(struct drm_device *dev);
-void sde_encoder_get_vsync_info(struct drm_encoder *encoder,
- struct vsync_info *vsync);
-
-
-
-#endif /* __sde_kms_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
deleted file mode 100644
index 9d6f28cfc06c..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_kms.h"
-#include "sde_hw_lm.h"
-#include "sde_hw_mdp_ctl.h"
-
-struct sde_hw_intr *sde_rm_acquire_intr(struct sde_kms *sde_kms)
-{
- struct sde_hw_intr *hw_intr;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.intr) {
- DRM_ERROR("intr already in use ");
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- hw_intr = sde_hw_intr_init(sde_kms->mmio,
- sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(hw_intr))
- sde_kms->hw_res.intr = hw_intr;
-
- return hw_intr;
-}
-
-struct sde_hw_intr *sde_rm_get_intr(struct sde_kms *sde_kms)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.intr;
-}
-
-struct sde_hw_ctl *sde_rm_acquire_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx)
-{
- struct sde_hw_ctl *hw_ctl;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl Path Idx %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.ctl[idx]) {
- DRM_ERROR("CTL path %d already in use ", idx);
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- hw_ctl = sde_hw_ctl_init(idx, sde_kms->mmio, sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(hw_ctl))
- sde_kms->hw_res.ctl[idx] = hw_ctl;
-
- return hw_ctl;
-}
-
-struct sde_hw_ctl *sde_rm_get_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl path Idx %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.ctl[idx];
-}
-
-void sde_rm_release_ctl_path(struct sde_kms *sde_kms, enum sde_ctl idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid pointer\n");
- return;
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl path Idx %d", idx);
- return;
- }
-}
-
-struct sde_hw_mixer *sde_rm_acquire_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx)
-{
- struct sde_hw_mixer *mixer;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
- DBG("Invalid mixer id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.mixer[idx]) {
- DRM_ERROR("mixer %d already in use ", idx);
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- mixer = sde_hw_lm_init(idx, sde_kms->mmio, sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(mixer))
- sde_kms->hw_res.mixer[idx] = mixer;
-
- return mixer;
-}
-
-struct sde_hw_mixer *sde_rm_get_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
- DRM_ERROR("Invalid mixer id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.mixer[idx];
-}
-
-const struct sde_hw_res_map *sde_rm_get_res_map(struct sde_kms *sde_kms,
- enum sde_intf idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->intf_count)) {
- DRM_ERROR("Invalid intf id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- DBG(" Platform Resource map for INTF %d -> lm %d, pp %d ctl %d",
- sde_kms->hw_res.res_table[idx].intf,
- sde_kms->hw_res.res_table[idx].lm,
- sde_kms->hw_res.res_table[idx].pp,
- sde_kms->hw_res.res_table[idx].ctl);
- return &(sde_kms->hw_res.res_table[idx]);
-}
diff --git a/drivers/gpu/drm/msm/sde/sde_mdp_formats.c b/drivers/gpu/drm/msm/sde/sde_mdp_formats.c
deleted file mode 100644
index 56b65d4bd45e..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_mdp_formats.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include "sde_mdp_formats.h"
-
-static struct sde_mdp_format_params sde_mdp_format_map[] = {
- INTERLEAVED_RGB_FMT(ARGB8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA,
- true, 4, 0),
-
- INTERLEAVED_RGB_FMT(ABGR8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA,
- true, 4, 0),
-
- INTERLEAVED_RGB_FMT(RGBA8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr,
- true, 4, 0),
-
- INTERLEAVED_RGB_FMT(BGRA8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb,
- true, 4, 0),
-
- INTERLEAVED_RGB_FMT(XRGB8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA,
- true, 4, 0),
-
- INTERLEAVED_RGB_FMT(RGB888,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, 0,
- false, 3, 0),
-
- INTERLEAVED_RGB_FMT(BGR888,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, 0,
- false, 3, 0),
-
- INTERLEAVED_RGB_FMT(RGB565,
- 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, 0,
- false, 2, 0),
-
- INTERLEAVED_RGB_FMT(BGR565,
- 0, 5, 6, 5,
- C2_R_Cr, C0_G_Y, C1_B_Cb, 0,
- false, 2, 0),
-
- PSEDUO_YUV_FMT(NV12,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- SDE_MDP_CHROMA_420, 0),
-
- PSEDUO_YUV_FMT(NV21,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C1_B_Cb,
- SDE_MDP_CHROMA_420, 0),
-
- PSEDUO_YUV_FMT(NV16,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- SDE_MDP_CHROMA_H2V1, 0),
-
- PSEDUO_YUV_FMT(NV61,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C1_B_Cb,
- SDE_MDP_CHROMA_H2V1, 0),
-
- INTERLEAVED_YUV_FMT(VYUY,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
- false, SDE_MDP_CHROMA_H2V1, 4, 2,
- 0),
-
- INTERLEAVED_YUV_FMT(UYVY,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y,
- false, SDE_MDP_CHROMA_H2V1, 4, 2,
- 0),
-
- INTERLEAVED_YUV_FMT(YUYV,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
- false, SDE_MDP_CHROMA_H2V1, 4, 2,
- 0),
-
- INTERLEAVED_YUV_FMT(YVYU,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
- false, SDE_MDP_CHROMA_H2V1, 4, 2,
- 0),
-
- PLANAR_YUV_FMT(YUV420,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C1_B_Cb, C0_G_Y,
- false, SDE_MDP_CHROMA_420, 2,
- 0),
-
- PLANAR_YUV_FMT(YVU420,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr, C0_G_Y,
- false, SDE_MDP_CHROMA_420, 2,
- 0),
-};
-
-struct sde_mdp_format_params *sde_mdp_get_format_params(u32 format,
- u32 fmt_modifier)
-{
- u32 i = 0;
- struct sde_mdp_format_params *fmt = NULL;
-
- for (i = 0; i < sizeof(sde_mdp_format_map)/sizeof(*sde_mdp_format_map);
- i++)
- if (format == sde_mdp_format_map[i].format) {
- fmt = &sde_mdp_format_map[i];
- break;
- }
-
- return fmt;
-}
-
diff --git a/drivers/gpu/drm/msm/sde/sde_mdp_formats.h b/drivers/gpu/drm/msm/sde/sde_mdp_formats.h
deleted file mode 100644
index e6f1c60aad11..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_mdp_formats.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SDE_MDP_FORMATS_H
-#define _SDE_MDP_FORMATS_H
-
-#include <drm/drm_fourcc.h>
-#include "sde_hw_mdss.h"
-
-/**
- * MDP supported format packing, bpp, and other format
- * information.
- * MDP currently only supports interleaved RGB formats
- * UBWC support for a pixel format is indicated by the flag,
- * there is additional meta data plane for such formats
- */
-
-#define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, alpha, bp, flg) \
-{ \
- .format = DRM_FORMAT_ ## fmt, \
- .fetch_planes = SDE_MDP_PLANE_INTERLEAVED, \
- .alpha_enable = alpha, \
- .element = { (e0), (e1), (e2), (e3) }, \
- .bits = { a, r, g, b}, \
- .chroma_sample = SDE_MDP_CHROMA_RGB, \
- .unpack_align_msb = 0, \
- .unpack_tight = 1, \
- .unpack_count = (alpha == true) ? 4:3, \
- .bpp = bp, \
- .fetch_mode = SDE_MDP_FETCH_LINEAR, \
- .is_yuv = false, \
- .flag = flg \
-}
-
-#define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
-alpha, chroma, count, bp, flg) \
-{ \
- .format = DRM_FORMAT_ ## fmt, \
- .fetch_planes = SDE_MDP_PLANE_INTERLEAVED, \
- .alpha_enable = alpha, \
- .element = { (e0), (e1), (e2), (e3)}, \
- .bits = { a, r, g, b}, \
- .chroma_sample = chroma, \
- .unpack_align_msb = 0, \
- .unpack_tight = 1, \
- .unpack_count = count, \
- .bpp = bp, \
- .fetch_mode = SDE_MDP_FETCH_LINEAR, \
- .is_yuv = true, \
- .flag = flg \
-}
-
-#define PSEDUO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg) \
-{ \
- .format = DRM_FORMAT_ ## fmt, \
- .fetch_planes = SDE_MDP_PLANE_PSEUDO_PLANAR, \
- .alpha_enable = false, \
- .element = { (e0), (e1), 0, 0 }, \
- .bits = { a, r, g, b}, \
- .chroma_sample = chroma, \
- .unpack_align_msb = 0, \
- .unpack_tight = 1, \
- .unpack_count = 2, \
- .bpp = 2, \
- .fetch_mode = SDE_MDP_FETCH_LINEAR, \
- .is_yuv = true, \
- .flag = flg \
-}
-
-#define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, flg)\
-{ \
- .format = DRM_FORMAT_ ## fmt, \
- .fetch_planes = SDE_MDP_PLANE_INTERLEAVED, \
- .alpha_enable = alpha, \
- .element = { (e0), (e1), (e2), 0 }, \
- .bits = { a, r, g, b}, \
- .chroma_sample = chroma, \
- .unpack_align_msb = 0, \
- .unpack_tight = 1, \
- .unpack_count = 0, \
- .bpp = bp, \
- .fetch_mode = SDE_MDP_FETCH_LINEAR, \
- .is_yuv = true, \
- .flag = flg \
-}
-
-/**
- * sde_mdp_get_format_params(): Returns sde format structure pointer.
- * @format: DRM format
- * @fmt_modifier: DRM format modifier
- */
-struct sde_mdp_format_params *sde_mdp_get_format_params(u32 format,
- u32 fmt_modifier);
-
-#endif /*_SDE_MDP_FORMATS_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
deleted file mode 100644
index cf34de2f1e3d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "sde_kms.h"
-#include "sde_hwio.h"
-#include "sde_hw_mdp_ctl.h"
-#include "sde_mdp_formats.h"
-#include "sde_hw_sspp.h"
-
-#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
-#define PHASE_STEP_SHIFT 21
-#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
-#define PHASE_RESIDUAL 15
-
-#define SDE_PLANE_FEATURE_SCALER \
- (BIT(SDE_SSPP_SCALAR_QSEED2)| \
- BIT(SDE_SSPP_SCALAR_QSEED3)| \
- BIT(SDE_SSPP_SCALAR_RGB))
-
-#ifndef SDE_PLANE_DEBUG_START
-#define SDE_PLANE_DEBUG_START()
-#endif
-
-#ifndef SDE_PLANE_DEBUG_END
-#define SDE_PLANE_DEBUG_END()
-#endif
-
-struct sde_plane {
- struct drm_plane base;
- const char *name;
-
- int mmu_id;
-
- enum sde_sspp pipe;
- uint32_t features; /* capabilities from catalog */
- uint32_t flush_mask; /* used to commit pipe registers */
- uint32_t nformats;
- uint32_t formats[32];
-
- struct sde_hw_pipe *pipe_hw;
- struct sde_hw_pipe_cfg pipe_cfg;
- struct sde_hw_pixel_ext pixel_ext;
-};
-#define to_sde_plane(x) container_of(x, struct sde_plane, base)
-
-static bool sde_plane_enabled(struct drm_plane_state *state)
-{
- return state->fb && state->crtc;
-}
-
-static void sde_plane_set_scanout(struct drm_plane *plane,
- struct sde_hw_pipe_cfg *pipe_cfg, struct drm_framebuffer *fb)
-{
- struct sde_plane *psde = to_sde_plane(plane);
- int i;
-
- if (pipe_cfg && fb && psde->pipe_hw->ops.setup_sourceaddress) {
- /* stride */
- i = min_t(int, ARRAY_SIZE(fb->pitches), SDE_MAX_PLANES);
- while (i) {
- --i;
- pipe_cfg->src.ystride[i] = fb->pitches[i];
- }
-
- /* address */
- for (i = 0; i < ARRAY_SIZE(pipe_cfg->addr.plane); ++i)
- pipe_cfg->addr.plane[i] = msm_framebuffer_iova(fb,
- psde->mmu_id, i);
-
- /* hw driver */
- psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
- }
-}
-
-static void sde_plane_scale_helper(struct drm_plane *plane,
- uint32_t src, uint32_t dst, uint32_t *phase_steps,
- enum sde_hw_filter *filter, struct sde_mdp_format_params *fmt,
- uint32_t chroma_subsampling)
-{
- /* calcualte phase steps, leave init phase as zero */
- phase_steps[SDE_SSPP_COMP_LUMA] =
- mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
- phase_steps[SDE_SSPP_COMP_CHROMA] =
- phase_steps[SDE_SSPP_COMP_LUMA] / chroma_subsampling;
-
- /* calculate scaler config, if necessary */
- if (src != dst) {
- filter[SDE_SSPP_COMP_ALPHA] = (src < dst) ?
- SDE_MDP_SCALE_FILTER_BIL :
- SDE_MDP_SCALE_FILTER_PCMN;
-
- if (fmt->is_yuv)
- filter[SDE_SSPP_COMP_LUMA] = SDE_MDP_SCALE_FILTER_CA;
- else
- filter[SDE_SSPP_COMP_LUMA] =
- filter[SDE_SSPP_COMP_ALPHA];
- }
-}
-
-/* CIFIX: clean up fmt/subsampling params once we're using fourcc formats */
-static void _sde_plane_pixel_ext_helper(struct drm_plane *plane,
- uint32_t src, uint32_t dst, uint32_t decimated_src,
- uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
- int *out_edge2, struct sde_mdp_format_params *fmt,
- uint32_t chroma_subsampling, bool post_compare)
-{
- /* CIFIX: adapted from mdss_mdp_pipe_calc_pixel_extn() */
- int64_t edge1, edge2, caf;
- uint32_t src_work;
- int i, tmp;
-
- if (plane && phase_steps && out_src && out_edge1 && out_edge2 && fmt) {
- /* enable CAF for YUV formats */
- if (fmt->is_yuv)
- caf = PHASE_STEP_UNIT_SCALE;
- else
- caf = 0;
-
- for (i = 0; i < SDE_MAX_PLANES; i++) {
- src_work = decimated_src;
- if (i == 1 || i == 2)
- src_work /= chroma_subsampling;
- if (post_compare)
- src = src_work;
- if (!(fmt->is_yuv) && (src == dst)) {
- /* unity */
- edge1 = 0;
- edge2 = 0;
- } else if (dst >= src) {
- /* upscale */
- edge1 = (1 << PHASE_RESIDUAL);
- edge1 -= caf;
- edge2 = (1 << PHASE_RESIDUAL);
- edge2 += (dst - 1) * *(phase_steps + i);
- edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
- edge2 += caf;
- edge2 = -(edge2);
- } else {
- /* downscale */
- edge1 = 0;
- edge2 = (dst - 1) * *(phase_steps + i);
- edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
- edge2 += *(phase_steps + i);
- edge2 = -(edge2);
- }
-
- /* only enable CAF for luma plane */
- caf = 0;
-
- /* populate output arrays */
- *(out_src + i) = src_work;
-
- /* edge updates taken from __pxl_extn_helper */
- /* CIFIX: why are we casting first to uint32_t? */
- if (edge1 >= 0) {
- tmp = (uint32_t)edge1;
- tmp >>= PHASE_STEP_SHIFT;
- *(out_edge1 + i) = -tmp;
- } else {
- tmp = (uint32_t)(-edge1);
- *(out_edge1 + i) = (tmp + PHASE_STEP_UNIT_SCALE
- - 1) >> PHASE_STEP_SHIFT;
- }
- if (edge2 >= 0) {
- tmp = (uint32_t)edge2;
- tmp >>= PHASE_STEP_SHIFT;
- *(out_edge2 + i) = -tmp;
- } else {
- tmp = (uint32_t)(-edge2);
- *(out_edge2 + i) = (tmp + PHASE_STEP_UNIT_SCALE
- - 1) >> PHASE_STEP_SHIFT;
- }
- }
- }
-}
-
-static int sde_plane_mode_set(struct drm_plane *plane,
- struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- struct sde_plane *psde = to_sde_plane(plane);
- struct sde_plane_state *pstate;
- const struct mdp_format *format;
- uint32_t nplanes, pix_format, tmp;
- int i;
- struct sde_mdp_format_params *fmt;
- struct sde_hw_pixel_ext *pe;
- int ret = 0;
-
- SDE_PLANE_DEBUG_START();
- nplanes = drm_format_num_planes(fb->pixel_format);
-
- pstate = to_sde_plane_state(plane->state);
-
- format = to_mdp_format(msm_framebuffer_format(fb));
- pix_format = format->base.pixel_format;
-
- /* src values are in Q16 fixed point, convert to integer */
- src_x = src_x >> 16;
- src_y = src_y >> 16;
- src_w = src_w >> 16;
- src_h = src_h >> 16;
-
- DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", psde->name,
- fb->base.id, src_x, src_y, src_w, src_h,
- crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
-
- /* update format configuration */
- memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
-
- psde->pipe_cfg.src.format = sde_mdp_get_format_params(pix_format,
- 0/* CIFIX: fmt_modifier */);
- psde->pipe_cfg.src.width = fb->width;
- psde->pipe_cfg.src.height = fb->height;
- psde->pipe_cfg.src.num_planes = nplanes;
-
- sde_plane_set_scanout(plane, &psde->pipe_cfg, fb);
-
- psde->pipe_cfg.src_rect.x = src_x;
- psde->pipe_cfg.src_rect.y = src_y;
- psde->pipe_cfg.src_rect.w = src_w;
- psde->pipe_cfg.src_rect.h = src_h;
-
- psde->pipe_cfg.dst_rect.x = crtc_x;
- psde->pipe_cfg.dst_rect.y = crtc_y;
- psde->pipe_cfg.dst_rect.w = crtc_w;
- psde->pipe_cfg.dst_rect.h = crtc_h;
-
- psde->pipe_cfg.horz_decimation = 0;
- psde->pipe_cfg.vert_decimation = 0;
-
- /* get sde pixel format definition */
- fmt = psde->pipe_cfg.src.format;
-
- /* update pixel extensions */
- pe = &(psde->pixel_ext);
- if (!pe->enable_pxl_ext) {
- uint32_t chroma_subsample_h, chroma_subsample_v;
-
- chroma_subsample_h = psde->pipe_cfg.horz_decimation ? 1 :
- drm_format_horz_chroma_subsampling(pix_format);
- chroma_subsample_v = psde->pipe_cfg.vert_decimation ? 1 :
- drm_format_vert_chroma_subsampling(pix_format);
-
- memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
-
- /* calculate phase steps */
- sde_plane_scale_helper(plane, src_w, crtc_w,
- pe->phase_step_x,
- pe->horz_filter, fmt, chroma_subsample_h);
- sde_plane_scale_helper(plane, src_h, crtc_h,
- pe->phase_step_y,
- pe->vert_filter, fmt, chroma_subsample_v);
-
- /* calculate left/right/top/bottom pixel extentions */
- tmp = DECIMATED_DIMENSION(src_w,
- psde->pipe_cfg.horz_decimation);
- if (fmt->is_yuv)
- tmp &= ~0x1;
- _sde_plane_pixel_ext_helper(plane, src_w, crtc_w, tmp,
- pe->phase_step_x,
- pe->roi_w,
- pe->num_ext_pxls_left,
- pe->num_ext_pxls_right, fmt,
- chroma_subsample_h, 0);
-
- tmp = DECIMATED_DIMENSION(src_h,
- psde->pipe_cfg.vert_decimation);
- _sde_plane_pixel_ext_helper(plane, src_h, crtc_h, tmp,
- pe->phase_step_y,
- pe->roi_h,
- pe->num_ext_pxls_top,
- pe->num_ext_pxls_btm, fmt,
- chroma_subsample_v, 1);
-
- /* CIFIX: port "Single pixel rgb scale adjustment"? */
-
- for (i = 0; i < SDE_MAX_PLANES; i++) {
- if (pe->num_ext_pxls_left[i] >= 0)
- pe->left_rpt[i] =
- pe->num_ext_pxls_left[i];
- else
- pe->left_ftch[i] =
- pe->num_ext_pxls_left[i];
-
- if (pe->num_ext_pxls_right[i] >= 0)
- pe->right_rpt[i] =
- pe->num_ext_pxls_right[i];
- else
- pe->right_ftch[i] =
- pe->num_ext_pxls_right[i];
-
- if (pe->num_ext_pxls_top[i] >= 0)
- pe->top_rpt[i] =
- pe->num_ext_pxls_top[i];
- else
- pe->top_ftch[i] =
- pe->num_ext_pxls_top[i];
-
- if (pe->num_ext_pxls_btm[i] >= 0)
- pe->btm_rpt[i] =
- pe->num_ext_pxls_btm[i];
- else
- pe->btm_ftch[i] =
- pe->num_ext_pxls_btm[i];
- }
- }
-
- if (psde->pipe_hw->ops.setup_sourceformat)
- psde->pipe_hw->ops.setup_sourceformat(psde->pipe_hw,
- &psde->pipe_cfg, 0 /* CIFIX: flags */);
- if (psde->pipe_hw->ops.setup_rects)
- psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
- &psde->pipe_cfg, &psde->pixel_ext);
-
- /* update csc */
-
- SDE_PLANE_DEBUG_END();
- return ret;
-}
-
-static int sde_plane_prepare_fb(struct drm_plane *plane,
- const struct drm_plane_state *new_state)
-{
- struct drm_framebuffer *fb = new_state->fb;
- struct sde_plane *psde = to_sde_plane(plane);
-
- if (!new_state->fb)
- return 0;
-
- SDE_PLANE_DEBUG_START();
- SDE_PLANE_DEBUG_END();
- DBG("%s: prepare: FB[%u]", psde->name, fb->base.id);
- return msm_framebuffer_prepare(fb, psde->mmu_id);
-}
-
-static void sde_plane_cleanup_fb(struct drm_plane *plane,
- const struct drm_plane_state *old_state)
-{
- struct drm_framebuffer *fb = old_state->fb;
- struct sde_plane *psde = to_sde_plane(plane);
-
- if (!fb)
- return;
-
- SDE_PLANE_DEBUG_START();
- SDE_PLANE_DEBUG_END();
- DBG("%s: cleanup: FB[%u]", psde->name, fb->base.id);
- msm_framebuffer_cleanup(fb, psde->mmu_id);
-}
-
-static int sde_plane_atomic_check(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- struct sde_plane *psde = to_sde_plane(plane);
- struct drm_plane_state *old_state = plane->state;
- const struct mdp_format *format;
-
- SDE_PLANE_DEBUG_START();
- SDE_PLANE_DEBUG_END();
- DBG("%s: check (%d -> %d)", psde->name,
- sde_plane_enabled(old_state), sde_plane_enabled(state));
-
- if (sde_plane_enabled(state)) {
- /* CIFIX: don't use mdp format? */
- format = to_mdp_format(msm_framebuffer_format(state->fb));
- if (MDP_FORMAT_IS_YUV(format) &&
- (!(psde->features & SDE_PLANE_FEATURE_SCALER) ||
- !(psde->features & BIT(SDE_SSPP_CSC)))) {
- dev_err(plane->dev->dev,
- "Pipe doesn't support YUV\n");
-
- return -EINVAL;
- }
-
- if (!(psde->features & SDE_PLANE_FEATURE_SCALER) &&
- (((state->src_w >> 16) != state->crtc_w) ||
- ((state->src_h >> 16) != state->crtc_h))) {
- dev_err(plane->dev->dev,
- "Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
- state->src_w >> 16, state->src_h >> 16,
- state->crtc_w, state->crtc_h);
-
- return -EINVAL;
- }
- }
-
- if (sde_plane_enabled(state) && sde_plane_enabled(old_state)) {
- /* we cannot change SMP block configuration during scanout: */
- bool full_modeset = false;
-
- if (state->fb->pixel_format != old_state->fb->pixel_format) {
- DBG("%s: pixel_format change!", psde->name);
- full_modeset = true;
- }
- if (state->src_w != old_state->src_w) {
- DBG("%s: src_w change!", psde->name);
- full_modeset = true;
- }
- if (to_sde_plane_state(old_state)->pending) {
- DBG("%s: still pending!", psde->name);
- full_modeset = true;
- }
- if (full_modeset) {
- struct drm_crtc_state *crtc_state =
- drm_atomic_get_crtc_state(state->state,
- state->crtc);
- crtc_state->mode_changed = true;
- to_sde_plane_state(state)->mode_changed = true;
- }
- } else {
- to_sde_plane_state(state)->mode_changed = true;
- }
-
- return 0;
-}
-
-static void sde_plane_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *old_state)
-{
- struct sde_plane *sde_plane = to_sde_plane(plane);
- struct drm_plane_state *state = plane->state;
-
- DBG("%s: update", sde_plane->name);
-
- SDE_PLANE_DEBUG_START();
- if (!sde_plane_enabled(state)) {
- to_sde_plane_state(state)->pending = true;
- } else if (to_sde_plane_state(state)->mode_changed) {
- int ret;
-
- to_sde_plane_state(state)->pending = true;
- ret = sde_plane_mode_set(plane,
- state->crtc, state->fb,
- state->crtc_x, state->crtc_y,
- state->crtc_w, state->crtc_h,
- state->src_x, state->src_y,
- state->src_w, state->src_h);
- /* atomic_check should have ensured that this doesn't fail */
- WARN_ON(ret < 0);
- } else {
- sde_plane_set_scanout(plane, &sde_plane->pipe_cfg, state->fb);
- }
- SDE_PLANE_DEBUG_END();
-}
-
-/* helper to install properties which are common to planes and crtcs */
-static void sde_plane_install_properties(struct drm_plane *plane,
- struct drm_mode_object *obj)
-{
- struct drm_device *dev = plane->dev;
- struct msm_drm_private *dev_priv = dev->dev_private;
- struct drm_property *prop;
-
- SDE_PLANE_DEBUG_START();
-#define INSTALL_PROPERTY(name, NAME, init_val, fnc, ...) do { \
- prop = dev_priv->plane_property[PLANE_PROP_##NAME]; \
- if (!prop) { \
- prop = drm_property_##fnc(dev, 0, #name, \
- ##__VA_ARGS__); \
- if (!prop) { \
- dev_warn(dev->dev, \
- "Create property %s failed\n", \
- #name); \
- return; \
- } \
- dev_priv->plane_property[PLANE_PROP_##NAME] = prop; \
- } \
- drm_object_attach_property(&plane->base, prop, init_val); \
- } while (0)
-
-#define INSTALL_RANGE_PROPERTY(name, NAME, min, max, init_val) \
- INSTALL_PROPERTY(name, NAME, init_val, \
- create_range, min, max)
-
-#define INSTALL_ENUM_PROPERTY(name, NAME, init_val) \
- INSTALL_PROPERTY(name, NAME, init_val, \
- create_enum, name##_prop_enum_list, \
- ARRAY_SIZE(name##_prop_enum_list))
-
- INSTALL_RANGE_PROPERTY(zpos, ZPOS, 1, 255, 1);
-
-#undef INSTALL_RANGE_PROPERTY
-#undef INSTALL_ENUM_PROPERTY
-#undef INSTALL_PROPERTY
- SDE_PLANE_DEBUG_END();
-}
-
-static int sde_plane_atomic_set_property(struct drm_plane *plane,
- struct drm_plane_state *state, struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *dev = plane->dev;
- struct sde_plane_state *pstate;
- struct msm_drm_private *dev_priv = dev->dev_private;
- int ret = 0;
-
- SDE_PLANE_DEBUG_START();
-
- pstate = to_sde_plane_state(state);
-
-#define SET_PROPERTY(name, NAME, type) do { \
- if (dev_priv->plane_property[PLANE_PROP_##NAME] == property) { \
- pstate->name = (type)val; \
- DBG("Set property %s %d", #name, (type)val); \
- goto done; \
- } \
- } while (0)
-
- SET_PROPERTY(zpos, ZPOS, uint8_t);
-
- dev_err(dev->dev, "Invalid property\n");
- ret = -EINVAL;
-done:
- SDE_PLANE_DEBUG_END();
- return ret;
-#undef SET_PROPERTY
-}
-
-static int sde_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
-{
- int rc;
-
- SDE_PLANE_DEBUG_START();
- rc = sde_plane_atomic_set_property(plane, plane->state, property,
- val);
- SDE_PLANE_DEBUG_END();
- return rc;
-}
-
-static int sde_plane_atomic_get_property(struct drm_plane *plane,
- const struct drm_plane_state *state,
- struct drm_property *property, uint64_t *val)
-{
- struct drm_device *dev = plane->dev;
- struct sde_plane_state *pstate;
- struct msm_drm_private *dev_priv = dev->dev_private;
- int ret = 0;
-
- SDE_PLANE_DEBUG_START();
- pstate = to_sde_plane_state(state);
-
-#define GET_PROPERTY(name, NAME, type) do { \
- if (dev_priv->plane_property[PLANE_PROP_##NAME] == property) { \
- *val = pstate->name; \
- DBG("Get property %s %lld", #name, *val); \
- goto done; \
- } \
- } while (0)
-
- GET_PROPERTY(zpos, ZPOS, uint8_t);
-
- dev_err(dev->dev, "Invalid property\n");
- ret = -EINVAL;
-done:
- SDE_PLANE_DEBUG_END();
- return ret;
-#undef SET_PROPERTY
-}
-
-static void sde_plane_destroy(struct drm_plane *plane)
-{
- struct sde_plane *psde = to_sde_plane(plane);
-
- SDE_PLANE_DEBUG_START();
-
- if (psde->pipe_hw)
- sde_hw_sspp_destroy(psde->pipe_hw);
-
- drm_plane_helper_disable(plane);
- drm_plane_cleanup(plane);
-
- kfree(psde);
-
- SDE_PLANE_DEBUG_END();
-}
-
-static void sde_plane_destroy_state(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- SDE_PLANE_DEBUG_START();
- if (state->fb)
- drm_framebuffer_unreference(state->fb);
-
- kfree(to_sde_plane_state(state));
- SDE_PLANE_DEBUG_END();
-}
-
-static struct drm_plane_state *
-sde_plane_duplicate_state(struct drm_plane *plane)
-{
- struct sde_plane_state *pstate;
-
- if (WARN_ON(!plane->state))
- return NULL;
-
- SDE_PLANE_DEBUG_START();
- pstate = kmemdup(to_sde_plane_state(plane->state),
- sizeof(*pstate), GFP_KERNEL);
-
- if (pstate && pstate->base.fb)
- drm_framebuffer_reference(pstate->base.fb);
-
- pstate->mode_changed = false;
- pstate->pending = false;
- SDE_PLANE_DEBUG_END();
-
- return &pstate->base;
-}
-
-static void sde_plane_reset(struct drm_plane *plane)
-{
- struct sde_plane_state *pstate;
-
- SDE_PLANE_DEBUG_START();
- if (plane->state && plane->state->fb)
- drm_framebuffer_unreference(plane->state->fb);
-
- kfree(to_sde_plane_state(plane->state));
- pstate = kzalloc(sizeof(*pstate), GFP_KERNEL);
-
- memset(pstate, 0, sizeof(struct sde_plane_state));
-
- /* assign default blend parameters */
- pstate->alpha = 255;
- pstate->premultiplied = 0;
-
- if (plane->type == DRM_PLANE_TYPE_PRIMARY)
- pstate->zpos = STAGE_BASE;
- else
- pstate->zpos = STAGE0 + drm_plane_index(plane);
-
- pstate->base.plane = plane;
-
- plane->state = &pstate->base;
- SDE_PLANE_DEBUG_END();
-}
-
-static const struct drm_plane_funcs sde_plane_funcs = {
- .update_plane = drm_atomic_helper_update_plane,
- .disable_plane = drm_atomic_helper_disable_plane,
- .destroy = sde_plane_destroy,
- .set_property = sde_plane_set_property,
- .atomic_set_property = sde_plane_atomic_set_property,
- .atomic_get_property = sde_plane_atomic_get_property,
- .reset = sde_plane_reset,
- .atomic_duplicate_state = sde_plane_duplicate_state,
- .atomic_destroy_state = sde_plane_destroy_state,
-};
-
-static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
- .prepare_fb = sde_plane_prepare_fb,
- .cleanup_fb = sde_plane_cleanup_fb,
- .atomic_check = sde_plane_atomic_check,
- .atomic_update = sde_plane_atomic_update,
-};
-
-enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
-{
- struct sde_plane *sde_plane = to_sde_plane(plane);
-
- return sde_plane->pipe;
-}
-
-/* initialize plane */
-struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe,
- bool private_plane)
-{
- static const char tmp_name[] = "---";
- struct drm_plane *plane = NULL;
- struct sde_plane *psde;
- struct sde_hw_ctl *sde_ctl;
- struct msm_drm_private *priv;
- struct sde_kms *kms;
- struct sde_mdss_cfg *sde_cat;
- int ret;
- enum drm_plane_type type;
-
- priv = dev->dev_private;
- if (!priv) {
- DRM_ERROR("[%u]Private data is NULL\n", pipe);
- goto exit;
- }
-
- if (!priv->kms) {
- DRM_ERROR("[%u]Invalid KMS reference\n", pipe);
- goto exit;
- }
- kms = to_sde_kms(priv->kms);
-
- psde = kzalloc(sizeof(*psde), GFP_KERNEL);
- if (!psde) {
- ret = -ENOMEM;
- goto fail;
- }
-
- memset(psde, 0, sizeof(*psde));
-
- plane = &psde->base;
-
- psde->pipe = pipe;
- psde->name = tmp_name;
-
- if (kms) {
- /* mmu id for buffer mapping */
- psde->mmu_id = kms->mmu_id;
-
- /* check catalog for features mask */
- sde_cat = kms->catalog;
- if (sde_cat)
- psde->features = sde_cat->sspp[pipe].features;
- }
- psde->nformats = mdp_get_formats(psde->formats,
- ARRAY_SIZE(psde->formats),
- !(psde->features & BIT(SDE_SSPP_CSC)) ||
- !(psde->features & SDE_PLANE_FEATURE_SCALER));
-
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
- ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
- psde->formats, psde->nformats,
- type);
- if (ret)
- goto fail;
-
- drm_plane_helper_add(plane, &sde_plane_helper_funcs);
-
- sde_plane_install_properties(plane, &plane->base);
-
- psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, sde_cat);
- if (IS_ERR(psde->pipe_hw)) {
- ret = PTR_ERR(psde->pipe_hw);
- psde->pipe_hw = NULL;
- goto fail;
- }
-
- /* cache flush mask for later */
- sde_ctl = sde_hw_ctl_init(CTL_0, kms->mmio, sde_cat);
- if (!IS_ERR(sde_ctl)) {
- if (sde_ctl->ops.get_bitmask_sspp)
- sde_ctl->ops.get_bitmask_sspp(sde_ctl,
- &psde->flush_mask, pipe);
- sde_hw_ctl_destroy(sde_ctl);
- }
-
- pr_err("%s: Successfully created plane\n", __func__);
- return plane;
-
-fail:
- pr_err("%s: Plane creation failed\n", __func__);
- if (plane)
- sde_plane_destroy(plane);
-exit:
- return ERR_PTR(ret);
-}
diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c
index bd93ded07131..bc7c0badf189 100644
--- a/drivers/gpu/msm/adreno_a5xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -943,11 +943,13 @@ void a5xx_snapshot(struct adreno_device *adreno_dev,
a5xx_snapshot_debugbus(device, snapshot);
/* Preemption record */
- FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
- kgsl_snapshot_add_section(device,
- KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
- snapshot, snapshot_preemption_record,
- &rb->preemption_desc);
+ if (adreno_is_preemption_enabled(adreno_dev)) {
+ FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
+ kgsl_snapshot_add_section(device,
+ KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
+ snapshot, snapshot_preemption_record,
+ &rb->preemption_desc);
+ }
}
}
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
index bd1e432d8c7d..bb92b8b79d93 100644
--- a/drivers/gpu/msm/kgsl_pool.c
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -299,6 +299,7 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages,
struct page *p = NULL;
int order = get_order(*page_size);
int pool_idx;
+ size_t size = 0;
if ((pages == NULL) || pages_len < (*page_size >> PAGE_SHIFT))
return -EINVAL;
@@ -311,11 +312,8 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages,
if (page == NULL) {
/* Retry with lower order pages */
if (order > 0) {
- size_t size = PAGE_SIZE << --order;
- *page_size = kgsl_get_page_size(size,
- ilog2(size));
- *align = ilog2(*page_size);
- return -EAGAIN;
+ size = PAGE_SIZE << --order;
+ goto eagain;
} else
return -ENOMEM;
@@ -325,8 +323,25 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages,
}
pool = _kgsl_get_pool_from_order(order);
- if (pool == NULL)
- return -EINVAL;
+ if (pool == NULL) {
+ /* Retry with lower order pages */
+ if (order > 0) {
+ size = PAGE_SIZE << --order;
+ goto eagain;
+ } else {
+ /*
+ * Fall back to direct allocation in case
+ * pool with zero order is not present
+ */
+ gfp_t gfp_mask = kgsl_gfp_mask(order);
+
+ page = alloc_pages(gfp_mask, order);
+ if (page == NULL)
+ return -ENOMEM;
+ _kgsl_pool_zero_page(page, order);
+ goto done;
+ }
+ }
pool_idx = kgsl_pool_idx_lookup(order);
page = _kgsl_pool_get_page(pool);
@@ -337,10 +352,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages,
/* Only allocate non-reserved memory for certain pools */
if (!pool->allocation_allowed && pool_idx > 0) {
- *page_size = PAGE_SIZE <<
+ size = PAGE_SIZE <<
kgsl_pools[pool_idx-1].pool_order;
- *align = ilog2(*page_size);
- return -EAGAIN;
+ goto eagain;
}
page = alloc_pages(gfp_mask, order);
@@ -348,10 +362,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages,
if (!page) {
if (pool_idx > 0) {
/* Retry with lower order pages */
- *page_size = PAGE_SIZE <<
+ size = PAGE_SIZE <<
kgsl_pools[pool_idx-1].pool_order;
- *align = ilog2(*page_size);
- return -EAGAIN;
+ goto eagain;
} else
return -ENOMEM;
}
@@ -367,6 +380,12 @@ done:
}
return pcount;
+
+eagain:
+ *page_size = kgsl_get_page_size(size,
+ ilog2(size));
+ *align = ilog2(*page_size);
+ return -EAGAIN;
}
void kgsl_pool_free_page(struct page *page)
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index cd9a82a9bf4a..fe6aa45901d0 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1994,6 +1994,42 @@ static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level)
return clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], rate);
}
+static inline void _close_pcl(struct kgsl_pwrctrl *pwr)
+{
+ if (pwr->pcl)
+ msm_bus_scale_unregister_client(pwr->pcl);
+
+ pwr->pcl = 0;
+}
+
+static inline void _close_ocmem_pcl(struct kgsl_pwrctrl *pwr)
+{
+ if (pwr->ocmem_pcl)
+ msm_bus_scale_unregister_client(pwr->ocmem_pcl);
+
+ pwr->ocmem_pcl = 0;
+}
+
+static inline void _close_regulators(struct kgsl_pwrctrl *pwr)
+{
+ int i;
+
+ for (i = 0; i < KGSL_MAX_REGULATORS; i++)
+ pwr->regulators[i].reg = NULL;
+}
+
+static inline void _close_clks(struct kgsl_device *device)
+{
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ int i;
+
+ for (i = 0; i < KGSL_MAX_CLKS; i++)
+ pwr->grp_clks[i] = NULL;
+
+ if (pwr->gpu_bimc_int_clk)
+ devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk);
+}
+
int kgsl_pwrctrl_init(struct kgsl_device *device)
{
int i, k, m, n = 0, result;
@@ -2011,7 +2047,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
result = _get_clocks(device);
if (result)
- return result;
+ goto error_cleanup_clks;
/* Make sure we have a source clk for freq setting */
if (pwr->grp_clks[0] == NULL)
@@ -2029,7 +2065,8 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
if (pwr->num_pwrlevels == 0) {
KGSL_PWR_ERR(device, "No power levels are defined\n");
- return -EINVAL;
+ result = -EINVAL;
+ goto error_cleanup_clks;
}
/* Initialize the user and thermal clock constraints */
@@ -2059,7 +2096,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
result = get_regulators(device);
if (result)
- return result;
+ goto error_cleanup_regulators;
pwr->power_flags = 0;
@@ -2079,8 +2116,10 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
pwr->ocmem_pcl = msm_bus_scale_register_client
(ocmem_scale_table);
- if (!pwr->ocmem_pcl)
- return -EINVAL;
+ if (!pwr->ocmem_pcl) {
+ result = -EINVAL;
+ goto error_disable_pm;
+ }
}
/* Bus width in bytes, set it to zero if not found */
@@ -2110,14 +2149,18 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
* from the driver.
*/
pwr->pcl = msm_bus_scale_register_client(bus_scale_table);
- if (pwr->pcl == 0)
- return -EINVAL;
+ if (pwr->pcl == 0) {
+ result = -EINVAL;
+ goto error_cleanup_ocmem_pcl;
+ }
}
pwr->bus_ib = kzalloc(bus_scale_table->num_usecases *
sizeof(*pwr->bus_ib), GFP_KERNEL);
- if (pwr->bus_ib == NULL)
- return -ENOMEM;
+ if (pwr->bus_ib == NULL) {
+ result = -ENOMEM;
+ goto error_cleanup_pcl;
+ }
/*
* Pull the BW vote out of the bus table. They will be used to
@@ -2175,36 +2218,26 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
&pwr->tsens_name);
return result;
+
+error_cleanup_pcl:
+ _close_pcl(pwr);
+error_cleanup_ocmem_pcl:
+ _close_ocmem_pcl(pwr);
+error_disable_pm:
+ pm_runtime_disable(&pdev->dev);
+error_cleanup_regulators:
+ _close_regulators(pwr);
+error_cleanup_clks:
+ _close_clks(device);
+ return result;
}
void kgsl_pwrctrl_close(struct kgsl_device *device)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- int i;
KGSL_PWR_INFO(device, "close device %d\n", device->id);
- pm_runtime_disable(&device->pdev->dev);
-
- if (pwr->pcl)
- msm_bus_scale_unregister_client(pwr->pcl);
-
- pwr->pcl = 0;
-
- if (pwr->ocmem_pcl)
- msm_bus_scale_unregister_client(pwr->ocmem_pcl);
-
- pwr->ocmem_pcl = 0;
-
- for (i = 0; i < KGSL_MAX_REGULATORS; i++)
- pwr->regulators[i].reg = NULL;
-
- for (i = 0; i < KGSL_MAX_REGULATORS; i++)
- pwr->grp_clks[i] = NULL;
-
- if (pwr->gpu_bimc_int_clk)
- devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk);
-
pwr->power_flags = 0;
if (!IS_ERR_OR_NULL(pwr->sysfs_pwr_limit)) {
@@ -2213,6 +2246,16 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
pwr->sysfs_pwr_limit = NULL;
}
kfree(pwr->bus_ib);
+
+ _close_pcl(pwr);
+
+ _close_ocmem_pcl(pwr);
+
+ pm_runtime_disable(&device->pdev->dev);
+
+ _close_regulators(pwr);
+
+ _close_clks(device);
}
/**
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 70766e208217..ce15e150277e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -410,8 +410,8 @@ struct arm_smmu_device {
struct mutex power_lock;
unsigned int power_count;
- struct msm_bus_client_handle *bus_client;
- char *bus_client_name;
+ u32 bus_client;
+ struct msm_bus_scale_pdata *bus_pdata;
enum tz_smmu_device_id sec_id;
};
@@ -912,14 +912,14 @@ static int arm_smmu_request_bus(struct arm_smmu_device *smmu)
{
if (!smmu->bus_client)
return 0;
- return msm_bus_scale_update_bw(smmu->bus_client, 0, 1000);
+ return msm_bus_scale_client_update_request(smmu->bus_client, 1);
}
static int arm_smmu_unrequest_bus(struct arm_smmu_device *smmu)
{
if (!smmu->bus_client)
return 0;
- return msm_bus_scale_update_bw(smmu->bus_client, 0, 0);
+ return msm_bus_scale_client_update_request(smmu->bus_client, 0);
}
static int arm_smmu_disable_regulators(struct arm_smmu_device *smmu)
@@ -3531,8 +3531,10 @@ static int arm_smmu_init_clocks(struct arm_smmu_device *smmu)
smmu->num_clocks =
of_property_count_strings(dev->of_node, "clock-names");
- if (smmu->num_clocks < 1)
+ if (smmu->num_clocks < 1) {
+ smmu->num_clocks = 0;
return 0;
+ }
smmu->clocks = devm_kzalloc(
dev, sizeof(*smmu->clocks) * smmu->num_clocks,
@@ -3569,34 +3571,37 @@ static int arm_smmu_init_clocks(struct arm_smmu_device *smmu)
static int arm_smmu_init_bus_scaling(struct platform_device *pdev,
struct arm_smmu_device *smmu)
{
- u32 master_id;
-
- if (of_property_read_u32(pdev->dev.of_node, "qcom,bus-master-id",
- &master_id)) {
- dev_dbg(smmu->dev, "No bus scaling info\n");
+ if (!of_find_property(pdev->dev.of_node, "qcom,msm-bus,name", NULL)) {
+ dev_dbg(&pdev->dev, "No bus scaling info\n");
return 0;
}
- smmu->bus_client_name = devm_kasprintf(
- smmu->dev, GFP_KERNEL, "smmu-bus-client-%s",
- dev_name(smmu->dev));
-
- if (!smmu->bus_client_name)
- return -ENOMEM;
-
- smmu->bus_client = msm_bus_scale_register(
- master_id, MSM_BUS_SLAVE_EBI_CH0, smmu->bus_client_name, true);
- if (IS_ERR(&smmu->bus_client)) {
- int ret = PTR_ERR(smmu->bus_client);
+ smmu->bus_pdata = msm_bus_cl_get_pdata(pdev);
+ if (!smmu->bus_pdata) {
+ dev_err(&pdev->dev, "Unable to read bus-scaling from DT\n");
+ return -EINVAL;
+ }
- if (ret != -EPROBE_DEFER)
- dev_err(smmu->dev, "Bus client registration failed\n");
- return ret;
+ smmu->bus_client = msm_bus_scale_register_client(smmu->bus_pdata);
+ if (!smmu->bus_client) {
+ dev_err(&pdev->dev, "Bus client registration failed\n");
+ return -EINVAL;
}
return 0;
}
+static void arm_smmu_exit_bus_scaling(struct arm_smmu_device *smmu)
+{
+ if (smmu->bus_client)
+ msm_bus_scale_unregister_client(smmu->bus_client);
+ if (smmu->bus_pdata)
+ msm_bus_cl_clear_pdata(smmu->bus_pdata);
+
+ smmu->bus_client = 0;
+ smmu->bus_pdata = NULL;
+}
+
static int arm_smmu_parse_impl_def_registers(struct arm_smmu_device *smmu)
{
struct device *dev = smmu->dev;
@@ -4033,6 +4038,7 @@ out_free_irqs:
free_irq(smmu->irqs[i], smmu);
out_put_masters:
+ arm_smmu_exit_bus_scaling(smmu);
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
struct arm_smmu_master *master
= container_of(node, struct arm_smmu_master, node);
@@ -4084,7 +4090,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
arm_smmu_power_off(smmu);
mutex_unlock(&smmu->attach_lock);
- msm_bus_scale_unregister(smmu->bus_client);
+ arm_smmu_exit_bus_scaling(smmu);
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
index 54c0aa39cdd3..1c0a10e2fbef 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1212,6 +1212,25 @@ static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx,
return CAM_SMMU_BUFF_NOT_EXIST;
}
+static enum cam_smmu_buf_state cam_smmu_check_secure_fd_in_list(int idx,
+ int ion_fd, dma_addr_t *paddr_ptr,
+ size_t *len_ptr)
+{
+ struct cam_sec_buff_info *mapping;
+
+ list_for_each_entry(mapping,
+ &iommu_cb_set.cb_info[idx].smmu_buf_list,
+ list) {
+ if (mapping->ion_fd == ion_fd) {
+ mapping->ref_count++;
+ *paddr_ptr = mapping->paddr;
+ *len_ptr = mapping->len;
+ return CAM_SMMU_BUFF_EXIST;
+ }
+ }
+ return CAM_SMMU_BUFF_NOT_EXIST;
+}
+
int cam_smmu_get_handle(char *identifier, int *handle_ptr)
{
int ret = 0;
@@ -1935,7 +1954,8 @@ int cam_smmu_get_stage2_phy_addr(int handle,
goto get_addr_end;
}
- buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr);
+ buf_state = cam_smmu_check_secure_fd_in_list(idx, ion_fd, paddr_ptr,
+ len_ptr);
if (buf_state == CAM_SMMU_BUFF_EXIST) {
CDBG("ion_fd:%d already in the list, give same addr back",
ion_fd);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 0db901de4562..af82b84f613f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1680,11 +1680,6 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event)
temp_dev->hw_info->vfe_ops.core_ops.
set_halt_restart_mask(temp_dev);
}
- /* heavy spin lock in axi halt, avoid spin lock outside. */
- msm_isp_axi_halt(vfe_dev, &halt_cmd);
- if (temp_dev)
- msm_isp_axi_halt(temp_dev, &halt_cmd);
-
error_event.frame_id =
vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 4b6005b9af46..39811aa84e8e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -1930,7 +1930,7 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
}
rc = msm_sensor_driver_get_gpio_data(&(msm_actuator_t->gconf),
(&pdev->dev)->of_node);
- if (rc < 0) {
+ if (rc <= 0) {
pr_err("%s: No/Error Actuator GPIOs\n", __func__);
} else {
msm_actuator_t->cam_pinctrl_status = 1;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index 80da9b4cfcb6..c04e71f459d1 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -96,6 +96,7 @@ enum sde_bus_clients {
enum sde_rot_regdump_access {
SDE_ROT_REGDUMP_READ,
SDE_ROT_REGDUMP_WRITE,
+ SDE_ROT_REGDUMP_VBIF,
SDE_ROT_REGDUMP_MAX
};
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 920f5a809777..29215c1a5910 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -1523,20 +1523,20 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,
u8 out_v_subsample, out_h_subsample;
if (!sde_rotator_is_valid_pixfmt(mgr, in_fmt->format, true)) {
- SDEROT_DBG("Invalid input format %x\n", in_fmt->format);
- return false;
+ SDEROT_ERR("Invalid input format %x\n", in_fmt->format);
+ goto verify_error;
}
if (!sde_rotator_is_valid_pixfmt(mgr, out_fmt->format, false)) {
- SDEROT_DBG("Invalid output format %x\n", out_fmt->format);
- return false;
+ SDEROT_ERR("Invalid output format %x\n", out_fmt->format);
+ goto verify_error;
}
if ((in_fmt->is_yuv != out_fmt->is_yuv) ||
(in_fmt->pixel_mode != out_fmt->pixel_mode) ||
(in_fmt->unpack_tight != out_fmt->unpack_tight)) {
- SDEROT_DBG("Rotator does not support CSC\n");
- return false;
+ SDEROT_ERR("Rotator does not support CSC\n");
+ goto verify_error;
}
/* Forcing same pixel depth */
@@ -1546,8 +1546,8 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,
(in_fmt->bits[C2_R_Cr] != out_fmt->bits[C2_R_Cr]) ||
(in_fmt->bits[C0_G_Y] != out_fmt->bits[C0_G_Y]) ||
(in_fmt->bits[C1_B_Cb] != out_fmt->bits[C1_B_Cb])) {
- SDEROT_DBG("Bit format does not match\n");
- return false;
+ SDEROT_ERR("Bit format does not match\n");
+ goto verify_error;
}
}
@@ -1560,87 +1560,161 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,
if ((in_v_subsample != out_h_subsample) ||
(in_h_subsample != out_v_subsample)) {
- SDEROT_DBG("Rotation has invalid subsampling\n");
- return false;
+ SDEROT_ERR("Rotation has invalid subsampling\n");
+ goto verify_error;
}
} else {
if (in_fmt->chroma_sample != out_fmt->chroma_sample) {
- SDEROT_DBG("Format subsampling mismatch\n");
- return false;
+ SDEROT_ERR("Format subsampling mismatch\n");
+ goto verify_error;
}
}
- SDEROT_DBG("in_fmt=%0d, out_fmt=%d\n", in_fmt->format, out_fmt->format);
return true;
+
+verify_error:
+ SDEROT_ERR("in_fmt=0x%x, out_fmt=0x%x\n",
+ in_fmt->format, out_fmt->format);
+ return false;
}
-int sde_rotator_verify_config(struct sde_rot_mgr *mgr,
- struct sde_rotation_config *config)
+static struct sde_mdp_format_params *__verify_input_config(
+ struct sde_rot_mgr *mgr,
+ struct sde_rotation_config *config)
{
- struct sde_mdp_format_params *in_fmt, *out_fmt;
+ struct sde_mdp_format_params *in_fmt;
u8 in_v_subsample, in_h_subsample;
- u8 out_v_subsample, out_h_subsample;
- u32 input, output;
- bool rotation;
+ u32 input;
int verify_input_only;
if (!mgr || !config) {
SDEROT_ERR("null parameters\n");
- return -EINVAL;
+ return NULL;
}
input = config->input.format;
- output = config->output.format;
- rotation = (config->flags & SDE_ROTATION_90) ? true : false;
verify_input_only =
(config->flags & SDE_ROTATION_VERIFY_INPUT_ONLY) ? 1 : 0;
in_fmt = sde_get_format_params(input);
if (!in_fmt) {
- SDEROT_DBG("Unrecognized input format:%u\n", input);
- return -EINVAL;
- }
-
- out_fmt = sde_get_format_params(output);
- if (!out_fmt) {
- SDEROT_DBG("Unrecognized output format:%u\n", output);
- return -EINVAL;
+ if (!verify_input_only)
+ SDEROT_ERR("Unrecognized input format:0x%x\n", input);
+ return NULL;
}
sde_mdp_get_v_h_subsample_rate(in_fmt->chroma_sample,
&in_v_subsample, &in_h_subsample);
- sde_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample,
- &out_v_subsample, &out_h_subsample);
/* Dimension of image needs to be divisible by subsample rate */
if ((config->input.height % in_v_subsample) ||
(config->input.width % in_h_subsample)) {
- SDEROT_DBG(
- "In ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
+ if (!verify_input_only)
+ SDEROT_ERR(
+ "In ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
config->input.width,
config->input.height,
in_v_subsample, in_h_subsample);
- return -EINVAL;
+ return NULL;
+ }
+
+ return in_fmt;
+}
+
+static struct sde_mdp_format_params *__verify_output_config(
+ struct sde_rot_mgr *mgr,
+ struct sde_rotation_config *config)
+{
+ struct sde_mdp_format_params *out_fmt;
+ u8 out_v_subsample, out_h_subsample;
+ u32 output;
+ int verify_input_only;
+
+ if (!mgr || !config) {
+ SDEROT_ERR("null parameters\n");
+ return NULL;
+ }
+
+ output = config->output.format;
+ verify_input_only =
+ (config->flags & SDE_ROTATION_VERIFY_INPUT_ONLY) ? 1 : 0;
+
+ out_fmt = sde_get_format_params(output);
+ if (!out_fmt) {
+ if (!verify_input_only)
+ SDEROT_ERR("Unrecognized output format:0x%x\n", output);
+ return NULL;
}
+ sde_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample,
+ &out_v_subsample, &out_h_subsample);
+
+ /* Dimension of image needs to be divisible by subsample rate */
if ((config->output.height % out_v_subsample) ||
(config->output.width % out_h_subsample)) {
- SDEROT_DBG(
- "Out ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
+ if (!verify_input_only)
+ SDEROT_ERR(
+ "Out ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
config->output.width,
config->output.height,
out_v_subsample, out_h_subsample);
- if (!verify_input_only)
- return -EINVAL;
+ return NULL;
}
- if (!sde_rotator_verify_format(mgr, in_fmt,
- out_fmt, rotation)) {
- SDEROT_DBG(
- "Rot format pairing invalid, in_fmt:%d, out_fmt:%d\n",
- input, output);
- if (!verify_input_only)
- return -EINVAL;
+ return out_fmt;
+}
+
+int sde_rotator_verify_config_input(struct sde_rot_mgr *mgr,
+ struct sde_rotation_config *config)
+{
+ struct sde_mdp_format_params *in_fmt;
+
+ in_fmt = __verify_input_config(mgr, config);
+ if (!in_fmt)
+ return -EINVAL;
+
+ return 0;
+}
+
+int sde_rotator_verify_config_output(struct sde_rot_mgr *mgr,
+ struct sde_rotation_config *config)
+{
+ struct sde_mdp_format_params *out_fmt;
+
+ out_fmt = __verify_output_config(mgr, config);
+ if (!out_fmt)
+ return -EINVAL;
+
+ return 0;
+}
+
+int sde_rotator_verify_config_all(struct sde_rot_mgr *mgr,
+ struct sde_rotation_config *config)
+{
+ struct sde_mdp_format_params *in_fmt, *out_fmt;
+ bool rotation;
+
+ if (!mgr || !config) {
+ SDEROT_ERR("null parameters\n");
+ return -EINVAL;
+ }
+
+ rotation = (config->flags & SDE_ROTATION_90) ? true : false;
+
+ in_fmt = __verify_input_config(mgr, config);
+ if (!in_fmt)
+ return -EINVAL;
+
+ out_fmt = __verify_output_config(mgr, config);
+ if (!out_fmt)
+ return -EINVAL;
+
+ if (!sde_rotator_verify_format(mgr, in_fmt, out_fmt, rotation)) {
+ SDEROT_ERR(
+ "Rot format pairing invalid, in_fmt:0x%x, out_fmt:0x%x\n",
+ config->input.format,
+ config->output.format);
+ return -EINVAL;
}
return 0;
@@ -2049,7 +2123,7 @@ static int sde_rotator_config_session(struct sde_rot_mgr *mgr,
int ret = 0;
struct sde_rot_perf *perf;
- ret = sde_rotator_verify_config(mgr, config);
+ ret = sde_rotator_verify_config_all(mgr, config);
if (ret) {
SDEROT_ERR("Rotator verify format failed\n");
return ret;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index eca0cbefcab1..7b27497ac6ef 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -413,7 +413,13 @@ void sde_rotator_remove_request(struct sde_rot_mgr *mgr,
struct sde_rot_file_private *private,
struct sde_rot_entry_container *req);
-int sde_rotator_verify_config(struct sde_rot_mgr *rot_dev,
+int sde_rotator_verify_config_all(struct sde_rot_mgr *rot_dev,
+ struct sde_rotation_config *config);
+
+int sde_rotator_verify_config_input(struct sde_rot_mgr *rot_dev,
+ struct sde_rotation_config *config);
+
+int sde_rotator_verify_config_output(struct sde_rot_mgr *rot_dev,
struct sde_rotation_config *config);
int sde_rotator_validate_request(struct sde_rot_mgr *rot_dev,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index cf33bc6437cc..a2da663e2046 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -246,11 +246,13 @@ static void sde_rot_dump_vbif_debug_bus(u32 bus_dump_flag,
* sde_rot_dump_reg - helper function for dumping rotator register set content
* @dump_name - register set name
* @reg_dump_flag - dumping flag controlling in-log/memory dump location
+ * @access - access type, sde registers or vbif registers
* @addr - starting address offset for dumping
* @len - range of the register set
* @dump_mem - output buffer for memory dump location option
*/
-void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
+void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag,
+ enum sde_rot_regdump_access access, u32 addr,
int len, u32 **dump_mem)
{
struct sde_rot_data_type *mdata = sde_rot_get_mdata();
@@ -258,6 +260,7 @@ void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
u32 *dump_addr = NULL;
phys_addr_t phys = 0;
int i;
+ void __iomem *base;
in_log = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
in_mem = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
@@ -285,14 +288,20 @@ void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
}
}
+ base = mdata->sde_io.base;
+ /*
+ * VBIF NRT base handling
+ */
+ if (access == SDE_ROT_REGDUMP_VBIF)
+ base = mdata->vbif_nrt_io.base;
for (i = 0; i < len; i++) {
u32 x0, x4, x8, xc;
- x0 = readl_relaxed(mdata->sde_io.base + addr+0x0);
- x4 = readl_relaxed(mdata->sde_io.base + addr+0x4);
- x8 = readl_relaxed(mdata->sde_io.base + addr+0x8);
- xc = readl_relaxed(mdata->sde_io.base + addr+0xc);
+ x0 = readl_relaxed(base + addr+0x0);
+ x4 = readl_relaxed(base + addr+0x4);
+ x8 = readl_relaxed(base + addr+0x8);
+ xc = readl_relaxed(base + addr+0xc);
if (in_log)
pr_info("0x%08X : %08x %08x %08x %08x\n",
@@ -338,6 +347,7 @@ static void sde_rot_dump_reg_all(void)
} else {
sde_rot_dump_reg(head->name,
sde_rot_dbg_evtlog.enable_reg_dump,
+ head->access,
head->offset, head->len,
&sde_rot_dbg_evtlog.reg_dump_array[i]);
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 347c0bef163f..63c53c188637 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1216,7 +1216,8 @@ static int sde_rotator_try_fmt_vid_cap(struct file *file,
config.output.format = f->fmt.pix.pixelformat;
config.output.width = f->fmt.pix.width;
config.output.height = f->fmt.pix.height;
- ret = sde_rotator_verify_config(rot_dev->mgr, &config);
+ config.flags |= SDE_ROTATION_VERIFY_INPUT_ONLY;
+ ret = sde_rotator_verify_config_output(rot_dev->mgr, &config);
sde_rot_mgr_unlock(rot_dev->mgr);
if (ret) {
if ((config.output.width == f->fmt.pix.width) &&
@@ -1233,7 +1234,7 @@ static int sde_rotator_try_fmt_vid_cap(struct file *file,
}
sde_rotator_format_recalc(f);
- return 0;
+ return ret;
}
/*
@@ -1263,7 +1264,7 @@ static int sde_rotator_try_fmt_vid_out(struct file *file,
config.input.width = f->fmt.pix.width;
config.input.height = f->fmt.pix.height;
config.flags |= SDE_ROTATION_VERIFY_INPUT_ONLY;
- ret = sde_rotator_verify_config(rot_dev->mgr, &config);
+ ret = sde_rotator_verify_config_input(rot_dev->mgr, &config);
sde_rot_mgr_unlock(rot_dev->mgr);
if (ret) {
if ((config.input.width == f->fmt.pix.width) &&
@@ -1280,7 +1281,7 @@ static int sde_rotator_try_fmt_vid_out(struct file *file,
}
sde_rotator_format_recalc(f);
- return 0;
+ return ret;
}
/*
@@ -1510,6 +1511,7 @@ static int sde_rotator_streamon(struct file *file,
if (vb2_is_streaming(vq)) {
sde_rot_mgr_lock(rot_dev->mgr);
sde_rotator_get_config_from_ctx(ctx, &config);
+ config.flags &= ~SDE_ROTATION_VERIFY_INPUT_ONLY;
ret = sde_rotator_session_config(rot_dev->mgr, ctx->private,
&config);
sde_rot_mgr_unlock(rot_dev->mgr);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index ddf11b35a1d6..3bb8399da4bf 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -226,6 +226,8 @@ static struct sde_rot_regdump sde_rot_r3_regdump[] = {
SDE_ROT_REGDUMP_WRITE },
{ "SDEROT_REGDMA_RAM", SDE_ROT_REGDMA_RAM_OFFSET, 0x2000,
SDE_ROT_REGDUMP_READ },
+ { "SDEROT_VBIF_NRT", SDE_ROT_VBIF_NRT_OFFSET, 0x590,
+ SDE_ROT_REGDUMP_VBIF },
};
/* Invalid software timestamp value for initialization */
@@ -363,6 +365,11 @@ static void sde_hw_rotator_dump_status(struct sde_hw_rotator *rot)
REGDMA_CSR_REGDMA_INVALID_CMD_RAM_OFFSET),
SDE_ROTREG_READ(rot->mdss_base,
REGDMA_CSR_REGDMA_FSM_STATE));
+
+ SDEROT_ERR(
+ "UBWC decode status = %x, UBWC encode status = %x\n",
+ SDE_ROTREG_READ(rot->mdss_base, ROT_SSPP_UBWC_ERROR_STATUS),
+ SDE_ROTREG_READ(rot->mdss_base, ROT_WB_UBWC_ERROR_STATUS));
}
/**
@@ -1681,7 +1688,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
SDEROT_EVTLOG(ctx->timestamp, flags,
item->input.width, item->input.height,
item->output.width, item->output.height,
- entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr);
+ entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr,
+ item->input.format, item->output.format);
if (mdata->default_ot_rd_limit) {
struct sde_mdp_set_ot_params ot_params;
@@ -2077,7 +2085,7 @@ static int sde_hw_rotator_validate_entry(struct sde_rot_mgr *mgr,
}
}
- fmt = sde_get_format_params(item->input.format);
+ fmt = sde_get_format_params(item->output.format);
/*
* Rotator downscale support max 4 times for UBWC format and
* max 2 times for TP10/TP10_UBWC format
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
index a748b87a231a..fedade122b88 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -235,6 +235,10 @@
#define ROT_QDSS_CLK_STATUS 0x18
#define ROT_QDSS_PULSE_TRIGGER 0x20
+/*
+ * SDE_ROT_VBIF_NRT:
+ */
+#define SDE_ROT_VBIF_NRT_OFFSET 0
/* REGDMA OP Code */
#define REGDMA_OP_NOP (0 << 28)
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 782b0eaa3648..78d3dd9d752a 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -298,7 +298,7 @@ static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
vmem_plus = 1;
dprintk(VIDC_WARN,
"could not calculate vmem ab value due to core freq mismatch\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
}
exit:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index babea6824c51..b36e3739e43b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1313,7 +1313,11 @@ static void cleanup_instance(struct msm_vidc_inst *inst)
debugfs_remove_recursive(inst->debugfs_root);
mutex_lock(&inst->pending_getpropq.lock);
- WARN_ON(!list_empty(&inst->pending_getpropq.list));
+ if (!list_empty(&inst->pending_getpropq.list)) {
+ dprintk(VIDC_ERR,
+ "pending_getpropq not empty\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
mutex_unlock(&inst->pending_getpropq.lock);
}
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index 11d8621564a6..39ac6273f34e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,7 @@
#endif
#define VIDC_DBG_TAG VIDC_DBG_LABEL ": %4s: "
+#define VIDC_DBG_WARN_ENABLE (msm_vidc_debug & VIDC_INFO)
/* To enable messages OR these values and
* echo the result to debugfs file.
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 30d1bae48e7d..777fb52b2201 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -105,7 +105,11 @@ static int __tzbsp_set_video_state(enum tzbsp_video_state state);
*/
static inline void __strict_check(struct venus_hfi_device *device)
{
- WARN_ON(!mutex_is_locked(&device->lock));
+ if (!mutex_is_locked(&device->lock)) {
+ dprintk(VIDC_WARN,
+ "device->lock mutex is not locked\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
}
static inline void __set_state(struct venus_hfi_device *device,
@@ -267,7 +271,7 @@ static int __acquire_regulator(struct regulator_info *rinfo)
if (!regulator_is_enabled(rinfo->regulator)) {
dprintk(VIDC_WARN, "Regulator is not enabled %s\n",
rinfo->name);
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
}
return rc;
@@ -617,7 +621,7 @@ static void __write_register(struct venus_hfi_device *device,
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"HFI Write register failed : Power is OFF\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return;
}
@@ -643,7 +647,7 @@ static int __read_register(struct venus_hfi_device *device, u32 reg)
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"HFI Read register failed : Power is OFF\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return -EINVAL;
}
@@ -1360,7 +1364,7 @@ static int __halt_axi(struct venus_hfi_device *device)
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"Clocks are OFF, skipping AXI HALT\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return -EINVAL;
}
@@ -3530,7 +3534,11 @@ static int __response_handler(struct venus_hfi_device *device)
if (session_id) {
struct hal_session *session = NULL;
- WARN_ON(upper_32_bits((uintptr_t)*session_id) != 0);
+ if (upper_32_bits((uintptr_t)*session_id) != 0) {
+ dprintk(VIDC_WARN,
+ "Upper 32 bits of session_id != 0\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
session = __get_session(device,
(u32)(uintptr_t)*session_id);
if (!session) {
@@ -4088,7 +4096,7 @@ static int __disable_regulator(struct regulator_info *rinfo)
disable_regulator_failed:
/* Bring attention to this issue */
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return rc;
}
diff --git a/drivers/mfd/qcom-i2c-pmic.c b/drivers/mfd/qcom-i2c-pmic.c
index ea5ac972b096..590e4c1a3f52 100644
--- a/drivers/mfd/qcom-i2c-pmic.c
+++ b/drivers/mfd/qcom-i2c-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -467,12 +467,29 @@ static int i2c_pmic_parse_dt(struct i2c_pmic *chip)
return rc;
}
+#define MAX_I2C_RETRIES 3
+static int i2c_pmic_read(struct regmap *map, unsigned int reg, void *val,
+ size_t val_count)
+{
+ int rc, retries = 0;
+
+ do {
+ rc = regmap_bulk_read(map, reg, val, val_count);
+ } while (rc == -ENOTCONN && retries++ < MAX_I2C_RETRIES);
+
+ if (retries > 1)
+ pr_err("i2c_pmic_read failed for %d retries, rc = %d\n",
+ retries - 1, rc);
+
+ return rc;
+}
+
static int i2c_pmic_determine_initial_status(struct i2c_pmic *chip)
{
int rc, i;
for (i = 0; i < chip->num_periphs; i++) {
- rc = regmap_bulk_read(chip->regmap,
+ rc = i2c_pmic_read(chip->regmap,
chip->periph[i].addr | INT_SET_TYPE_OFFSET,
chip->periph[i].cached, IRQ_MAX_REGS);
if (rc < 0) {
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index ceef607f67c0..5ffb21b8e1e5 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -505,6 +505,7 @@ static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
mutex_init(&wcd9xxx->io_lock);
mutex_init(&wcd9xxx->xfer_lock);
+ mutex_init(&wcd9xxx->reset_lock);
ret = wcd9xxx_bringup(wcd9xxx->dev);
if (ret) {
@@ -583,6 +584,7 @@ err:
err_bring_up:
mutex_destroy(&wcd9xxx->io_lock);
mutex_destroy(&wcd9xxx->xfer_lock);
+ mutex_destroy(&wcd9xxx->reset_lock);
return ret;
}
@@ -595,6 +597,7 @@ static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
mutex_destroy(&wcd9xxx->io_lock);
mutex_destroy(&wcd9xxx->xfer_lock);
+ mutex_destroy(&wcd9xxx->reset_lock);
if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
slim_remove_device(wcd9xxx->slim_slave);
}
@@ -1480,9 +1483,11 @@ static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
if (wcd9xxx->dev_up)
return 0;
+ mutex_lock(&wcd9xxx->reset_lock);
ret = wcd9xxx_reset(wcd9xxx->dev);
if (ret)
dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
+ mutex_unlock(&wcd9xxx->reset_lock);
return ret;
}
@@ -1490,6 +1495,7 @@ static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
static int wcd9xxx_slim_device_up(struct slim_device *sldev)
{
struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+ int ret = 0;
if (!wcd9xxx) {
pr_err("%s: wcd9xxx is NULL\n", __func__);
@@ -1501,7 +1507,12 @@ static int wcd9xxx_slim_device_up(struct slim_device *sldev)
return 0;
wcd9xxx->dev_up = true;
- return wcd9xxx_device_up(wcd9xxx);
+
+ mutex_lock(&wcd9xxx->reset_lock);
+ ret = wcd9xxx_device_up(wcd9xxx);
+ mutex_unlock(&wcd9xxx->reset_lock);
+
+ return ret;
}
static int wcd9xxx_slim_device_down(struct slim_device *sldev)
@@ -1519,10 +1530,14 @@ static int wcd9xxx_slim_device_down(struct slim_device *sldev)
return 0;
wcd9xxx->dev_up = false;
+
+ mutex_lock(&wcd9xxx->reset_lock);
if (wcd9xxx->dev_down)
wcd9xxx->dev_down(wcd9xxx);
wcd9xxx_irq_exit(&wcd9xxx->core_res);
wcd9xxx_reset_low(wcd9xxx->dev);
+ mutex_unlock(&wcd9xxx->reset_lock);
+
return 0;
}
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 2bc8bdff54f1..856179b96f37 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -304,6 +304,7 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
goto err_disable_irq;
}
+ memset(status, 0, sizeof(status));
ret = regmap_bulk_read(wcd9xxx_res->wcd_core_regmap,
wcd9xxx_res->intr_reg[WCD9XXX_INTR_STATUS_BASE],
status, num_irq_regs);
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index efb987b4a6b6..bd21f8cca2aa 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -559,6 +559,7 @@ static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle);
static struct qseecom_handle *hdcp1_handle;
static bool hdcp1_supported = true;
static bool hdcp1_enc_enabled;
+static struct mutex hdcp1_ta_cmd_lock;
static const char *hdcp_lib_message_name(int msg_id)
{
@@ -805,8 +806,8 @@ static int hdcp_lib_get_version(struct hdcp_lib_handle *handle)
goto exit;
}
- if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
- pr_err("library already loaded\n");
+ if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+ pr_err("library not loaded\n");
return rc;
}
@@ -901,8 +902,8 @@ static int hdcp_app_init_legacy(struct hdcp_lib_handle *handle)
goto exit;
}
- if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
- pr_err("library already loaded\n");
+ if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+ pr_err("library not loaded\n");
goto exit;
}
@@ -949,8 +950,8 @@ static int hdcp_app_init(struct hdcp_lib_handle *handle)
goto exit;
}
- if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
- pr_err("library already loaded\n");
+ if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+ pr_err("library not loaded\n");
goto exit;
}
@@ -1024,6 +1025,7 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
goto exit;
}
+ handle->hdcp_state |= HDCP_STATE_APP_LOADED;
pr_debug("qseecom_start_app success\n");
rc = hdcp_lib_get_version(handle);
@@ -1050,8 +1052,6 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
pr_err("app init failed\n");
goto exit;
}
-
- handle->hdcp_state |= HDCP_STATE_APP_LOADED;
exit:
return rc;
}
@@ -1240,8 +1240,8 @@ static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle)
goto exit;
}
- if (handle->hdcp_state & HDCP_STATE_TXMTR_INIT) {
- pr_err("txmtr already initialized\n");
+ if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
+ pr_err("library not loaded\n");
goto exit;
}
@@ -1622,6 +1622,12 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle)
rc = -EBUSY;
goto exit;
}
+
+ if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
+ pr_debug("library already loaded\n");
+ rc = -EBUSY;
+ goto exit;
+ }
} else {
if (atomic_read(&handle->hdcp_off)) {
pr_debug("hdcp2.2 session tearing down\n");
@@ -2212,6 +2218,8 @@ bool hdcp1_check_if_supported_load_app(void)
if (rc) {
pr_err("qseecom_start_app failed %d\n", rc);
hdcp1_supported = false;
+ } else {
+ mutex_init(&hdcp1_ta_cmd_lock);
}
}
@@ -2276,12 +2284,16 @@ int hdcp1_set_enc(bool enable)
struct hdcp1_set_enc_req *set_enc_req;
struct hdcp1_set_enc_rsp *set_enc_rsp;
- if (!hdcp1_supported || !hdcp1_handle)
- return -EINVAL;
+ mutex_lock(&hdcp1_ta_cmd_lock);
+
+ if (!hdcp1_supported || !hdcp1_handle) {
+ rc = -EINVAL;
+ goto end;
+ }
if (hdcp1_enc_enabled == enable) {
pr_debug("already %s\n", enable ? "enabled" : "disabled");
- return rc;
+ goto end;
}
/* set keys and request aksv */
@@ -2299,18 +2311,21 @@ int hdcp1_set_enc(bool enable)
if (rc < 0) {
pr_err("qseecom cmd failed err=%d\n", rc);
- return -EINVAL;
+ goto end;
}
rc = set_enc_rsp->ret;
if (rc) {
pr_err("enc cmd failed, rsp=%d\n", set_enc_rsp->ret);
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
hdcp1_enc_enabled = enable;
pr_debug("%s success\n", enable ? "enable" : "disable");
- return 0;
+end:
+ mutex_unlock(&hdcp1_ta_cmd_lock);
+ return rc;
}
int hdcp_library_register(struct hdcp_register_data *data)
diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c
index 7176c114f85b..ef963451a3f9 100644
--- a/drivers/misc/qcom/qdsp6v2/aac_in.c
+++ b/drivers/misc/qcom/qdsp6v2/aac_in.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@
#define AAC_FORMAT_ADTS 65535
+#define MAX_SAMPLE_RATE_384K 384000
+
static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg)
{
struct q6audio_in *audio = file->private_data;
@@ -233,6 +235,13 @@ static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg)
break;
}
+ if (cfg->sample_rate > MAX_SAMPLE_RATE_384K) {
+ pr_err("%s: ERROR: invalid sample rate = %u",
+ __func__, cfg->sample_rate);
+ rc = -EINVAL;
+ break;
+ }
+
min_bitrate = ((cfg->sample_rate)*(cfg->channels))/2;
/* This calculation should be based on AAC mode. But we cannot
* get AAC mode in this setconfig. min_bitrate's logical max
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 3d346d85d45a..1653f7e1ae99 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4432,6 +4432,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE);
if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) {
ret = -EIO;
+ kfree(entry);
goto err;
}
entry->app_arch = app_arch;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5743588aa52b..efbecb6e1dd0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -4068,7 +4068,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
INIT_LIST_HEAD(&md->part);
md->usage = 1;
- ret = mmc_init_queue(&md->queue, card, &md->lock, subname, area_type);
+ ret = mmc_init_queue(&md->queue, card, NULL, subname, area_type);
if (ret)
goto err_putdisk;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 75a51bd2fc0b..f5dbb67ba929 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -724,15 +724,13 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
if (wait) {
/*
- * After blk_stop_queue is called, wait for all
+ * After blk_cleanup_queue is called, wait for all
* active_reqs to complete.
* Then wait for cmdq thread to exit before calling
* cmdq shutdown to avoid race between issuing
* requests and shutdown of cmdq.
*/
- spin_lock_irqsave(q->queue_lock, flags);
- blk_stop_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_cleanup_queue(q);
if (host->cmdq_ctx.active_reqs)
wait_for_completion(
@@ -757,9 +755,15 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait)
}
if (!(test_and_set_bit(MMC_QUEUE_SUSPENDED, &mq->flags))) {
- spin_lock_irqsave(q->queue_lock, flags);
- blk_stop_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ if (!wait) {
+ /* suspend/stop the queue in case of suspend */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ } else {
+ /* shutdown the queue in case of shutdown/reboot */
+ blk_cleanup_queue(q);
+ }
rc = down_trylock(&mq->thread_sem);
if (rc && !wait) {
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index 57cc6b29b2d0..9e0ccdc44d6b 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -2,6 +2,17 @@
# MMC core configuration
#
+config MMC_RING_BUFFER
+ bool "MMC_RING_BUFFER"
+ depends on MMC
+ default n
+ help
+ This enables the ring buffer tracing of significant
+ events for mmc driver to provide command history for
+ debugging purpose.
+
+ If unsure, say N.
+
config MMC_EMBEDDED_SDIO
boolean "MMC embedded SDIO device support (EXPERIMENTAL)"
help
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 2c25138f28b7..60781dd192ab 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -10,3 +10,4 @@ mmc_core-y := core.o bus.o host.o \
quirks.o slot-gpio.o
mmc_core-$(CONFIG_OF) += pwrseq.o pwrseq_simple.o pwrseq_emmc.o
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
+obj-$(CONFIG_MMC_RING_BUFFER) += ring_buffer.o
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index c894f64c2e38..a0d31ded04db 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -32,6 +32,26 @@ module_param(fail_request, charp, 0);
#endif /* CONFIG_FAIL_MMC_REQUEST */
/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
+static int mmc_ring_buffer_show(struct seq_file *s, void *data)
+{
+ struct mmc_host *mmc = s->private;
+
+ mmc_dump_trace_buffer(mmc, s);
+ return 0;
+}
+
+static int mmc_ring_buffer_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mmc_ring_buffer_show, inode->i_private);
+}
+
+static const struct file_operations mmc_ring_buffer_fops = {
+ .open = mmc_ring_buffer_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int mmc_ios_show(struct seq_file *s, void *data)
{
static const char *vdd_str[] = {
@@ -368,6 +388,11 @@ void mmc_add_host_debugfs(struct mmc_host *host)
&host->cmdq_thist_enabled))
goto err_node;
+#ifdef CONFIG_MMC_RING_BUFFER
+ if (!debugfs_create_file("ring_buffer", S_IRUSR,
+ root, host, &mmc_ring_buffer_fops))
+ goto err_node;
+#endif
#ifdef CONFIG_MMC_CLKGATE
if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
root, &host->clk_delay))
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index f6a54a8e1076..333f691a73c7 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -26,6 +26,8 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/ring_buffer.h>
+
#include <linux/mmc/slot-gpio.h>
#include "core.h"
@@ -869,6 +871,7 @@ int mmc_add_host(struct mmc_host *host)
mmc_add_host_debugfs(host);
#endif
mmc_host_clk_sysfs_init(host);
+ mmc_trace_init(host);
err = sysfs_create_group(&host->class_dev.kobj, &clk_scaling_attr_grp);
if (err)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 449514bae4f3..414877874190 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2635,6 +2635,7 @@ static int mmc_suspend(struct mmc_host *host)
int err;
ktime_t start = ktime_get();
+ MMC_TRACE(host, "%s: Enter\n", __func__);
err = _mmc_suspend(host, true);
if (!err) {
pm_runtime_disable(&host->card->dev);
@@ -2643,6 +2644,7 @@ static int mmc_suspend(struct mmc_host *host)
trace_mmc_suspend(mmc_hostname(host), err,
ktime_to_us(ktime_sub(ktime_get(), start)));
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
@@ -2718,6 +2720,7 @@ static int mmc_resume(struct mmc_host *host)
int err = 0;
ktime_t start = ktime_get();
+ MMC_TRACE(host, "%s: Enter\n", __func__);
if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
err = _mmc_resume(host);
pm_runtime_set_active(&host->card->dev);
@@ -2727,7 +2730,7 @@ static int mmc_resume(struct mmc_host *host)
trace_mmc_resume(mmc_hostname(host), err,
ktime_to_us(ktime_sub(ktime_get(), start)));
-
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
diff --git a/drivers/mmc/core/ring_buffer.c b/drivers/mmc/core/ring_buffer.c
new file mode 100644
index 000000000000..83945e1cae40
--- /dev/null
+++ b/drivers/mmc/core/ring_buffer.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mmc/ring_buffer.h>
+#include <linux/mmc/host.h>
+
+void mmc_stop_tracing(struct mmc_host *mmc)
+{
+ mmc->trace_buf.stop_tracing = true;
+}
+
+void mmc_trace_write(struct mmc_host *mmc,
+ const char *fmt, ...)
+{
+ unsigned int idx;
+ va_list args;
+ char *event;
+ unsigned long flags;
+ char str[MMC_TRACE_EVENT_SZ];
+
+ if (unlikely(!mmc->trace_buf.data) ||
+ unlikely(mmc->trace_buf.stop_tracing))
+ return;
+
+ /*
+ * Here an increment and modulus is used to keep
+ * index within array bounds. The cast to unsigned is
+ * necessary so increment and rolover wraps to 0 correctly
+ */
+ spin_lock_irqsave(&mmc->trace_buf.trace_lock, flags);
+ mmc->trace_buf.wr_idx += 1;
+ idx = ((unsigned int)mmc->trace_buf.wr_idx) &
+ (MMC_TRACE_RBUF_NUM_EVENTS - 1);
+ spin_unlock_irqrestore(&mmc->trace_buf.trace_lock, flags);
+
+ /* Catch some unlikely machine specific wrap-around bug */
+ if (unlikely(idx > (MMC_TRACE_RBUF_NUM_EVENTS - 1))) {
+ pr_err("%s: %s: Invalid idx:%d for mmc trace, tracing stopped !\n",
+ mmc_hostname(mmc), __func__, idx);
+ mmc_stop_tracing(mmc);
+ return;
+ }
+
+ event = &mmc->trace_buf.data[idx * MMC_TRACE_EVENT_SZ];
+ va_start(args, fmt);
+ snprintf(str, MMC_TRACE_EVENT_SZ, "<%d> %lld: %s: %s",
+ raw_smp_processor_id(),
+ ktime_to_ns(ktime_get()),
+ mmc_hostname(mmc), fmt);
+ memset(event, '\0', MMC_TRACE_EVENT_SZ);
+ vscnprintf(event, MMC_TRACE_EVENT_SZ, str, args);
+ va_end(args);
+}
+
+void mmc_trace_init(struct mmc_host *mmc)
+{
+ BUILD_BUG_ON_NOT_POWER_OF_2(MMC_TRACE_RBUF_NUM_EVENTS);
+
+ mmc->trace_buf.data = (char *)
+ __get_free_pages(GFP_KERNEL|__GFP_ZERO,
+ MMC_TRACE_RBUF_SZ_ORDER);
+
+ if (!mmc->trace_buf.data) {
+ pr_err("%s: %s: Unable to allocate trace for mmc\n",
+ __func__, mmc_hostname(mmc));
+ return;
+ }
+
+ spin_lock_init(&mmc->trace_buf.trace_lock);
+ mmc->trace_buf.wr_idx = -1;
+}
+
+void mmc_trace_free(struct mmc_host *mmc)
+{
+ if (mmc->trace_buf.data)
+ free_pages((unsigned long)mmc->trace_buf.data,
+ MMC_TRACE_RBUF_SZ_ORDER);
+}
+
+void mmc_dump_trace_buffer(struct mmc_host *mmc, struct seq_file *s)
+{
+ unsigned int idx, cur_idx;
+ unsigned int N = MMC_TRACE_RBUF_NUM_EVENTS - 1;
+ char *event;
+ unsigned long flags;
+
+ if (!mmc->trace_buf.data)
+ return;
+
+ spin_lock_irqsave(&mmc->trace_buf.trace_lock, flags);
+ idx = ((unsigned int)mmc->trace_buf.wr_idx) & N;
+ cur_idx = (idx + 1) & N;
+
+ do {
+ event = &mmc->trace_buf.data[cur_idx * MMC_TRACE_EVENT_SZ];
+ if (s)
+ seq_printf(s, "%s", (char *)event);
+ else
+ pr_err("%s", (char *)event);
+ cur_idx = (cur_idx + 1) & N;
+ if (cur_idx == idx) {
+ event =
+ &mmc->trace_buf.data[cur_idx * MMC_TRACE_EVENT_SZ];
+ if (s)
+ seq_printf(s, "latest_event: %s",
+ (char *)event);
+ else
+ pr_err("latest_event: %s", (char *)event);
+ break;
+ }
+ } while (1);
+ spin_unlock_irqrestore(&mmc->trace_buf.trace_lock, flags);
+}
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 7b84030ffe92..7e7d7eb4da2a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1222,11 +1222,13 @@ static int mmc_sd_suspend(struct mmc_host *host)
{
int err;
+ MMC_TRACE(host, "%s: Enter\n", __func__);
err = _mmc_sd_suspend(host);
if (!err) {
pm_runtime_disable(&host->card->dev);
pm_runtime_set_suspended(&host->card->dev);
}
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
@@ -1292,12 +1294,14 @@ static int mmc_sd_resume(struct mmc_host *host)
{
int err = 0;
+ MMC_TRACE(host, "%s: Enter\n", __func__);
if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
err = _mmc_sd_resume(host);
pm_runtime_set_active(&host->card->dev);
pm_runtime_mark_last_busy(&host->card->dev);
}
pm_runtime_enable(&host->card->dev);
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 5fedab49cf34..13a2f2d14d12 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -998,6 +998,7 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/
static int mmc_sdio_suspend(struct mmc_host *host)
{
+ MMC_TRACE(host, "%s: Enter\n", __func__);
mmc_claim_host(host);
if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
@@ -1013,7 +1014,7 @@ static int mmc_sdio_suspend(struct mmc_host *host)
}
mmc_release_host(host);
-
+ MMC_TRACE(host, "%s: Exit\n", __func__);
return 0;
}
@@ -1024,6 +1025,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
+ MMC_TRACE(host, "%s: Enter\n", __func__);
/* Basic card reinitialization. */
mmc_claim_host(host);
@@ -1079,6 +1081,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
host->pm_flags &= ~MMC_PM_KEEP_POWER;
host->pm_flags &= ~MMC_PM_WAKE_SDIO_IRQ;
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 52427815722b..d712f29da9f1 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -198,6 +198,14 @@ static void cmdq_dumpregs(struct cmdq_host *cq_host)
{
struct mmc_host *mmc = cq_host->mmc;
+ MMC_TRACE(mmc,
+ "%s: 0x0C=0x%08x 0x10=0x%08x 0x14=0x%08x 0x18=0x%08x 0x28=0x%08x 0x2C=0x%08x 0x30=0x%08x 0x34=0x%08x 0x54=0x%08x 0x58=0x%08x 0x5C=0x%08x 0x48=0x%08x\n",
+ __func__, cmdq_readl(cq_host, CQCTL), cmdq_readl(cq_host, CQIS),
+ cmdq_readl(cq_host, CQISTE), cmdq_readl(cq_host, CQISGE),
+ cmdq_readl(cq_host, CQTDBR), cmdq_readl(cq_host, CQTCN),
+ cmdq_readl(cq_host, CQDQS), cmdq_readl(cq_host, CQDPT),
+ cmdq_readl(cq_host, CQTERRI), cmdq_readl(cq_host, CQCRI),
+ cmdq_readl(cq_host, CQCRA), cmdq_readl(cq_host, CQCRDCT));
pr_err(DRV_NAME ": ========== REGISTER DUMP (%s)==========\n",
mmc_hostname(mmc));
@@ -426,6 +434,7 @@ static int cmdq_enable(struct mmc_host *mmc)
pm_ref_count:
cmdq_runtime_pm_put(cq_host);
out:
+ MMC_TRACE(mmc, "%s: CQ enabled err: %d\n", __func__, err);
return err;
}
@@ -443,6 +452,7 @@ static void cmdq_disable_nosync(struct mmc_host *mmc, bool soft)
cq_host->enabled = false;
mmc_host_set_cq_disable(mmc);
+ MMC_TRACE(mmc, "%s: CQ disabled\n", __func__);
}
static void cmdq_disable(struct mmc_host *mmc, bool soft)
@@ -525,6 +535,12 @@ static void cmdq_prep_task_desc(struct mmc_request *mrq,
REL_WRITE(!!(req_flags & REL_WR)) |
BLK_COUNT(mrq->cmdq_req->data.blocks) |
BLK_ADDR((u64)mrq->cmdq_req->blk_addr);
+
+ MMC_TRACE(mrq->host,
+ "%s: Task: 0x%08x | Args: 0x%08x | cnt: 0x%08x\n", __func__,
+ lower_32_bits(*data),
+ upper_32_bits(*data),
+ mrq->cmdq_req->data.blocks);
}
static int cmdq_dma_map(struct mmc_host *host, struct mmc_request *mrq)
@@ -665,6 +681,11 @@ static void cmdq_prep_dcmd_desc(struct mmc_host *mmc,
dataddr = (__le64 __force *)(desc + 4);
dataddr[0] = cpu_to_le64((u64)mrq->cmd->arg);
cmdq_log_task_desc_history(cq_host, *task_desc, true);
+ MMC_TRACE(mrq->host,
+ "%s: DCMD: Task: 0x%08x | Args: 0x%08x\n",
+ __func__,
+ lower_32_bits(*task_desc),
+ upper_32_bits(*task_desc));
}
static void cmdq_pm_qos_vote(struct sdhci_host *host, struct mmc_request *mrq)
@@ -743,6 +764,7 @@ ring_doorbell:
cmdq_dumpregs(cq_host);
BUG_ON(1);
}
+ MMC_TRACE(mmc, "%s: tag: %d\n", __func__, tag);
cmdq_writel(cq_host, 1 << tag, CQTDBR);
/* Commit the doorbell write immediately */
wmb();
@@ -785,6 +807,8 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
if (!status && !err)
return IRQ_NONE;
+ MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n",
+ __func__, status, err);
if (err || (status & CQIS_RED)) {
err_info = cmdq_readl(cq_host, CQTERRI);
@@ -920,7 +944,9 @@ skip_cqterri:
/* complete the corresponding mrq */
pr_debug("%s: completing tag -> %lu\n",
mmc_hostname(mmc), tag);
- cmdq_finish_data(mmc, tag);
+ MMC_TRACE(mmc, "%s: completing tag -> %lu\n",
+ __func__, tag);
+ cmdq_finish_data(mmc, tag);
}
}
@@ -997,6 +1023,8 @@ static int cmdq_halt(struct mmc_host *mmc, bool halt)
retries--;
continue;
} else {
+ MMC_TRACE(mmc, "%s: halt done , retries: %d\n",
+ __func__, retries);
/* halt done: re-enable legacy interrupts */
if (cq_host->ops->clear_set_irqs)
cq_host->ops->clear_set_irqs(mmc,
@@ -1014,6 +1042,7 @@ static int cmdq_halt(struct mmc_host *mmc, bool halt)
cq_host->ops->set_data_timeout(mmc, 0xf);
if (cq_host->ops->clear_set_irqs)
cq_host->ops->clear_set_irqs(mmc, true);
+ MMC_TRACE(mmc, "%s: unhalt done\n", __func__);
cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT,
CQCTL);
}
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index abf2ae2020c9..2ef459582aae 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -102,7 +102,7 @@ int sdhci_msm_ice_init(struct sdhci_host *host)
struct sdhci_msm_host *msm_host = pltfm_host->priv;
int err = 0;
- if (msm_host->ice.vops->config) {
+ if (msm_host->ice.vops->init) {
err = msm_host->ice.vops->init(msm_host->ice.pdev,
msm_host,
sdhci_msm_ice_error_cb);
@@ -148,9 +148,10 @@ int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
req = mrq->req;
if (req) {
lba = req->__sector;
- if (msm_host->ice.vops->config) {
- err = msm_host->ice.vops->config(msm_host->ice.pdev,
- req, &ice_set);
+ if (msm_host->ice.vops->config_start) {
+ err = msm_host->ice.vops->config_start(
+ msm_host->ice.pdev,
+ req, &ice_set, false);
if (err) {
pr_err("%s: ice config failed %d\n",
mmc_hostname(host->mmc), err);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 203daf3bd5eb..466e0a2c8483 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2,7 +2,7 @@
* drivers/mmc/host/sdhci-msm.c - Qualcomm Technologies, Inc. MSM SDHCI Platform
* driver source file
*
- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3293,6 +3293,11 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
if (host->cq_host)
sdhci_msm_cmdq_dump_debug_ram(host);
+ MMC_TRACE(host->mmc, "Data cnt: 0x%08x | Fifo cnt: 0x%08x\n",
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_DATA_CNT),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_FIFO_CNT));
pr_info("Data cnt: 0x%08x | Fifo cnt: 0x%08x | Int sts: 0x%08x\n",
sdhci_msm_readl_relaxed(host,
msm_host_offset->CORE_MCI_DATA_CNT),
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 08822464d82f..3fd564388720 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -111,6 +111,17 @@ static void sdhci_dump_state(struct sdhci_host *host)
static void sdhci_dumpregs(struct sdhci_host *host)
{
+ MMC_TRACE(host->mmc,
+ "%s: 0x04=0x%08x 0x06=0x%08x 0x0E=0x%08x 0x30=0x%08x 0x34=0x%08x 0x38=0x%08x\n",
+ __func__,
+ sdhci_readw(host, SDHCI_BLOCK_SIZE),
+ sdhci_readw(host, SDHCI_BLOCK_COUNT),
+ sdhci_readw(host, SDHCI_COMMAND),
+ sdhci_readl(host, SDHCI_INT_STATUS),
+ sdhci_readl(host, SDHCI_INT_ENABLE),
+ sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
+ mmc_stop_tracing(host->mmc);
+
pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
mmc_hostname(host->mmc));
@@ -1013,6 +1024,11 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
/* Set the DMA boundary value and block size */
sdhci_set_blk_size_reg(host, data->blksz, SDHCI_DEFAULT_BOUNDARY_ARG);
sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
+ MMC_TRACE(host->mmc,
+ "%s: 0x28=0x%08x 0x3E=0x%08x 0x06=0x%08x\n", __func__,
+ sdhci_readb(host, SDHCI_HOST_CONTROL),
+ sdhci_readw(host, SDHCI_HOST_CONTROL2),
+ sdhci_readw(host, SDHCI_BLOCK_COUNT));
}
static void sdhci_set_transfer_mode(struct sdhci_host *host,
@@ -1071,6 +1087,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
mode |= SDHCI_TRNS_DMA;
sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
+ MMC_TRACE(host->mmc, "%s: 0x00=0x%08x 0x0C=0x%08x\n", __func__,
+ sdhci_readw(host, SDHCI_ARGUMENT2),
+ sdhci_readw(host, SDHCI_TRANSFER_MODE));
}
static void sdhci_finish_data(struct sdhci_host *host)
@@ -1082,6 +1101,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
data = host->data;
host->data = NULL;
+ MMC_TRACE(host->mmc, "%s: 0x24=0x%08x\n", __func__,
+ sdhci_readl(host, SDHCI_PRESENT_STATE));
if (host->flags & SDHCI_REQ_USE_DMA) {
if (host->flags & SDHCI_USE_ADMA)
sdhci_adma_table_post(host, data);
@@ -1210,6 +1231,11 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
if (cmd->data)
host->data_start_time = ktime_get();
trace_mmc_cmd_rw_start(cmd->opcode, cmd->arg, cmd->flags);
+ MMC_TRACE(host->mmc,
+ "%s: updated 0x8=0x%08x 0xC=0x%08x 0xE=0x%08x\n", __func__,
+ sdhci_readl(host, SDHCI_ARGUMENT),
+ sdhci_readw(host, SDHCI_TRANSFER_MODE),
+ sdhci_readw(host, SDHCI_COMMAND));
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}
EXPORT_SYMBOL_GPL(sdhci_send_command);
@@ -1231,8 +1257,14 @@ static void sdhci_finish_command(struct sdhci_host *host)
sdhci_readb(host,
SDHCI_RESPONSE + (3-i)*4-1);
}
+ MMC_TRACE(host->mmc,
+ "%s: resp 0: 0x%08x resp 1: 0x%08x resp 2: 0x%08x resp 3: 0x%08x\n",
+ __func__, host->cmd->resp[0], host->cmd->resp[1],
+ host->cmd->resp[2], host->cmd->resp[3]);
} else {
host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
+ MMC_TRACE(host->mmc, "%s: resp 0: 0x%08x\n",
+ __func__, host->cmd->resp[0]);
}
}
@@ -3169,6 +3201,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
goto out;
}
+ MMC_TRACE(host->mmc,
+ "%s: intmask: 0x%x\n", __func__, intmask);
+
if (intmask & SDHCI_INT_AUTO_CMD_ERR)
host->auto_cmd_err_sts = sdhci_readw(host,
SDHCI_AUTO_CMD_ERR);
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index e7205546fa6b..a0dd6bd8165c 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -16,7 +16,6 @@
*/
#include "hif.h"
-#include "pci.h"
#include "ce.h"
#include "debug.h"
@@ -63,56 +62,56 @@ static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n);
+ ar->bus_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n);
}
static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS);
+ return ar->bus_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS);
}
static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
+ ar->bus_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
}
static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS);
+ return ar->bus_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS);
}
static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS);
+ return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS);
}
static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr);
+ ar->bus_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr);
}
static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n);
+ ar->bus_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n);
}
static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32((ar),
+ u32 ctrl1_addr = ar->bus_read32((ar),
(ce_ctrl_addr) + CE_CTRL1_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
(ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) |
CE_CTRL1_DMAX_LENGTH_SET(n));
}
@@ -121,9 +120,9 @@ static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
(ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) |
CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n));
}
@@ -132,9 +131,9 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
(ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) |
CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n));
}
@@ -142,30 +141,30 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS);
+ return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS);
}
static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
u32 addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr);
+ ar->bus_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr);
}
static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n);
+ ar->bus_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n);
}
static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
(addr & ~SRC_WATERMARK_HIGH_MASK) |
SRC_WATERMARK_HIGH_SET(n));
}
@@ -174,9 +173,9 @@ static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
(addr & ~SRC_WATERMARK_LOW_MASK) |
SRC_WATERMARK_LOW_SET(n));
}
@@ -185,9 +184,9 @@ static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
(addr & ~DST_WATERMARK_HIGH_MASK) |
DST_WATERMARK_HIGH_SET(n));
}
@@ -196,9 +195,9 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
(addr & ~DST_WATERMARK_LOW_MASK) |
DST_WATERMARK_LOW_SET(n));
}
@@ -206,50 +205,50 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
+ u32 host_ie_addr = ar->bus_read32(ar,
ce_ctrl_addr + HOST_IE_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
host_ie_addr | HOST_IE_COPY_COMPLETE_MASK);
}
static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
+ u32 host_ie_addr = ar->bus_read32(ar,
ce_ctrl_addr + HOST_IE_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK);
}
static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
+ u32 host_ie_addr = ar->bus_read32(ar,
ce_ctrl_addr + HOST_IE_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
host_ie_addr & ~CE_WATERMARK_MASK);
}
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
+ u32 misc_ie_addr = ar->bus_read32(ar,
ce_ctrl_addr + MISC_IE_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
misc_ie_addr | CE_ERROR_MASK);
}
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
+ u32 misc_ie_addr = ar->bus_read32(ar,
ce_ctrl_addr + MISC_IE_ADDRESS);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
+ ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
misc_ie_addr & ~CE_ERROR_MASK);
}
@@ -257,7 +256,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
+ ar->bus_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
}
/*
@@ -267,7 +266,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
*/
int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
- u32 buffer,
+ dma_addr_t buffer,
unsigned int nbytes,
unsigned int transfer_id,
unsigned int flags)
@@ -325,11 +324,10 @@ exit:
void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
{
struct ath10k *ar = pipe->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_ring *src_ring = pipe->src_ring;
u32 ctrl_addr = pipe->ctrl_addr;
- lockdep_assert_held(&ar_pci->ce_lock);
+ lockdep_assert_held(&ar->ce_lock);
/*
* This function must be called only if there is an incomplete
@@ -351,19 +349,18 @@ void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
- u32 buffer,
+ dma_addr_t buffer,
unsigned int nbytes,
unsigned int transfer_id,
unsigned int flags)
{
struct ath10k *ar = ce_state->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
ret = ath10k_ce_send_nolock(ce_state, per_transfer_context,
buffer, nbytes, transfer_id, flags);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -371,14 +368,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
{
struct ath10k *ar = pipe->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int delta;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
delta = CE_RING_DELTA(pipe->src_ring->nentries_mask,
pipe->src_ring->write_index,
pipe->src_ring->sw_index - 1);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return delta;
}
@@ -386,21 +382,20 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
{
struct ath10k *ar = pipe->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask;
unsigned int write_index = dest_ring->write_index;
unsigned int sw_index = dest_ring->sw_index;
- lockdep_assert_held(&ar_pci->ce_lock);
+ lockdep_assert_held(&ar->ce_lock);
return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
}
-int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
+int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
+ dma_addr_t paddr)
{
struct ath10k *ar = pipe->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask;
unsigned int write_index = dest_ring->write_index;
@@ -409,7 +404,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index);
u32 ctrl_addr = pipe->ctrl_addr;
- lockdep_assert_held(&ar_pci->ce_lock);
+ lockdep_assert_held(&ar->ce_lock);
if ((pipe->id != 5) &&
CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
@@ -439,15 +434,15 @@ void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
dest_ring->write_index = write_index;
}
-int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
+int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
+ dma_addr_t paddr)
{
struct ath10k *ar = pipe->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -510,14 +505,13 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
unsigned int *nbytesp)
{
struct ath10k *ar = ce_state->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
ret = ath10k_ce_completed_recv_next_nolock(ce_state,
per_transfer_contextp,
nbytesp);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -532,7 +526,6 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
unsigned int write_index;
int ret;
struct ath10k *ar;
- struct ath10k_pci *ar_pci;
dest_ring = ce_state->dest_ring;
@@ -540,9 +533,8 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
return -EIO;
ar = ce_state->ar;
- ar_pci = ath10k_pci_priv(ar);
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
nentries_mask = dest_ring->nentries_mask;
sw_index = dest_ring->sw_index;
@@ -570,7 +562,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
ret = -EIO;
}
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -638,7 +630,6 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
unsigned int write_index;
int ret;
struct ath10k *ar;
- struct ath10k_pci *ar_pci;
src_ring = ce_state->src_ring;
@@ -646,9 +637,8 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
return -EIO;
ar = ce_state->ar;
- ar_pci = ath10k_pci_priv(ar);
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
nentries_mask = src_ring->nentries_mask;
sw_index = src_ring->sw_index;
@@ -679,7 +669,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
ret = -EIO;
}
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -688,13 +678,12 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp)
{
struct ath10k *ar = ce_state->ar;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
ret = ath10k_ce_completed_send_next_nolock(ce_state,
per_transfer_contextp);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
return ret;
}
@@ -707,17 +696,17 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
*/
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_ce_pipe *ce_state =
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id);
u32 ctrl_addr = ce_state->ctrl_addr;
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */
ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
HOST_IS_COPY_COMPLETE_MASK);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
if (ce_state->recv_cb)
ce_state->recv_cb(ce_state);
@@ -725,7 +714,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
if (ce_state->send_cb)
ce_state->send_cb(ce_state);
- spin_lock_bh(&ar_pci->ce_lock);
+ spin_lock_bh(&ar->ce_lock);
/*
* Misc CE interrupts are not being handled, but still need
@@ -733,7 +722,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
*/
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
- spin_unlock_bh(&ar_pci->ce_lock);
+ spin_unlock_bh(&ar->ce_lock);
}
/*
@@ -799,22 +788,22 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar)
void ath10k_ce_enable_interrupts(struct ath10k *ar)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ce_id;
/* Skip the last copy engine, CE7 the diagnostic window, as that
* uses polling and isn't initialized for interrupts.
*/
for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
- ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
+ ath10k_ce_per_engine_handler_adjust(
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id));
}
static int ath10k_ce_init_src_ring(struct ath10k *ar,
unsigned int ce_id,
const struct ce_attr *attr)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_ce_pipe *ce_state =
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id);
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
@@ -850,8 +839,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
unsigned int ce_id,
const struct ce_attr *attr)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_ce_pipe *ce_state =
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id);
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
@@ -1040,8 +1029,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
const struct ce_attr *attr)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_ce_pipe *ce_state =
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id);
int ret;
/*
@@ -1097,8 +1086,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_ce_pipe *ce_state =
+ ((struct ath10k_ce_pipe *)ar->ce_states + ce_id);
if (ce_state->src_ring) {
dma_free_coherent(ar->dev,
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index dfc098606bee..3c6dba648574 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -46,11 +46,20 @@ struct ath10k_ce_pipe;
#define CE_DESC_FLAGS_META_DATA_MASK ar->hw_values->ce_desc_meta_data_mask
#define CE_DESC_FLAGS_META_DATA_LSB ar->hw_values->ce_desc_meta_data_lsb
+#ifndef CONFIG_ATH10K_SNOC
struct ce_desc {
__le32 addr;
__le16 nbytes;
__le16 flags; /* %CE_DESC_FLAGS_ */
};
+#else
+struct ce_desc {
+ __le64 addr;
+ u16 nbytes; /* length in register map */
+ u16 flags; /* fw_metadata_high */
+ u32 toeplitz_hash_result;
+};
+#endif
struct ath10k_ce_ring {
/* Number of entries in this ring; must be power of 2 */
@@ -144,7 +153,7 @@ struct ce_attr;
*/
int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_send_context,
- u32 buffer,
+ dma_addr_t buffer,
unsigned int nbytes,
/* 14 bits */
unsigned int transfer_id,
@@ -152,7 +161,7 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
- u32 buffer,
+ dma_addr_t buffer,
unsigned int nbytes,
unsigned int transfer_id,
unsigned int flags);
@@ -164,8 +173,10 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
/*==================Recv=======================*/
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
-int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
-int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
+int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
+ dma_addr_t paddr);
+int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
+ dma_addr_t paddr);
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries);
/* recv flags */
@@ -263,6 +274,7 @@ struct ce_attr {
void (*recv_cb)(struct ath10k_ce_pipe *);
};
+#ifndef CONFIG_ATH10K_SNOC
#define SR_BA_ADDRESS 0x0000
#define SR_SIZE_ADDRESS 0x0004
#define DR_BA_ADDRESS 0x0008
@@ -383,6 +395,190 @@ struct ce_attr {
#define DST_WATERMARK_HIGH_RESET 0
#define DST_WATERMARK_ADDRESS 0x0050
+#else
+#define WCN3990_CE0_SR_BA_LOW (0x00240000)
+#define WCN3990_CE1_SR_BA_LOW (0x00241000)
+#define WCN3990_CE2_SR_BA_LOW (0x00242000)
+#define WCN3990_CE3_SR_BA_LOW (0x00243000)
+#define WCN3990_CE4_SR_BA_LOW (0x00244000)
+#define WCN3990_CE5_SR_BA_LOW (0x00245000)
+#define WCN3990_CE6_SR_BA_LOW (0x00246000)
+#define WCN3990_CE7_SR_BA_LOW (0x00247000)
+#define WCN3990_CE8_SR_BA_LOW (0x00248000)
+#define WCN3990_CE9_SR_BA_LOW (0x00249000)
+#define WCN3990_CE10_SR_BA_LOW (0x0024A000)
+#define WCN3990_CE11_SR_BA_LOW (0x0024B000)
+#define WCN3990_CE0_DR_BA_LOW (0x0024000C)
+#define WNC3990_CE0_DR_SIZE (0x00240014)
+#define WCN3990_CE0_CE_CTRL1 (0x00240018)
+#define WCN3990_CE0_HOST_IE (0x0024002C)
+#define WCN3990_CE0_HOST_IS (0x00240030)
+#define WCN3990_CE0_MISC_IE (0x00240034)
+#define WCN3990_CE0_MISC_IS (0x00240038)
+#define WCN3990_CE0_SRC_WR_INDEX (0x0024003C)
+#define WCN3990_CE0_CURRENT_SRRI (0x00240044)
+#define WCN3990_CE0_CURRENT_DRRI (0x00240048)
+#define WCN3990_CE0_SRC_WATERMARK (0x0024004C)
+#define WCN3990_CE0_DST_WATERMARK (0x00240050)
+#define WCN3990_CE0_SR_SIZE (0x00240008)
+#define HOST_IE_COPY_COMPLETE_MASK (0x00000001)
+#define WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY 0x0024C000
+#define WCN3990_CE_WRAPPER_INDEX_BASE_LOW 0x0024C004
+#define WCN3990_CE_WRAPPER_INDEX_BASE_HIGH 0x0024C008
+#define CE_CTRL1_IDX_UPD_EN 0x00080000
+
+#define WCN3990_CE_WRAPPER_BASE_ADDRESS \
+ WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY
+#define WCN3990_CE0_BASE_ADDRESS \
+ WCN3990_CE0_SR_BA_LOW
+#define WCN3990_CE1_BASE_ADDRESS \
+ WCN3990_CE1_SR_BA_LOW
+#define WCN3990_CE2_BASE_ADDRESS \
+ WCN3990_CE2_SR_BA_LOW
+#define WCN3990_CE3_BASE_ADDRESS \
+ WCN3990_CE3_SR_BA_LOW
+#define WCN3990_CE4_BASE_ADDRESS \
+ WCN3990_CE4_SR_BA_LOW
+#define WCN3990_CE5_BASE_ADDRESS \
+ WCN3990_CE5_SR_BA_LOW
+#define WCN3990_CE6_BASE_ADDRESS \
+ WCN3990_CE6_SR_BA_LOW
+#define WCN3990_CE7_BASE_ADDRESS \
+ WCN3990_CE7_SR_BA_LOW
+#define WCN3990_CE8_BASE_ADDRESS \
+ WCN3990_CE8_SR_BA_LOW
+#define WCN3990_CE9_BASE_ADDRESS \
+ WCN3990_CE9_SR_BA_LOW
+#define WCN3990_CE10_BASE_ADDRESS \
+ WCN3990_CE10_SR_BA_LOW
+#define WCN3990_CE11_BASE_ADDRESS \
+ WCN3990_CE11_SR_BA_LOW
+
+#define SR_BA_ADDRESS (WCN3990_CE0_SR_BA_LOW\
+ - WCN3990_CE0_BASE_ADDRESS)
+#define SR_SIZE_ADDRESS (WCN3990_CE0_SR_SIZE \
+ - WCN3990_CE0_BASE_ADDRESS)
+#define DR_BA_ADDRESS (WCN3990_CE0_DR_BA_LOW\
+ - WCN3990_CE0_BASE_ADDRESS)
+#define DR_SIZE_ADDRESS (WNC3990_CE0_DR_SIZE\
+ - WCN3990_CE0_BASE_ADDRESS)
+#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW \
+ (WCN3990_CE_WRAPPER_INDEX_BASE_LOW - WCN3990_CE_WRAPPER_BASE_ADDRESS)
+
+#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH \
+ (WCN3990_CE_WRAPPER_INDEX_BASE_HIGH - WCN3990_CE_WRAPPER_BASE_ADDRESS)
+
+#define CE_RRI_LOW (WCN3990_CE_WRAPPER_BASE_ADDRESS \
+ + WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW)
+
+#define CE_RRI_HIGH (WCN3990_CE_WRAPPER_BASE_ADDRESS \
+ + WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH)
+
+#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 18
+#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 18
+
+#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00040000
+#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
+ (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
+ CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
+
+#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
+#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
+
+#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00020000
+#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
+ (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
+ CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
+#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
+ (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
+ CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
+
+#define CE_CTRL1_DMAX_LENGTH_MSB 0
+#define CE_CTRL1_DMAX_LENGTH_LSB 0
+
+#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000FFFF
+#define CE_CTRL1_DMAX_LENGTH_GET(x) \
+ (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
+#define CE_CTRL1_DMAX_LENGTH_SET(x) \
+ (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
+
+#define CE_CTRL1_ADDRESS (WCN3990_CE0_CE_CTRL1 \
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define HOST_IE_ADDRESS (WCN3990_CE0_HOST_IE\
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
+#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
+#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
+#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
+#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
+#define HOST_IS_ADDRESS (WCN3990_CE0_HOST_IS \
+ - WCN3990_CE0_BASE_ADDRESS)
+#define MISC_IE_ADDRESS (WCN3990_CE0_MISC_IE \
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define MISC_IS_AXI_ERR_MASK 0x00000100
+#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
+#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
+#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
+#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
+#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
+#define MISC_IS_ADDRESS (WCN3990_CE0_MISC_IS \
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define SR_WR_INDEX_ADDRESS 0x3C
+#define DST_WR_INDEX_ADDRESS 0x40
+
+#define CURRENT_SRRI_ADDRESS (WCN3990_CE0_CURRENT_SRRI\
+ - WCN3990_CE0_BASE_ADDRESS)
+#define CURRENT_DRRI_ADDRESS (WCN3990_CE0_CURRENT_DRRI\
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define SRC_WATERMARK_LOW_MSB 0
+#define SRC_WATERMARK_LOW_LSB 16
+
+#define SRC_WATERMARK_LOW_MASK 0xffff0000
+#define SRC_WATERMARK_LOW_GET(x) \
+ (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
+#define SRC_WATERMARK_LOW_SET(x) \
+ (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
+
+#define SRC_WATERMARK_LOW_RESET 0
+#define SRC_WATERMARK_HIGH_MSB 15
+#define SRC_WATERMARK_HIGH_LSB 0
+#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
+#define SRC_WATERMARK_HIGH_GET(x) \
+ (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
+#define SRC_WATERMARK_HIGH_SET(x) \
+ (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
+
+#define SRC_WATERMARK_HIGH_RESET 0
+#define SRC_WATERMARK_ADDRESS (WCN3990_CE0_SRC_WATERMARK\
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define DST_WATERMARK_LOW_LSB 16
+#define DST_WATERMARK_LOW_MASK 0xffff0000
+#define DST_WATERMARK_LOW_SET(x) \
+ (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
+#define DST_WATERMARK_LOW_RESET 0
+#define DST_WATERMARK_HIGH_MSB 15
+#define DST_WATERMARK_HIGH_LSB 0
+#define DST_WATERMARK_HIGH_MASK 0x0000ffff
+#define DST_WATERMARK_HIGH_GET(x) \
+ (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
+#define DST_WATERMARK_HIGH_SET(x) \
+ (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
+#define DST_WATERMARK_HIGH_RESET 0
+#define DST_WATERMARK_ADDRESS (WCN3990_CE0_DST_WATERMARK \
+ - WCN3990_CE0_BASE_ADDRESS)
+
+#define BITS0_TO_31(val) ((uint32_t)((uint64_t)(val)\
+ & (uint64_t)(0xFFFFFFFF)))
+#define BITS32_TO_35(val) ((uint32_t)(((uint64_t)(val)\
+ & (uint64_t)(0xF00000000)) >> 32))
+#endif
+
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
{
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
@@ -425,7 +621,7 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
#define CE_INTERRUPT_SUMMARY(ar) \
CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \
- ath10k_pci_read32((ar), CE_WRAPPER_BASE_ADDRESS + \
+ ar->bus_read32((ar), CE_WRAPPER_BASE_ADDRESS + \
CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS))
#endif /* _CE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 21ae8d663e67..bf77ac66c79e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1560,10 +1560,22 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
+/* WAR: WCN3990 fw loading is done by PIL, assign WMI/HTT version */
+static inline void init_fw_param(struct ath10k *ar,
+ struct ath10k_fw_file *fw_file)
+{
+ if (QCA_REV_WCN3990(ar)) {
+ fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_HL_1_0;
+ fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
+ }
+}
+
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
+ init_fw_param(ar, &ar->normal_mode_fw.fw_file);
+
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
@@ -1666,6 +1678,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
ar->max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
@@ -1712,6 +1725,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 521f1c55c19e..9eede4266721 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -74,6 +74,7 @@ struct ath10k;
enum ath10k_bus {
ATH10K_BUS_PCI,
ATH10K_BUS_AHB,
+ ATH10K_BUS_SNOC,
};
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -83,6 +84,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "pci";
case ATH10K_BUS_AHB:
return "ahb";
+ case ATH10K_BUS_SNOC:
+ return "snoc";
}
return "unknown";
@@ -778,7 +781,7 @@ struct ath10k {
} scan;
struct {
- struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
} mac;
/* should never be NULL; needed for regular htt rx */
@@ -912,6 +915,10 @@ struct ath10k {
struct net_device napi_dev;
struct napi_struct napi;
+ void (*bus_write32)(void *ar, u32 offset, u32 value);
+ u32 (*bus_read32)(void *ar, u32 offset);
+ spinlock_t ce_lock; /* lock for CE access */
+ void *ce_states;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index c458fa96a6d4..b1db01a167ac 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -38,6 +38,7 @@ enum ath10k_debug_mask {
ATH10K_DBG_WMI_PRINT = 0x00002000,
ATH10K_DBG_PCI_PS = 0x00004000,
ATH10K_DBG_AHB = 0x00008000,
+ ATH10K_DBG_SNOC = 0x00009000,
ATH10K_DBG_ANY = 0xffffffff,
};
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index b2566b06e1e1..9e79d52e18cf 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -74,9 +74,9 @@ struct ath10k_hif_ops {
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
- u32 (*read32)(struct ath10k *ar, u32 address);
+ u32 (*read32)(void *ar, u32 address);
- void (*write32)(struct ath10k *ar, u32 address, u32 value);
+ void (*write32)(void *ar, u32 address, u32 value);
/* Power up the device and enter BMI transfer mode for FW download */
int (*power_up)(struct ath10k *ar);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 961ef0626680..ed6ac39cd49d 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -27,6 +27,7 @@
#define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX
#define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
+#define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
/* when under memory pressure rx ring refill may fail and needs a retry */
#define HTT_RX_RING_REFILL_RETRY_MS 50
@@ -471,7 +472,15 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
*/
htt->rx_ring.size = HTT_RX_RING_SIZE;
htt->rx_ring.size_mask = htt->rx_ring.size - 1;
- htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
+
+ switch (ar->hw_rev) {
+ case ATH10K_HW_WCN3990:
+ htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC;
+ break;
+ default:
+ htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
+ break;
+ }
if (!is_power_of_2(htt->rx_ring.size)) {
ath10k_warn(ar, "htt rx ring size is not power of 2\n");
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 675e75d66db2..4332a27dfa9a 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -138,6 +138,32 @@ const struct ath10k_hw_regs qca4019_regs = {
.pcie_intr_clr_address = 0x00000010,
};
+const struct ath10k_hw_regs wcn3990_regs = {
+ .rtc_soc_base_address = 0x00000000,
+ .rtc_wmac_base_address = 0x00000000,
+ .soc_core_base_address = 0x00000000,
+ .ce_wrapper_base_address = 0x0024C000,
+ .soc_global_reset_address = 0x00000008,
+ .ce0_base_address = 0x00240000,
+ .ce1_base_address = 0x00241000,
+ .ce2_base_address = 0x00242000,
+ .ce3_base_address = 0x00243000,
+ .ce4_base_address = 0x00244000,
+ .ce5_base_address = 0x00245000,
+ .ce6_base_address = 0x00246000,
+ .ce7_base_address = 0x00247000,
+ .ce8_base_address = 0x00248000,
+ .ce9_base_address = 0x00249000,
+ .ce10_base_address = 0x0024A000,
+ .ce11_base_address = 0x0024B000,
+ .soc_chip_id_address = 0x000000f0,
+ .soc_reset_control_si0_rst_mask = 0x00000001,
+ .soc_reset_control_ce_rst_mask = 0x00000100,
+ .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
+ .ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
+ .pcie_intr_fw_mask = 0x00100000,
+};
+
const struct ath10k_hw_values qca988x_values = {
.rtc_state_val_on = 3,
.ce_count = 8,
@@ -181,6 +207,15 @@ const struct ath10k_hw_values qca4019_values = {
.ce_desc_meta_data_lsb = 4,
};
+const struct ath10k_hw_values wcn3990_values = {
+ .rtc_state_val_on = 5,
+ .ce_count = 12,
+ .msi_assign_ce_max = 12,
+ .num_target_ce_config_wlan = 12,
+ .ce_desc_meta_data_mask = 0xFFF0,
+ .ce_desc_meta_data_lsb = 4,
+};
+
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
{
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 6038b7486f1d..b7d9c23e17fa 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -184,6 +184,7 @@ enum ath10k_fw_wmi_op_version {
ATH10K_FW_WMI_OP_VERSION_TLV = 4,
ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
ATH10K_FW_WMI_OP_VERSION_10_4 = 6,
+ ATH10K_FW_WMI_OP_VERSION_HL_1_0 = 7,
/* keep last */
ATH10K_FW_WMI_OP_VERSION_MAX,
@@ -224,12 +225,14 @@ enum ath10k_hw_rev {
ATH10K_HW_QCA9377,
ATH10K_HW_QCA4019,
ATH10K_HW_QCA9887,
+ ATH10K_HW_WCN3990,
};
struct ath10k_hw_regs {
u32 rtc_soc_base_address;
u32 rtc_wmac_base_address;
u32 soc_core_base_address;
+ u32 soc_global_reset_address;
u32 ce_wrapper_base_address;
u32 ce0_base_address;
u32 ce1_base_address;
@@ -239,6 +242,10 @@ struct ath10k_hw_regs {
u32 ce5_base_address;
u32 ce6_base_address;
u32 ce7_base_address;
+ u32 ce8_base_address;
+ u32 ce9_base_address;
+ u32 ce10_base_address;
+ u32 ce11_base_address;
u32 soc_reset_control_si0_rst_mask;
u32 soc_reset_control_ce_rst_mask;
u32 soc_chip_id_address;
@@ -256,6 +263,7 @@ extern const struct ath10k_hw_regs qca988x_regs;
extern const struct ath10k_hw_regs qca6174_regs;
extern const struct ath10k_hw_regs qca99x0_regs;
extern const struct ath10k_hw_regs qca4019_regs;
+extern const struct ath10k_hw_regs wcn3990_regs;
struct ath10k_hw_values {
u32 rtc_state_val_on;
@@ -271,6 +279,7 @@ extern const struct ath10k_hw_values qca6174_values;
extern const struct ath10k_hw_values qca99x0_values;
extern const struct ath10k_hw_values qca9888_values;
extern const struct ath10k_hw_values qca4019_values;
+extern const struct ath10k_hw_values wcn3990_values;
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
@@ -283,6 +292,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
#define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
+#define QCA_REV_WCN3990(ar) ((ar)->hw_rev == ATH10K_HW_WCN3990)
/* Known peculiarities:
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
@@ -516,6 +526,11 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
#define TARGET_TLV_NUM_WOW_PATTERNS 22
+/* Target specific defines for WMI-HL-1.0 firmware */
+#define TARGET_HL_10_TLV_NUM_PEERS 14
+#define TARGET_HL_10_TLV_AST_SKID_LIMIT 6
+#define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2
+
/* Diagnostic Window */
#define CE_DIAG_PIPE 7
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 76297d69f1ed..7a5bfeea8f3d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -531,7 +531,7 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
enum wmi_phy_mode phymode = MODE_UNKNOWN;
switch (chandef->chan->band) {
- case NL80211_BAND_2GHZ:
+ case IEEE80211_BAND_2GHZ:
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM)
@@ -554,7 +554,7 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
break;
}
break;
- case NL80211_BAND_5GHZ:
+ case IEEE80211_BAND_5GHZ:
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
phymode = MODE_11A;
@@ -2122,7 +2122,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
const struct ieee80211_rate *rates;
- enum nl80211_band band;
+ enum ieee80211_band band;
u32 ratemask;
u8 rate;
int i;
@@ -2182,7 +2182,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
- enum nl80211_band band;
+ enum ieee80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
int i, n;
@@ -2406,7 +2406,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
- enum nl80211_band band;
+ enum ieee80211_band band;
const u16 *vht_mcs_mask;
u8 ampdu_factor;
@@ -2424,7 +2424,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
arg->peer_flags |= ar->wmi.peer_flags->vht;
- if (def.chan->band == NL80211_BAND_2GHZ)
+ if (def.chan->band == IEEE80211_BAND_2GHZ)
arg->peer_flags |= ar->wmi.peer_flags->vht_2g;
arg->peer_vht_caps = vht_cap->cap;
@@ -2493,7 +2493,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
{
- return sta->supp_rates[NL80211_BAND_2GHZ] >>
+ return sta->supp_rates[IEEE80211_BAND_2GHZ] >>
ATH10K_MAC_FIRST_OFDM_RATE_IDX;
}
@@ -2504,7 +2504,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
{
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
- enum nl80211_band band;
+ enum ieee80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
enum wmi_phy_mode phymode = MODE_UNKNOWN;
@@ -2517,7 +2517,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
switch (band) {
- case NL80211_BAND_2GHZ:
+ case IEEE80211_BAND_2GHZ:
if (sta->vht_cap.vht_supported &&
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
@@ -2537,7 +2537,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
}
break;
- case NL80211_BAND_5GHZ:
+ case IEEE80211_BAND_5GHZ:
/*
* Check VHT first.
*/
@@ -2915,7 +2915,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
{
struct ieee80211_hw *hw = ar->hw;
struct ieee80211_supported_band **bands;
- enum nl80211_band band;
+ enum ieee80211_band band;
struct ieee80211_channel *channel;
struct wmi_scan_chan_list_arg arg = {0};
struct wmi_channel_arg *ch;
@@ -2927,7 +2927,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
bands = hw->wiphy->bands;
- for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!bands[band])
continue;
@@ -2946,7 +2946,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
return -ENOMEM;
ch = arg.channels;
- for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!bands[band])
continue;
@@ -2984,7 +2984,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
/* FIXME: why use only legacy modes, why not any
* HT/VHT modes? Would that even make any
* difference? */
- if (channel->band == NL80211_BAND_2GHZ)
+ if (channel->band == IEEE80211_BAND_2GHZ)
ch->mode = MODE_11G;
else
ch->mode = MODE_11A;
@@ -3899,16 +3899,12 @@ void __ath10k_scan_finish(struct ath10k *ar)
break;
case ATH10K_SCAN_RUNNING:
case ATH10K_SCAN_ABORTING:
- if (!ar->scan.is_roc) {
- struct cfg80211_scan_info info = {
- .aborted = (ar->scan.state ==
- ATH10K_SCAN_ABORTING),
- };
-
- ieee80211_scan_completed(ar->hw, &info);
- } else if (ar->scan.roc_notify) {
+ if (!ar->scan.is_roc)
+ ieee80211_scan_completed(ar->hw,
+ (ar->scan.state ==
+ ATH10K_SCAN_ABORTING));
+ else if (ar->scan.roc_notify)
ieee80211_remain_on_channel_expired(ar->hw);
- }
/* fall through */
case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE;
@@ -4370,11 +4366,11 @@ static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar)
vht_cap = ath10k_create_vht_cap(ar);
if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
- band = &ar->mac.sbands[NL80211_BAND_2GHZ];
+ band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
band->ht_cap = ht_cap;
}
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
- band = &ar->mac.sbands[NL80211_BAND_5GHZ];
+ band = &ar->mac.sbands[IEEE80211_BAND_5GHZ];
band->ht_cap = ht_cap;
band->vht_cap = vht_cap;
}
@@ -5722,7 +5718,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
struct ath10k_sta *arsta;
struct ieee80211_sta *sta;
struct cfg80211_chan_def def;
- enum nl80211_band band;
+ enum ieee80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
u32 changed, bw, nss, smps;
@@ -6562,14 +6558,14 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
mutex_lock(&ar->conf_mutex);
- sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
+ sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
idx -= sband->n_channels;
sband = NULL;
}
if (!sband)
- sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
+ sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
if (!sband || idx >= sband->n_channels) {
ret = -ENOENT;
@@ -6594,7 +6590,7 @@ exit:
static bool
ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
- enum nl80211_band band,
+ enum ieee80211_band band,
const struct cfg80211_bitrate_mask *mask)
{
int num_rates = 0;
@@ -6613,7 +6609,7 @@ ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
static bool
ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
- enum nl80211_band band,
+ enum ieee80211_band band,
const struct cfg80211_bitrate_mask *mask,
int *nss)
{
@@ -6662,7 +6658,7 @@ ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
static int
ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
- enum nl80211_band band,
+ enum ieee80211_band band,
const struct cfg80211_bitrate_mask *mask,
u8 *rate, u8 *nss)
{
@@ -6763,7 +6759,7 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
static bool
ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
- enum nl80211_band band,
+ enum ieee80211_band band,
const struct cfg80211_bitrate_mask *mask)
{
int i;
@@ -6815,7 +6811,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
struct ath10k *ar = arvif->ar;
- enum nl80211_band band;
+ enum ieee80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
u8 rate;
@@ -7479,7 +7475,7 @@ static const struct ieee80211_ops ath10k_ops = {
};
#define CHAN2G(_channel, _freq, _flags) { \
- .band = NL80211_BAND_2GHZ, \
+ .band = IEEE80211_BAND_2GHZ, \
.hw_value = (_channel), \
.center_freq = (_freq), \
.flags = (_flags), \
@@ -7488,7 +7484,7 @@ static const struct ieee80211_ops ath10k_ops = {
}
#define CHAN5G(_channel, _freq, _flags) { \
- .band = NL80211_BAND_5GHZ, \
+ .band = IEEE80211_BAND_5GHZ, \
.hw_value = (_channel), \
.center_freq = (_freq), \
.flags = (_flags), \
@@ -7819,7 +7815,7 @@ int ath10k_mac_register(struct ath10k *ar)
goto err_free;
}
- band = &ar->mac.sbands[NL80211_BAND_2GHZ];
+ band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels);
band->channels = channels;
@@ -7831,7 +7827,7 @@ int ath10k_mac_register(struct ath10k *ar)
band->bitrates = ath10k_g_rates;
}
- ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
+ ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
}
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
@@ -7843,12 +7839,12 @@ int ath10k_mac_register(struct ath10k *ar)
goto err_free;
}
- band = &ar->mac.sbands[NL80211_BAND_5GHZ];
+ band = &ar->mac.sbands[IEEE80211_BAND_5GHZ];
band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels);
band->channels = channels;
band->n_bitrates = ath10k_a_rates_size;
band->bitrates = ath10k_a_rates;
- ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
+ ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band;
}
ath10k_mac_setup_ht_vht_cap(ar);
@@ -7959,6 +7955,7 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) {
ar->hw->wiphy->iface_combinations =
ath10k_tlv_qcs_if_comb;
@@ -8045,8 +8042,8 @@ err_dfs_detector_exit:
ar->dfs_detector->exit(ar->dfs_detector);
err_free:
- kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
- kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
+ kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
+ kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
SET_IEEE80211_DEV(ar->hw, NULL);
return ret;
@@ -8059,8 +8056,8 @@ void ath10k_mac_unregister(struct ath10k *ar)
if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
ar->dfs_detector->exit(ar->dfs_detector);
- kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
- kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
+ kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
+ kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
SET_IEEE80211_DEV(ar->hw, NULL);
}
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 9fbeb7e5ab2d..0c250f8d45ce 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -669,14 +669,14 @@ static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset)
return val;
}
-inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value)
+inline void ath10k_pci_write32(void *ar, u32 offset, u32 value)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
ar_pci->bus_ops->write32(ar, offset, value);
}
-inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
+inline u32 ath10k_pci_read32(void *ar, u32 offset)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -3246,6 +3246,16 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ar->id.subsystem_vendor = pdev->subsystem_vendor;
ar->id.subsystem_device = pdev->subsystem_device;
+ spin_lock_init(&ar_pci->ce_lock);
+ spin_lock_init(&ar_pci->ps_lock);
+
+ ar->bus_write32 = ath10k_pci_write32;
+ ar->bus_read32 = ath10k_pci_read32;
+ ar->ce_lock = ar_pci->ce_lock;
+ ar->ce_states = ar_pci->ce_states;
+
+ setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
+ (unsigned long)ar);
setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer,
(unsigned long)ar);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 9854ad56b2de..06d0bd3993d3 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -263,11 +263,11 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
#define DIAG_ACCESS_CE_TIMEOUT_MS 10
-void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value);
+void ath10k_pci_write32(void *ar, u32 offset, u32 value);
void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val);
void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val);
-u32 ath10k_pci_read32(struct ath10k *ar, u32 offset);
+u32 ath10k_pci_read32(void *ar, u32 offset);
u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr);
u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr);
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 034e7a54c5b2..6260f11d4e32 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -205,12 +205,25 @@ struct rx_attention {
* descriptor.
*/
+#ifndef CONFIG_ATH10K_SNOC
struct rx_frag_info {
u8 ring0_more_count;
u8 ring1_more_count;
u8 ring2_more_count;
u8 ring3_more_count;
} __packed;
+#else
+struct rx_frag_info {
+ u8 ring0_more_count;
+ u8 ring1_more_count;
+ u8 ring2_more_count;
+ u8 ring3_more_count;
+ u8 ring4_more_count;
+ u8 ring5_more_count;
+ u8 ring6_more_count;
+ u8 ring7_more_count;
+} __packed;
+#endif
/*
* ring0_more_count
@@ -465,11 +478,23 @@ struct rx_msdu_start_qca99x0 {
__le32 info2; /* %RX_MSDU_START_INFO2_ */
} __packed;
+#ifdef CONFIG_ATH10K_SNOC
+struct rx_msdu_start_wcn3990 {
+ __le32 info3;
+} __packed;
+#else
+struct rx_msdu_start_wcn3990 {
+} __packed;
+#endif
+
struct rx_msdu_start {
struct rx_msdu_start_common common;
union {
struct rx_msdu_start_qca99x0 qca99x0;
} __packed;
+ union {
+ struct rx_msdu_start_wcn3990 wcn3990;
+ } __packed;
} __packed;
/*
@@ -589,10 +614,18 @@ struct rx_msdu_end_qca99x0 {
__le32 info2;
} __packed;
+struct rx_msdu_end_wcn3990 {
+ __le32 rule_indication_0;
+ __le32 rule_indication_1;
+ __le32 rule_indication_2;
+ __le32 rule_indication_3;
+} __packed;
+
struct rx_msdu_end {
struct rx_msdu_end_common common;
union {
struct rx_msdu_end_qca99x0 qca99x0;
+ struct rx_msdu_end_wcn3990 wcn3990;
} __packed;
} __packed;
@@ -953,8 +986,13 @@ struct rx_ppdu_end_qca6174 {
struct rx_pkt_end {
__le32 info0; /* %RX_PKT_END_INFO0_ */
+#ifndef CONFIG_ATH10K_SNOC
__le32 phy_timestamp_1;
__le32 phy_timestamp_2;
+#else
+ __le64 phy_timestamp_1;
+ __le64 phy_timestamp_2;
+#endif
} __packed;
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_MASK 0x00003fff
@@ -990,6 +1028,9 @@ struct rx_pkt_end {
struct rx_location_info {
__le32 rx_location_info0; /* %RX_LOCATION_INFO0_ */
__le32 rx_location_info1; /* %RX_LOCATION_INFO1_ */
+#ifdef CONFIG_ATH10K_SNOC
+ __le32 rx_location_info2; /* %RX_LOCATION_INFO2_ */
+#endif
} __packed;
enum rx_phy_ppdu_end_info0 {
@@ -1080,6 +1121,25 @@ struct rx_ppdu_end_qca9984 {
__le16 info1; /* %RX_PPDU_END_INFO1_ */
} __packed;
+struct rx_timing_offset {
+ __le32 timing_offset;
+ __le32 reserved;
+};
+
+struct rx_ppdu_end_wcn3990 {
+ __le32 reserved_info_0;
+ __le32 reserved_info_1;
+ __le32 rx_antenna_info;
+ __le32 rx_coex_info;
+ __le32 rx_mpdu_cnt_info;
+ __le32 rx_bb_length;
+ __le64 phy_timestamp_tx;
+ struct rx_pkt_end rx_pkt_end;
+ struct rx_phy_ppdu_end rx_phy_ppdu_end;
+ struct rx_timing_offset rx_timing_offset;
+ struct rx_location_info rx_location_info;
+} __packed;
+
struct rx_ppdu_end {
struct rx_ppdu_end_common common;
union {
@@ -1087,6 +1147,7 @@ struct rx_ppdu_end {
struct rx_ppdu_end_qca6174 qca6174;
struct rx_ppdu_end_qca99x0 qca99x0;
struct rx_ppdu_end_qca9984 qca9984;
+ struct rx_ppdu_end_wcn3990 wcn3990;
} __packed;
} __packed;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index e64f59300a7c..7a8f9cfd8253 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -937,7 +937,12 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
ev = tb[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT];
reg = tb[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES];
- svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
+ if (QCA_REV_WCN3990(ar)) {
+ svc_bmap = (__le32 *)(skb->data +
+ WMI_TLV_TAG_STRUCT_HL_1_0_SVC_OFFSET);
+ } else {
+ svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
+ }
mem_reqs = tb[WMI_TLV_TAG_ARRAY_STRUCT];
if (!ev || !reg || !svc_bmap || !mem_reqs) {
@@ -1400,7 +1405,18 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
- cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
+ if (QCA_REV_WCN3990(ar)) {
+ cfg->num_peers = __cpu_to_le32(TARGET_HL_10_TLV_NUM_PEERS);
+ cfg->ast_skid_limit =
+ __cpu_to_le32(TARGET_HL_10_TLV_AST_SKID_LIMIT);
+ cfg->num_wds_entries =
+ __cpu_to_le32(TARGET_HL_10_TLV_NUM_WDS_ENTRIES);
+ } else {
+ cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
+ cfg->ast_skid_limit = __cpu_to_le32(0x10);
+ cfg->num_wds_entries = __cpu_to_le32(0x20);
+ }
+
if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
@@ -1412,7 +1428,6 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_peer_keys = __cpu_to_le32(2);
cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
- cfg->ast_skid_limit = __cpu_to_le32(0x10);
cfg->tx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
@@ -1428,7 +1443,6 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_mcast_table_elems = __cpu_to_le32(0);
cfg->mcast2ucast_mode = __cpu_to_le32(0);
cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
- cfg->num_wds_entries = __cpu_to_le32(0x20);
cfg->dma_burst_size = __cpu_to_le32(0);
cfg->mac_aggr_delim = __cpu_to_le32(0);
cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
@@ -3562,7 +3576,78 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
.pmf = WMI_TLV_PEER_PMF,
};
-/************/
+static const struct wmi_ops wmi_hl_1_0_ops = {
+ .rx = ath10k_wmi_tlv_op_rx,
+ .map_svc = wmi_hl_1_0_svc_map,
+ .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
+ .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
+ .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
+ .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
+ .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
+ .pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
+ .pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
+ .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
+ .pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
+ .pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
+ .pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
+ .pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
+ .pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
+ .get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
+ .gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
+ .gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ .gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ .gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
+ .gen_init = ath10k_wmi_tlv_op_gen_init,
+ .gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ .gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+ .gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
+ .gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
+ .gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
+ .gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
+ .gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
+ .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
+ .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
+ .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
+ .gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
+ .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
+ .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
+ .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
+ .gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
+ .gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
+ .gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
+ .gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
+ .gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
+ .gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
+ .gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
+ .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
+ .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
+ .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
+ .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
+ .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
+ .gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
+ .gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
+ .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
+ .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
+ .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
+ .gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
+ .gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
+ .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
+ .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
+ .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
+ .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
+ .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
+ .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
+};
+
+void ath10k_wmi_hl_1_0_attach(struct ath10k *ar)
+{
+ ar->wmi.cmd = &wmi_tlv_cmd_map;
+ ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
+ ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
+ ar->wmi.ops = &wmi_hl_1_0_ops;
+}
+
/* TLV init */
/************/
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index b8aa6000573c..496fee5d489b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -889,6 +889,7 @@ enum wmi_tlv_tag {
WMI_TLV_TAG_STRUCT_SAP_OFL_DEL_STA_EVENT,
WMI_TLV_TAG_STRUCT_APFIND_CMD_PARAM,
WMI_TLV_TAG_STRUCT_APFIND_EVENT_HDR,
+ WMI_TLV_TAG_STRUCT_HL_1_0_SVC_OFFSET = 176,
WMI_TLV_TAG_MAX
};
@@ -966,6 +967,125 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
};
+enum wmi_hl_10_service {
+ WMI_HL_10_SERVICE_BEACON_OFFLOAD = 0,
+ WMI_HL_10_SERVICE_SCAN_OFFLOAD,
+ WMI_HL_10_SERVICE_ROAM_SCAN_OFFLOAD,
+ WMI_HL_10_SERVICE_BCN_MISS_OFFLOAD,
+ WMI_HL_10_SERVICE_STA_PWRSAVE,
+ WMI_HL_10_SERVICE_STA_ADVANCED_PWRSAVE,
+ WMI_HL_10_SERVICE_AP_UAPSD,
+ WMI_HL_10_SERVICE_AP_DFS,
+ WMI_HL_10_SERVICE_11AC,
+ WMI_HL_10_SERVICE_BLOCKACK,
+ WMI_HL_10_SERVICE_PHYERR,
+ WMI_HL_10_SERVICE_BCN_FILTER,
+ WMI_HL_10_SERVICE_RTT,
+ WMI_HL_10_SERVICE_WOW,
+ WMI_HL_10_SERVICE_RATECTRL_CACHE,
+ WMI_HL_10_SERVICE_IRAM_TIDS,
+ WMI_HL_10_SERVICE_ARPNS_OFFLOAD,
+ WMI_HL_10_SERVICE_NLO,
+ WMI_HL_10_SERVICE_GTK_OFFLOAD,
+ WMI_HL_10_SERVICE_SCAN_SCH,
+ WMI_HL_10_SERVICE_CSA_OFFLOAD,
+ WMI_HL_10_SERVICE_CHATTER,
+ WMI_HL_10_SERVICE_COEX_FREQAVOID,
+ WMI_HL_10_SERVICE_PACKET_POWER_SAVE,
+ WMI_HL_10_SERVICE_FORCE_FW_HANG,
+ WMI_HL_10_SERVICE_GPIO,
+ WMI_HL_10_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
+ WMI_HL_10_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+ WMI_HL_10_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+ WMI_HL_10_SERVICE_STA_KEEP_ALIVE,
+ WMI_HL_10_SERVICE_TX_ENCAP,
+ WMI_HL_10_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
+ WMI_HL_10_SERVICE_EARLY_RX,
+ WMI_HL_10_SERVICE_STA_SMPS,
+ WMI_HL_10_SERVICE_FWTEST,
+ WMI_HL_10_SERVICE_STA_WMMAC,
+ WMI_HL_10_SERVICE_TDLS,
+ WMI_HL_10_SERVICE_BURST,
+ WMI_HL_10_SERVICE_MCC_BCN_INTERVAL_CHANGE,
+ WMI_HL_10_SERVICE_ADAPTIVE_OCS,
+ WMI_HL_10_SERVICE_BA_SSN_SUPPORT,
+ WMI_HL_10_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
+ WMI_HL_10_SERVICE_WLAN_HB,
+ WMI_HL_10_SERVICE_LTE_ANT_SHARE_SUPPORT,
+ WMI_HL_10_SERVICE_BATCH_SCAN,
+ WMI_HL_10_SERVICE_QPOWER,
+ WMI_HL_10_SERVICE_PLMREQ,
+ WMI_HL_10_SERVICE_THERMAL_MGMT,
+ WMI_HL_10_SERVICE_RMC,
+ WMI_HL_10_SERVICE_MHF_OFFLOAD,
+ WMI_HL_10_SERVICE_COEX_SAR,
+ WMI_HL_10_SERVICE_BCN_TXRATE_OVERRIDE,
+ WMI_HL_10_SERVICE_NAN,
+ WMI_HL_10_SERVICE_L1SS_STAT,
+ WMI_HL_10_SERVICE_ESTIMATE_LINKSPEED,
+ WMI_HL_10_SERVICE_OBSS_SCAN,
+ WMI_HL_10_SERVICE_TDLS_OFFCHAN,
+ WMI_HL_10_SERVICE_TDLS_UAPSD_BUFFER_STA,
+ WMI_HL_10_SERVICE_TDLS_UAPSD_SLEEP_STA,
+ WMI_HL_10_SERVICE_IBSS_PWRSAVE,
+ WMI_HL_10_SERVICE_LPASS,
+ WMI_HL_10_SERVICE_EXTSCAN,
+ WMI_HL_10_SERVICE_D0WOW,
+ WMI_HL_10_SERVICE_HSOFFLOAD,
+ WMI_HL_10_SERVICE_ROAM_HO_OFFLOAD,
+ WMI_HL_10_SERVICE_RX_FULL_REORDER,
+ WMI_HL_10_SERVICE_DHCP_OFFLOAD,
+ WMI_HL_10_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
+ WMI_HL_10_SERVICE_MDNS_OFFLOAD,
+ WMI_HL_10_SERVICE_SAP_AUTH_OFFLOAD,
+ WMI_HL_10_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT,
+ WMI_HL_10_SERVICE_OCB,
+ WMI_HL_10_SERVICE_AP_ARPNS_OFFLOAD,
+ WMI_HL_10_SERVICE_PER_BAND_CHAINMASK_SUPPORT,
+ WMI_HL_10_SERVICE_PACKET_FILTER_OFFLOAD,
+ WMI_HL_10_SERVICE_MGMT_TX_HTT,
+ WMI_HL_10_SERVICE_MGMT_TX_WMI,
+ WMI_HL_10_SERVICE_EXT_MSG,
+ WMI_HL_10_SERVICE_MAWC,
+ WMI_HL_10_SERVICE_PEER_ASSOC_CONF,
+ WMI_HL_10_SERVICE_EGAP,
+ WMI_HL_10_SERVICE_STA_PMF_OFFLOAD,
+ WMI_HL_10_SERVICE_UNIFIED_WOW_CAPABILITY,
+ WMI_HL_10_SERVICE_ENHANCED_PROXY_STA,
+ WMI_HL_10_SERVICE_ATF,
+ WMI_HL_10_SERVICE_COEX_GPIO,
+ WMI_HL_10_SERVICE_AUX_SPECTRAL_INTF,
+ WMI_HL_10_SERVICE_AUX_CHAN_LOAD_INTF,
+ WMI_HL_10_SERVICE_BSS_CHANNEL_INFO_64,
+ WMI_HL_10_SERVICE_ENTERPRISE_MESH,
+ WMI_HL_10_SERVICE_RESTRT_CHNL_SUPPORT,
+ WMI_HL_10_SERVICE_BPF_OFFLOAD,
+ WMI_HL_10_SERVICE_SYNC_DELETE_CMDS,
+ WMI_HL_10_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+ WMI_HL_10_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+ WMI_HL_10_SERVICE_RATECTRL_LIMIT_MAX_MIN_RATES,
+ WMI_HL_10_SERVICE_NAN_DATA,
+ WMI_HL_10_SERVICE_NAN_RTT,
+ WMI_HL_10_SERVICE_11AX,
+ WMI_HL_10_SERVICE_DEPRECATED_REPLACE,
+ WMI_HL_10_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
+ WMI_HL_10_SERVICE_ENHANCED_MCAST_FILTER,
+ WMI_HL_10_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
+ WMI_HL_10_SERVICE_MESH_11S,
+ WMI_HL_10_SERVICE_HALF_RATE_QUARTER_RATE_SUPPORT,
+ WMI_HL_10_SERVICE_VDEV_RX_FILTER,
+ WMI_HL_10_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT,
+ WMI_HL_10_SERVICE_MARK_FIRST_WAKEUP_PACKET,
+ WMI_HL_10_SERVICE_MULTIPLE_MCAST_FILTER_SET,
+ WMI_HL_10_SERVICE_HOST_MANAGED_RX_REORDER,
+ WMI_HL_10_SERVICE_FLASH_RDWR_SUPPORT,
+ WMI_HL_10_SERVICE_WLAN_STATS_REPORT,
+ WMI_HL_10_SERVICE_TX_MSDU_ID_NEW_PARTITION_SUPPORT,
+ WMI_HL_10_SERVICE_DFS_PHYERR_OFFLOAD,
+ WMI_HL_10_MAX_SERVICE = 128,
+ WMI_HL_10_MAX_EXT_SERVICE
+};
+
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
((svc_id) < (len) && \
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
@@ -978,6 +1098,63 @@ enum wmi_tlv_service {
} while (0)
static inline void
+wmi_hl_1_0_svc_map(const __le32 *in, unsigned long *out, size_t len)
+{
+ SVCMAP(WMI_HL_10_SERVICE_BEACON_OFFLOAD,
+ WMI_SERVICE_BEACON_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_SCAN_OFFLOAD,
+ WMI_SERVICE_SCAN_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_ROAM_SCAN_OFFLOAD,
+ WMI_SERVICE_ROAM_SCAN_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_BCN_MISS_OFFLOAD,
+ WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_STA_PWRSAVE,
+ WMI_SERVICE_STA_PWRSAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_STA_ADVANCED_PWRSAVE,
+ WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_AP_UAPSD,
+ WMI_SERVICE_AP_UAPSD, len);
+ SVCMAP(WMI_HL_10_SERVICE_AP_DFS,
+ WMI_SERVICE_AP_DFS, len);
+ SVCMAP(WMI_HL_10_SERVICE_11AC,
+ WMI_SERVICE_11AC, len);
+ SVCMAP(WMI_HL_10_SERVICE_BLOCKACK,
+ WMI_SERVICE_BLOCKACK, len);
+ SVCMAP(WMI_HL_10_SERVICE_PHYERR,
+ WMI_SERVICE_PHYERR, len);
+ SVCMAP(WMI_HL_10_SERVICE_BCN_FILTER,
+ WMI_SERVICE_BCN_FILTER, len);
+ SVCMAP(WMI_HL_10_SERVICE_RTT,
+ WMI_SERVICE_RTT, len);
+ SVCMAP(WMI_HL_10_SERVICE_WOW,
+ WMI_SERVICE_WOW, len);
+ SVCMAP(WMI_HL_10_SERVICE_RATECTRL_CACHE,
+ WMI_SERVICE_RATECTRL_CACHE, len);
+ SVCMAP(WMI_HL_10_SERVICE_IRAM_TIDS,
+ WMI_SERVICE_IRAM_TIDS, len);
+ SVCMAP(WMI_HL_10_SERVICE_ARPNS_OFFLOAD,
+ WMI_SERVICE_ARPNS_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_NLO,
+ WMI_SERVICE_NLO, len);
+ SVCMAP(WMI_HL_10_SERVICE_GTK_OFFLOAD,
+ WMI_SERVICE_GTK_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_SCAN_SCH,
+ WMI_SERVICE_SCAN_SCH, len);
+ SVCMAP(WMI_HL_10_SERVICE_CSA_OFFLOAD,
+ WMI_SERVICE_CSA_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_CHATTER,
+ WMI_SERVICE_CHATTER, len);
+ SVCMAP(WMI_HL_10_SERVICE_COEX_FREQAVOID,
+ WMI_SERVICE_COEX_FREQAVOID, len);
+ SVCMAP(WMI_HL_10_SERVICE_PACKET_POWER_SAVE,
+ WMI_SERVICE_PACKET_POWER_SAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_FORCE_FW_HANG,
+ WMI_SERVICE_FORCE_FW_HANG, len);
+ SVCMAP(WMI_HL_10_SERVICE_RX_FULL_REORDER,
+ WMI_SERVICE_RX_FULL_REORDER, len);
+}
+
+static inline void
wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
{
SVCMAP(WMI_TLV_SERVICE_BEACON_OFFLOAD,
@@ -1182,6 +1359,14 @@ struct wmi_tlv_svc_rdy_ev {
__le32 max_num_scan_chans;
__le32 hw_bd_id; /* 0 means hw_bd_info is invalid */
struct wmi_tlv_hw_bd_info hw_bd_info[5];
+#ifdef CONFIG_ATH10K_SNOC
+ __le32 max_supported_macs;
+ __le32 wmi_fw_sub_feat_caps;
+ __le32 num_dbs_hw_modes;
+ __le32 txrx_chainmask;
+ __le32 default_dbs_hw_mode_index;
+ __le32 num_msdu_desc;
+#endif
} __packed;
struct wmi_tlv_rdy_ev {
@@ -1641,5 +1826,5 @@ struct wmi_tlv_tx_pause_ev {
} __packed;
void ath10k_wmi_tlv_attach(struct ath10k *ar);
-
+void ath10k_wmi_hl_1_0_attach(struct ath10k *ar);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 54df425bb0fc..f7ada7147136 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2320,9 +2320,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
* of mgmt rx.
*/
if (channel >= 1 && channel <= 14) {
- status->band = NL80211_BAND_2GHZ;
+ status->band = IEEE80211_BAND_2GHZ;
} else if (channel >= 36 && channel <= 165) {
- status->band = NL80211_BAND_5GHZ;
+ status->band = IEEE80211_BAND_5GHZ;
} else {
/* Shouldn't happen unless list of advertised channels to
* mac80211 has been changed.
@@ -2332,7 +2332,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
return 0;
}
- if (phy_mode == MODE_11B && status->band == NL80211_BAND_5GHZ)
+ if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ)
ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
sband = &ar->mac.sbands[status->band];
@@ -2387,7 +2387,7 @@ static int freq_to_idx(struct ath10k *ar, int freq)
struct ieee80211_supported_band *sband;
int band, ch, idx = 0;
- for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
+ for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
sband = ar->hw->wiphy->bands[band];
if (!sband)
continue;
@@ -8196,6 +8196,9 @@ int ath10k_wmi_attach(struct ath10k *ar)
case ATH10K_FW_WMI_OP_VERSION_TLV:
ath10k_wmi_tlv_attach(ar);
break;
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
+ ath10k_wmi_hl_1_0_attach(ar);
+ break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
ath10k_err(ar, "unsupported WMI op version: %d\n",
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a680a970b7f7..e4281438c04f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath9k_htc_sta *ista;
int ret = 0;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d184e682e636..5cc0ddc254eb 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1860,14 +1860,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
static int ath9k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
bool flush = false;
int ret = 0;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
mutex_lock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 19d3d64416bf..4d1527a2e292 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work)
static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
struct ar9170 *ar = hw->priv;
struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
struct carl9170_sta_tid *tid_info;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 7c169abdbafe..a27279c2c695 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw)
static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_sta *sta_priv = NULL;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
action, tid);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 8983b5f125c3..0a3928a8fe90 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -754,6 +754,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
if (rc == 0) {
netif_carrier_on(ndev);
+ wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
/* Connect can take lots of time */
mod_timer(&wil->connect_timer,
jiffies + msecs_to_jiffies(2000));
@@ -1273,6 +1274,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
wil->pbss = pbss;
netif_carrier_on(ndev);
+ wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
if (rc)
@@ -1288,6 +1290,7 @@ err_bcast:
wmi_pcp_stop(wil);
err_pcp_start:
netif_carrier_off(ndev);
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
out:
mutex_unlock(&wil->mutex);
return rc;
@@ -1394,6 +1397,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
wil_dbg_misc(wil, "%s()\n", __func__);
netif_carrier_off(ndev);
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
wil_set_recovery_state(wil, fw_recovery_idle);
mutex_lock(&wil->mutex);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index fa061daa56d7..eb1fd9dd09ba 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -270,6 +270,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
wil_bcast_fini(wil);
wil_update_net_queues_bh(wil, NULL, true);
netif_carrier_off(ndev);
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
if (test_bit(wil_status_fwconnected, wil->status)) {
clear_bit(wil_status_fwconnected, wil->status);
@@ -553,6 +554,12 @@ out_wmi_wq:
return -EAGAIN;
}
+void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
+{
+ if (wil->platform_ops.bus_request)
+ wil->platform_ops.bus_request(wil->platform_handle, kbps);
+}
+
/**
* wil6210_disconnect - disconnect one connection
* @wil: driver context
@@ -1068,9 +1075,7 @@ int __wil_up(struct wil6210_priv *wil)
napi_enable(&wil->napi_tx);
set_bit(wil_status_napi_en, wil->status);
- if (wil->platform_ops.bus_request)
- wil->platform_ops.bus_request(wil->platform_handle,
- WIL_MAX_BUS_REQUEST_KBPS);
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
return 0;
}
@@ -1094,8 +1099,7 @@ int __wil_down(struct wil6210_priv *wil)
set_bit(wil_status_resetting, wil->status);
- if (wil->platform_ops.bus_request)
- wil->platform_ops.bus_request(wil->platform_handle, 0);
+ wil6210_bus_request(wil, 0);
wil_disable_irq(wil);
if (test_and_clear_bit(wil_status_napi_en, wil->status)) {
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index cc20517a4726..b9727ebe79ac 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -39,6 +39,7 @@ extern bool debug_fw;
#define WIL_FW_NAME "wil6210.fw" /* code */
#define WIL_FW2_NAME "wil6210.brd" /* board & radio parameters */
+#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
/**
@@ -892,7 +893,7 @@ int wmi_aoa_meas(struct wil6210_priv *wil, const void *mac_addr, u8 chan,
u8 type);
int wmi_abort_scan(struct wil6210_priv *wil);
void wil_abort_scan(struct wil6210_priv *wil, bool sync);
-
+void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps);
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
u16 reason_code, bool from_event);
void wil_probe_client_flush(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 24f42e3a6d92..09595349f24b 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -566,6 +566,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
if (rc) {
netif_carrier_off(ndev);
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
wil_err(wil,
"%s: cfg80211_connect_result with failure\n",
__func__);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index bec2dc1ca2e4..61ae2768132a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static int
brcms_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct brcms_info *wl = hw->priv;
struct scb *scb = &wl->wlc->pri_scb;
int status;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u8 buf_size = params->buf_size;
if (WARN_ON(scb->magic != SCB_MAGIC))
return -EIDRM;
diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h
index bebb3379017f..a0bacaa39b31 100644
--- a/drivers/net/wireless/cw1200/sta.h
+++ b/drivers/net/wireless/cw1200/sta.h
@@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
u32 changed);
int cw1200_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu);
+ struct ieee80211_ampdu_params *params);
void cw1200_suspend_resume(struct cw1200_common *priv,
struct wsm_suspend_resume *arg);
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 8ab8706f9422..e432715e02d8 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u32 iv32,
u16 *phase1key);
int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 * ssn,
- u8 buf_size, bool amsdu);
+ struct ieee80211_ampdu_params *params);
int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 0cd95120bc78..d59769e858f4 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1817,10 +1817,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+
switch (action) {
case IEEE80211_AMPDU_TX_START:
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index f715eee39851..e70dd9523911 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int
mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
- bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct mt7601u_dev *dev = hw->priv;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
WARN_ON(msta->wcid.idx > GROUP_WCID(0));
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 30e3aaae32e2..088429d0a634 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
static int
mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
-
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
+ u8 buf_size = params->buf_size;
int i, rc = 0;
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_ampdu_stream *stream;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
index 6aed923a709a..7d820c395375 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
@@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
static int
rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
- bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
u8 ampdu_factor, ampdu_density;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
switch (action) {
case IEEE80211_AMPDU_TX_START:
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index c925a4dff599..a4527880b2b7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1371,11 +1371,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw,
static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
switch (action) {
case IEEE80211_AMPDU_TX_START:
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index b5bcc933a2a6..4df992de7d07 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
* informs the f/w regarding this.
* @hw: Pointer to the ieee80211_hw structure.
* @vif: Pointer to the ieee80211_vif structure.
- * @action: ieee80211_ampdu_mlme_action enum.
- * @sta: Pointer to the ieee80211_sta structure.
- * @tid: Traffic identifier.
- * @ssn: Pointer to ssn value.
- * @buf_size: Buffer size (for kernel version > 2.6.38).
- * @amsdu: is AMSDU in AMPDU allowed
+ * @params: Pointer to A-MPDU action parameters
*
* Return: status: 0 on success, negative error code on failure.
*/
static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta,
- unsigned short tid,
- unsigned short *ssn,
- unsigned char buf_size,
- bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
int status = -EOPNOTSUPP;
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
u16 seq_no = 0;
u8 ii = 0;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
+ u8 buf_size = params->buf_size;
for (ii = 0; ii < RSI_MAX_VIFS; ii++) {
if (vif == adapter->vifs[ii])
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9733b31a780d..69c1c09687a3 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
EXPORT_SYMBOL_GPL(rt2800_get_tsf);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 440790b92b19..83f1a44fb9b4 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
const struct ieee80211_tx_queue_params *params);
u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu);
+ struct ieee80211_ampdu_params *params);
int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ec7f6af3fab2..30165ea0fa25 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5261,14 +5261,16 @@ out:
static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int ret;
u8 hlid, *ba_bitmap;
+ struct ieee80211_sta *sta = params->sta;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
tid);
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index a617c9e8e11f..fd241f6b62da 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -362,8 +362,13 @@ static void gsi_process_chan(struct gsi_xfer_compl_evt *evt,
notify->chan_user_data = ch_ctx->props.chan_user_data;
notify->evt_id = evt->code;
notify->bytes_xfered = evt->len;
- if (callback)
+ if (callback) {
+ if (atomic_read(&ch_ctx->poll_mode)) {
+ GSIERR("Calling client callback in polling mode\n");
+ WARN_ON(1);
+ }
ch_ctx->props.xfer_cb(notify);
+ }
}
static void gsi_process_evt_re(struct gsi_evt_ctx *ctx,
@@ -459,12 +464,12 @@ check_again:
ctx->ring.rp = rp;
while (ctx->ring.rp_local != rp) {
++cntr;
- gsi_process_evt_re(ctx, &notify, true);
if (ctx->props.exclusive &&
atomic_read(&ctx->chan->poll_mode)) {
cntr = 0;
break;
}
+ gsi_process_evt_re(ctx, &notify, true);
}
gsi_ring_evt_doorbell(ctx);
if (cntr != 0)
@@ -1586,15 +1591,21 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
return -GSI_STATUS_INVALID_PARAMS;
}
- if (props->evt_ring_hdl != ~0 &&
- atomic_read(&gsi_ctx->evtr[props->evt_ring_hdl].chan_ref_cnt) &&
- gsi_ctx->evtr[props->evt_ring_hdl].props.exclusive) {
- GSIERR("evt ring=%lu already in exclusive use chan_hdl=%p\n",
+ if (props->evt_ring_hdl != ~0) {
+ if (props->evt_ring_hdl >= GSI_EVT_RING_MAX) {
+ GSIERR("invalid evt ring=%lu\n", props->evt_ring_hdl);
+ return -GSI_STATUS_INVALID_PARAMS;
+ }
+
+ if (atomic_read(
+ &gsi_ctx->evtr[props->evt_ring_hdl].chan_ref_cnt) &&
+ gsi_ctx->evtr[props->evt_ring_hdl].props.exclusive) {
+ GSIERR("evt ring=%lu exclusively used by chan_hdl=%p\n",
props->evt_ring_hdl, chan_hdl);
- return -GSI_STATUS_UNSUPPORTED_OP;
+ return -GSI_STATUS_UNSUPPORTED_OP;
+ }
}
-
ctx = &gsi_ctx->chan[props->ch_id];
if (ctx->allocated) {
GSIERR("chan %d already allocated\n", props->ch_id);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 09ec8458fcad..1e79fd954969 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3774,6 +3774,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,
ipa_ctx->ipa_wrapper_size = resource_p->ipa_mem_size;
ipa_ctx->ipa_hw_type = resource_p->ipa_hw_type;
ipa_ctx->ipa_hw_mode = resource_p->ipa_hw_mode;
+ ipa_ctx->ipa_uc_monitor_holb =
+ resource_p->ipa_uc_monitor_holb;
ipa_ctx->use_ipa_teth_bridge = resource_p->use_ipa_teth_bridge;
ipa_ctx->ipa_bam_remote_mode = resource_p->ipa_bam_remote_mode;
ipa_ctx->modem_cfg_emb_pipe_flt = resource_p->modem_cfg_emb_pipe_flt;
@@ -4316,6 +4318,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->ipa_pipe_mem_size = IPA_PIPE_MEM_SIZE;
ipa_drv_res->ipa_hw_type = 0;
ipa_drv_res->ipa_hw_mode = 0;
+ ipa_drv_res->ipa_uc_monitor_holb = false;
ipa_drv_res->ipa_bam_remote_mode = false;
ipa_drv_res->modem_cfg_emb_pipe_flt = false;
ipa_drv_res->ipa_wdi2 = false;
@@ -4340,6 +4343,14 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
IPADBG(": found ipa_drv_res->ipa_hw_mode = %d",
ipa_drv_res->ipa_hw_mode);
+ /* Check ipa_uc_monitor_holb enabled or disabled */
+ ipa_drv_res->ipa_uc_monitor_holb =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,ipa-uc-monitor-holb");
+ IPADBG(": ipa uc monitor holb = %s\n",
+ ipa_drv_res->ipa_uc_monitor_holb
+ ? "Enabled" : "Disabled");
+
/* Get IPA WAN / LAN RX pool sizes */
result = of_property_read_u32(pdev->dev.of_node,
"qcom,wan-rx-ring-size",
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index 7ce51fccb822..8d2213f30ec2 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1272,8 +1272,9 @@ static ssize_t ipa_read_wdi(struct file *file, char __user *ubuf,
"RX num_db=%u\n"
"RX num_unexpected_db=%u\n"
"RX num_pkts_in_dis_uninit_state=%u\n"
- "num_ic_inj_vdev_change=%u\n"
- "num_ic_inj_fw_desc_change=%u\n"
+ "RX num_ic_inj_vdev_change=%u\n"
+ "RX num_ic_inj_fw_desc_change=%u\n"
+ "RX num_qmb_int_handled=%u\n"
"RX reserved1=%u\n"
"RX reserved2=%u\n",
stats.rx_ch_stats.max_outstanding_pkts,
@@ -1295,6 +1296,7 @@ static ssize_t ipa_read_wdi(struct file *file, char __user *ubuf,
stats.rx_ch_stats.num_pkts_in_dis_uninit_state,
stats.rx_ch_stats.num_ic_inj_vdev_change,
stats.rx_ch_stats.num_ic_inj_fw_desc_change,
+ stats.rx_ch_stats.num_qmb_int_handled,
stats.rx_ch_stats.reserved1,
stats.rx_ch_stats.reserved2);
cnt += nbytes;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 2c2a9c617b16..b45e748b66a6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -47,7 +47,7 @@
#define IPA_QMAP_HEADER_LENGTH (4)
#define IPA_DL_CHECKSUM_LENGTH (8)
#define IPA_NUM_DESC_PER_SW_TX (2)
-#define IPA_GENERIC_RX_POOL_SZ 1000
+#define IPA_GENERIC_RX_POOL_SZ 192
#define IPA_UC_FINISH_MAX 6
#define IPA_UC_WAIT_MIN_SLEEP 1000
#define IPA_UC_WAII_MAX_SLEEP 1200
@@ -1174,6 +1174,7 @@ struct ipa_context {
u32 ipa_rx_min_timeout_usec;
u32 ipa_rx_max_timeout_usec;
u32 ipa_polling_iteration;
+ bool ipa_uc_monitor_holb;
};
/**
@@ -1229,6 +1230,7 @@ struct ipa_plat_drv_res {
bool tethered_flow_control;
u32 ipa_rx_polling_sleep_msec;
u32 ipa_polling_iteration;
+ bool ipa_uc_monitor_holb;
};
struct ipa_mem_partition {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
index 13db6b08ba9d..3dd2eb093317 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -768,8 +768,12 @@ int ipa_uc_monitor_holb(enum ipa_client_type ipa_client, bool enable)
int ep_idx;
int ret;
- /* HOLB monitoring is applicable only to 2.6L. */
- if (ipa_ctx->ipa_hw_type != IPA_HW_v2_6L) {
+ /*
+ * HOLB monitoring is applicable to 2.6L.
+ * And also could be enabled from dtsi node.
+ */
+ if (ipa_ctx->ipa_hw_type != IPA_HW_v2_6L ||
+ !ipa_ctx->ipa_uc_monitor_holb) {
IPADBG("Not applicable on this target\n");
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index 6dc194f97656..5bda4cb9ed2b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -477,6 +477,9 @@ int ipa2_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats)
RX_STATS(num_db);
RX_STATS(num_unexpected_db);
RX_STATS(num_pkts_in_dis_uninit_state);
+ RX_STATS(num_ic_inj_vdev_change);
+ RX_STATS(num_ic_inj_fw_desc_change);
+ RX_STATS(num_qmb_int_handled);
RX_STATS(reserved1);
RX_STATS(reserved2);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index e3d20422d591..2cd8d5c975f4 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -195,7 +195,7 @@ static const int ep_mapping[3][IPA_CLIENT_MAX] = {
[IPA_2_6L][IPA_CLIENT_HSIC1_PROD] = -1,
- [IPA_2_6L][IPA_CLIENT_WLAN1_PROD] = -1,
+ [IPA_2_6L][IPA_CLIENT_WLAN1_PROD] = 18,
[IPA_2_6L][IPA_CLIENT_HSIC2_PROD] = -1,
[IPA_2_6L][IPA_CLIENT_USB2_PROD] = -1,
[IPA_2_6L][IPA_CLIENT_HSIC3_PROD] = -1,
@@ -228,16 +228,16 @@ static const int ep_mapping[3][IPA_CLIENT_MAX] = {
[IPA_2_6L][IPA_CLIENT_TEST4_PROD] = 14,
[IPA_2_6L][IPA_CLIENT_HSIC1_CONS] = -1,
- [IPA_2_6L][IPA_CLIENT_WLAN1_CONS] = -1,
+ [IPA_2_6L][IPA_CLIENT_WLAN1_CONS] = 17,
[IPA_2_6L][IPA_CLIENT_HSIC2_CONS] = -1,
[IPA_2_6L][IPA_CLIENT_USB2_CONS] = -1,
- [IPA_2_6L][IPA_CLIENT_WLAN2_CONS] = -1,
+ [IPA_2_6L][IPA_CLIENT_WLAN2_CONS] = 16,
[IPA_2_6L][IPA_CLIENT_HSIC3_CONS] = -1,
[IPA_2_6L][IPA_CLIENT_USB3_CONS] = -1,
- [IPA_2_6L][IPA_CLIENT_WLAN3_CONS] = -1,
+ [IPA_2_6L][IPA_CLIENT_WLAN3_CONS] = 15,
[IPA_2_6L][IPA_CLIENT_HSIC4_CONS] = -1,
[IPA_2_6L][IPA_CLIENT_USB4_CONS] = -1,
- [IPA_2_6L][IPA_CLIENT_WLAN4_CONS] = -1,
+ [IPA_2_6L][IPA_CLIENT_WLAN4_CONS] = 19,
[IPA_2_6L][IPA_CLIENT_HSIC5_CONS] = -1,
[IPA_2_6L][IPA_CLIENT_USB_CONS] = 0,
[IPA_2_6L][IPA_CLIENT_USB_DPL_CONS] = 10,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 25e5e3b74f26..17e6973b807f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1356,8 +1356,9 @@ static ssize_t ipa3_read_wdi(struct file *file, char __user *ubuf,
"RX num_db=%u\n"
"RX num_unexpected_db=%u\n"
"RX num_pkts_in_dis_uninit_state=%u\n"
- "num_ic_inj_vdev_change=%u\n"
- "num_ic_inj_fw_desc_change=%u\n"
+ "RX num_ic_inj_vdev_change=%u\n"
+ "RX num_ic_inj_fw_desc_change=%u\n"
+ "RX num_qmb_int_handled=%u\n"
"RX reserved1=%u\n"
"RX reserved2=%u\n",
stats.rx_ch_stats.max_outstanding_pkts,
@@ -1379,6 +1380,7 @@ static ssize_t ipa3_read_wdi(struct file *file, char __user *ubuf,
stats.rx_ch_stats.num_pkts_in_dis_uninit_state,
stats.rx_ch_stats.num_ic_inj_vdev_change,
stats.rx_ch_stats.num_ic_inj_fw_desc_change,
+ stats.rx_ch_stats.num_qmb_int_handled,
stats.rx_ch_stats.reserved1,
stats.rx_ch_stats.reserved2);
cnt += nbytes;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index bf794faa7f6a..3086311b5c2a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -37,6 +37,8 @@
#define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000
#define QMI_SEND_REQ_TIMEOUT_MS 60000
+#define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000
+
static struct qmi_handle *ipa3_svc_handle;
static void ipa3_a5_svc_recv_msg(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_recv_msg, ipa3_a5_svc_recv_msg);
@@ -713,7 +715,8 @@ int ipa3_qmi_enable_force_clear_datapath_send(
&req_desc,
req,
sizeof(*req),
- &resp_desc, &resp, sizeof(resp), 0);
+ &resp_desc, &resp, sizeof(resp),
+ QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
if (rc < 0) {
IPAWANERR("send req failed %d\n", rc);
return rc;
@@ -758,7 +761,8 @@ int ipa3_qmi_disable_force_clear_datapath_send(
&req_desc,
req,
sizeof(*req),
- &resp_desc, &resp, sizeof(resp), 0);
+ &resp_desc, &resp, sizeof(resp),
+ QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
if (rc < 0) {
IPAWANERR("send req failed %d\n", rc);
return rc;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 41bb8651f69c..24b61880f95d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -472,6 +472,9 @@ int ipa3_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats)
RX_STATS(num_db);
RX_STATS(num_unexpected_db);
RX_STATS(num_pkts_in_dis_uninit_state);
+ RX_STATS(num_ic_inj_vdev_change);
+ RX_STATS(num_ic_inj_fw_desc_change);
+ RX_STATS(num_qmb_int_handled);
RX_STATS(reserved1);
RX_STATS(reserved2);
@@ -1353,6 +1356,33 @@ uc_timeout:
return result;
}
+static int ipa3_wait_for_prod_empty(void)
+{
+ int i;
+ u32 rx_door_bell_value;
+
+ for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
+ rx_door_bell_value = ipahal_read_reg_mn(
+ IPA_UC_MAILBOX_m_n,
+ IPA_HW_WDI_RX_MBOX_START_INDEX / 32,
+ IPA_HW_WDI_RX_MBOX_START_INDEX % 32);
+ IPADBG("(%d)rx_DB(%u)rp(%u),comp_wp(%u)\n",
+ i,
+ rx_door_bell_value,
+ *ipa3_ctx->uc_ctx.rdy_ring_rp_va,
+ *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va);
+ if (*ipa3_ctx->uc_ctx.rdy_ring_rp_va !=
+ *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va) {
+ usleep_range(IPA_UC_WAIT_MIN_SLEEP,
+ IPA_UC_WAII_MAX_SLEEP);
+ } else {
+ return 0;
+ }
+ }
+
+ return -ETIME;
+}
+
/**
* ipa3_disable_wdi_pipe() - WDI client disable
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
@@ -1368,9 +1398,9 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
union IpaHwWdiCommonChCmdData_t disable;
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
u32 prod_hdl;
- int i;
- u32 rx_door_bell_value;
+
u32 source_pipe_bitmask = 0;
+ bool disable_force_clear = false;
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
ipa3_ctx->ep[clnt_hdl].valid == 0) {
@@ -1406,16 +1436,8 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
* holb on IPA Producer pipe
*/
if (IPA_CLIENT_IS_PROD(ep->client)) {
- /* enable force clear */
IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n",
clnt_hdl, ep->client);
- source_pipe_bitmask = 1 <<
- ipa3_get_ep_mapping(ep->client);
- result = ipa3_enable_force_clear(clnt_hdl, false,
- source_pipe_bitmask);
- if (result)
- goto uc_timeout;
-
/* remove delay on wlan-prod pipe*/
memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl));
ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
@@ -1439,30 +1461,34 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
* rdy_comp_ring_wp_pa on WDI2.0
*/
if (ipa3_ctx->ipa_wdi2) {
- for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
- rx_door_bell_value = ipahal_read_reg_mn(
- IPA_UC_MAILBOX_m_n,
- IPA_HW_WDI_RX_MBOX_START_INDEX/32,
- IPA_HW_WDI_RX_MBOX_START_INDEX % 32);
- IPADBG("(%d)rx_DB(%u)rp(%u),comp_wp(%u)\n",
- i,
- rx_door_bell_value,
- *ipa3_ctx->uc_ctx.rdy_ring_rp_va,
- *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va);
- if (*ipa3_ctx->uc_ctx.rdy_ring_rp_va !=
- *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va) {
- usleep_range(IPA_UC_WAIT_MIN_SLEEP,
- IPA_UC_WAII_MAX_SLEEP);
+ result = ipa3_wait_for_prod_empty();
+ if (result) {
+ IPADBG("prod not empty\n");
+ /*
+ * In case ipa_uc still haven't processed all
+ * pending descriptors, ask modem to drain
+ */
+ source_pipe_bitmask = 1 <<
+ ipa3_get_ep_mapping(ep->client);
+ result = ipa3_enable_force_clear(clnt_hdl,
+ false, source_pipe_bitmask);
+ if (result) {
+ IPAERR("failed to force clear %d\n",
+ result);
} else {
- break;
+ disable_force_clear = true;
+ }
+
+ /*
+ * In case ipa_uc still haven't processed all
+ * pending descriptors, we have to assert
+ */
+ result = ipa3_wait_for_prod_empty();
+ if (result) {
+ IPAERR("prod still not empty\n");
+ ipa_assert();
}
}
- /*
- * In case ipa_uc still haven't processed all
- * pending descriptors, we have to assert
- */
- if (i == IPA_UC_FINISH_MAX)
- ipa_assert();
}
}
@@ -1482,8 +1508,8 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
ep_cfg_ctrl.ipa_ep_delay = true;
ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
- /* disable force clear */
- ipa3_disable_force_clear(clnt_hdl);
+ if (disable_force_clear)
+ ipa3_disable_force_clear(clnt_hdl);
}
IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
ep->uc_offload_state &= ~IPA_WDI_ENABLED;
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index b7fc68a6efdd..7f97d7c6bab7 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,10 @@
#include <soc/qcom/memory_dump.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/cpufreq.h>
+#include <linux/sched/core_ctl.h>
#include "wil_platform.h"
#include "msm_11ad.h"
@@ -54,6 +58,8 @@
#define DISABLE_PCIE_L1_MASK 0xFFFFFFFD
#define PCIE20_CAP_LINKCTRLSTATUS 0x80
+#define WIGIG_MIN_CPU_BOOST_KBPS 150000
+
struct device;
static const char * const gpio_en_name = "qcom,wigig-en";
@@ -113,6 +119,11 @@ struct msm11ad_ctx {
struct msm11ad_vreg vddio;
struct msm11ad_clk rf_clk3;
struct msm11ad_clk rf_clk3_pin;
+
+ /* cpu boost support */
+ bool use_cpu_boost;
+ bool is_cpu_boosted;
+ struct cpumask boost_cpu;
};
static LIST_HEAD(dev_list);
@@ -823,6 +834,36 @@ out_rc:
return rc;
}
+static void msm_11ad_init_cpu_boost(struct msm11ad_ctx *ctx)
+{
+ unsigned int minfreq = 0, maxfreq = 0, freq;
+ int i, boost_cpu;
+
+ for_each_possible_cpu(i) {
+ freq = cpufreq_quick_get_max(i);
+ if (freq > maxfreq) {
+ maxfreq = freq;
+ boost_cpu = i;
+ }
+ if (!minfreq || freq < minfreq)
+ minfreq = freq;
+ }
+
+ if (minfreq != maxfreq) {
+ /*
+ * use first big core for boost, to be compatible with WLAN
+ * which assigns big cores from the last index
+ */
+ ctx->use_cpu_boost = true;
+ cpumask_clear(&ctx->boost_cpu);
+ cpumask_set_cpu(boost_cpu, &ctx->boost_cpu);
+ dev_info(ctx->dev, "CPU boost: will use core %d\n", boost_cpu);
+ } else {
+ ctx->use_cpu_boost = false;
+ dev_info(ctx->dev, "CPU boost disabled, uniform topology\n");
+ }
+}
+
static int msm_11ad_probe(struct platform_device *pdev)
{
struct msm11ad_ctx *ctx;
@@ -998,6 +1039,8 @@ static int msm_11ad_probe(struct platform_device *pdev)
goto out_rc;
}
+ msm_11ad_init_cpu_boost(ctx);
+
/* report */
dev_info(ctx->dev, "msm_11ad discovered. %p {\n"
" gpio_en = %d\n"
@@ -1074,6 +1117,34 @@ static struct platform_driver msm_11ad_driver = {
};
module_platform_driver(msm_11ad_driver);
+static void msm_11ad_set_boost_affinity(struct msm11ad_ctx *ctx)
+{
+ /*
+ * There is a very small window where user space can change the
+ * affinity after we changed it here and before setting the
+ * NO_BALANCING flag. Retry this several times as a workaround.
+ */
+ int retries = 5, rc;
+ struct irq_desc *desc;
+
+ while (retries > 0) {
+ irq_modify_status(ctx->pcidev->irq, IRQ_NO_BALANCING, 0);
+ rc = irq_set_affinity_hint(ctx->pcidev->irq, &ctx->boost_cpu);
+ if (rc)
+ dev_warn(ctx->dev,
+ "Failed set affinity, rc=%d\n", rc);
+ irq_modify_status(ctx->pcidev->irq, 0, IRQ_NO_BALANCING);
+ desc = irq_to_desc(ctx->pcidev->irq);
+ if (cpumask_equal(desc->irq_common_data.affinity,
+ &ctx->boost_cpu))
+ break;
+ retries--;
+ }
+
+ if (!retries)
+ dev_warn(ctx->dev, "failed to set CPU boost affinity\n");
+}
+
/* hooks for the wil6210 driver */
static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */)
{
@@ -1102,6 +1173,35 @@ static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */)
"Failed msm_bus voting. kbps=%d vote=%d, rc=%d\n",
kbps, vote, rc);
+ if (ctx->use_cpu_boost) {
+ bool was_boosted = ctx->is_cpu_boosted;
+ bool needs_boost = (kbps >= WIGIG_MIN_CPU_BOOST_KBPS);
+
+ if (was_boosted != needs_boost) {
+ if (needs_boost) {
+ rc = core_ctl_set_boost(true);
+ if (rc) {
+ dev_err(ctx->dev,
+ "Failed enable boost rc=%d\n",
+ rc);
+ goto out;
+ }
+ msm_11ad_set_boost_affinity(ctx);
+ dev_dbg(ctx->dev, "CPU boost enabled\n");
+ } else {
+ rc = core_ctl_set_boost(false);
+ if (rc)
+ dev_err(ctx->dev,
+ "Failed disable boost rc=%d\n",
+ rc);
+ irq_modify_status(ctx->pcidev->irq,
+ IRQ_NO_BALANCING, 0);
+ dev_dbg(ctx->dev, "CPU boost disabled\n");
+ }
+ ctx->is_cpu_boosted = needs_boost;
+ }
+ }
+out:
return rc;
}
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 864152ca463d..dbda0b6a9c9a 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -1249,11 +1249,9 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
if (!chg->external_vconn) {
rc = smblib_read(chg, RID_CC_CONTROL_7_0_REG, &stat);
- if (rc < 0) {
+ if (rc < 0)
smblib_err(chg, "Couldn't read RID_CC_CONTROL_7_0 rc=%d\n",
rc);
- return rc;
- }
/* check if VCONN is enabled on either CC pin */
if (stat & VCONN_EN_CC_MASK) {
@@ -1262,7 +1260,6 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
if (rc < 0)
smblib_err(chg, "Couldn't disable VCONN rc=%d\n",
rc);
- return rc;
}
}
@@ -1362,17 +1359,48 @@ int smblib_get_prop_batt_capacity(struct smb_charger *chg,
int smblib_get_prop_batt_status(struct smb_charger *chg,
union power_supply_propval *val)
{
+ union power_supply_propval pval = {0, };
+ bool usb_online, dc_online;
u8 stat;
int rc;
+ rc = smblib_get_prop_usb_online(chg, &pval);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get usb online property rc=%d\n",
+ rc);
+ return rc;
+ }
+ usb_online = (bool)pval.intval;
+
+ rc = smblib_get_prop_dc_online(chg, &pval);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get dc online property rc=%d\n",
+ rc);
+ return rc;
+ }
+ dc_online = (bool)pval.intval;
+
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
-
stat = stat & BATTERY_CHARGER_STATUS_MASK;
+
+ if (!usb_online && !dc_online) {
+ switch (stat) {
+ case TERMINATE_CHARGE:
+ case INHIBIT_CHARGE:
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ }
+ return rc;
+ }
+
switch (stat) {
case TRICKLE_CHARGE:
case PRE_CHARGE:
@@ -2351,6 +2379,12 @@ int smblib_reg_block_restore(struct smb_charger *chg,
static struct reg_info cc2_detach_settings[] = {
{
+ .reg = TYPE_C_CFG_REG,
+ .mask = APSD_START_ON_CC_BIT,
+ .val = 0,
+ .desc = "TYPE_C_CFG_REG",
+ },
+ {
.reg = TYPE_C_CFG_2_REG,
.mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT,
.val = TYPE_C_UFP_MODE_BIT,
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 70d935e9d1df..c836e780fc86 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,9 @@
#define DEAD_TIME_MASK GENMASK(7, 4)
#define HIGH_DEAD_TIME_MASK GENMASK(7, 4)
+#define SMB2CHG_DC_TM_SREFGEN (DCIN_BASE + 0xE2)
+#define STACKED_DIODE_EN_BIT BIT(2)
+
enum {
OOB_COMP_WA_BIT = BIT(0),
};
@@ -410,6 +413,7 @@ static enum power_supply_property smb138x_parallel_props[] = {
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CHARGER_TEMP,
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
+ POWER_SUPPLY_PROP_MODEL_NAME,
};
static int smb138x_parallel_get_prop(struct power_supply *psy,
@@ -456,6 +460,9 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
rc = smblib_get_prop_charger_temp_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = "smb138x";
+ break;
default:
pr_err("parallel power supply get prop %d not supported\n",
prop);
@@ -1212,6 +1219,13 @@ static int smb138x_slave_probe(struct smb138x *chip)
goto cleanup;
}
+ /* enable stacked diode */
+ rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT);
+ if (rc < 0) {
+ pr_err("Couldn't enable stacked diode rc=%d\n", rc);
+ return rc;
+ }
+
rc = smb138x_init_parallel_psy(chip);
if (rc < 0) {
pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c
index 1ac9791b467b..1070a34073e4 100644
--- a/drivers/regulator/cpr3-mmss-regulator.c
+++ b/drivers/regulator/cpr3-mmss-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -453,45 +453,24 @@ done:
}
/**
- * cpr3_msm8996_mmss_apply_closed_loop_offset_voltages() - modify the
- * closed-loop voltage adjustments by the amounts that are needed
- * for this fuse combo
+ * cpr3_msm8996_mmss_adjust_target_quotients() - adjust the target quotients
+ * for each corner according to device tree values and fuse values
* @vreg: Pointer to the CPR3 regulator
- * @volt_adjust: Array of closed-loop voltage adjustment values of length
- * vreg->corner_count which is further adjusted based upon
- * offset voltage fuse values.
*
* Return: 0 on success, errno on failure
*/
-static int cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(
- struct cpr3_regulator *vreg, int *volt_adjust)
+static int cpr3_msm8996_mmss_adjust_target_quotients(
+ struct cpr3_regulator *vreg)
{
struct cpr3_msm8996_mmss_fuses *fuse = vreg->platform_fuses;
const struct cpr3_fuse_param (*offset_param)[2];
- u32 *corner_map;
int *volt_offset;
- int rc = 0, i, fuse_len;
-
- if (!of_find_property(vreg->of_node,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
- /* No closed-loop offset required. */
- return 0;
- }
+ int i, fuse_len, rc = 0;
- corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
- GFP_KERNEL);
volt_offset = kcalloc(vreg->fuse_corner_count, sizeof(*volt_offset),
GFP_KERNEL);
- if (!corner_map || !volt_offset) {
- rc = -ENOMEM;
- goto done;
- }
-
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
- 1, corner_map);
- if (rc)
- goto done;
+ if (!volt_offset)
+ return -ENOMEM;
offset_param = cpr3_ctrl_is_msm8998(vreg->thread->ctrl)
? msm8998_mmss_offset_voltage_param
@@ -507,223 +486,11 @@ static int cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(
i, volt_offset[i]);
}
- for (i = 0; i < vreg->corner_count; i++) {
- if (corner_map[i] == 0) {
- continue;
- } else if (corner_map[i] > vreg->fuse_corner_count) {
- cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
- i, corner_map[i]);
- rc = -EINVAL;
- goto done;
- }
-
- volt_adjust[i] += volt_offset[corner_map[i] - 1];
- }
+ rc = cpr3_adjust_target_quotients(vreg, volt_offset);
+ if (rc)
+ cpr3_err(vreg, "adjust target quotients failed, rc=%d\n", rc);
-done:
- kfree(corner_map);
kfree(volt_offset);
-
- return rc;
-}
-
-/**
- * cpr3_mmss_enforce_inc_quotient_monotonicity() - Ensure that target quotients
- * increase monotonically from lower to higher corners
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static void cpr3_mmss_enforce_inc_quotient_monotonicity(
- struct cpr3_regulator *vreg)
-{
- int i, j;
-
- for (i = 1; i < vreg->corner_count; i++) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j]
- && vreg->corner[i].target_quot[j]
- < vreg->corner[i - 1].target_quot[j]) {
- cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
- i, j,
- vreg->corner[i].target_quot[j],
- i - 1, j,
- vreg->corner[i - 1].target_quot[j],
- i, j,
- vreg->corner[i - 1].target_quot[j]);
- vreg->corner[i].target_quot[j]
- = vreg->corner[i - 1].target_quot[j];
- }
- }
- }
-}
-
-/**
- * cpr3_mmss_enforce_dec_quotient_monotonicity() - Ensure that target quotients
- * decrease monotonically from higher to lower corners
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static void cpr3_mmss_enforce_dec_quotient_monotonicity(
- struct cpr3_regulator *vreg)
-{
- int i, j;
-
- for (i = vreg->corner_count - 2; i >= 0; i--) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i + 1].target_quot[j]
- && vreg->corner[i].target_quot[j]
- > vreg->corner[i + 1].target_quot[j]) {
- cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
- i, j,
- vreg->corner[i].target_quot[j],
- i + 1, j,
- vreg->corner[i + 1].target_quot[j],
- i, j,
- vreg->corner[i + 1].target_quot[j]);
- vreg->corner[i].target_quot[j]
- = vreg->corner[i + 1].target_quot[j];
- }
- }
- }
-}
-
-/**
- * _cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
- * corner of the regulator according to input adjustment and
- * scaling arrays
- * @vreg: Pointer to the CPR3 regulator
- * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
- * with units of microvolts. The array must have
- * vreg->corner_count number of elements.
- * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
- * The array must have an inner dimension of CPR3_RO_COUNT
- * and an outer dimension of vreg->corner_count
- * @label: Null terminated string providing a label for the type
- * of adjustment.
- *
- * Return: true if any corners received a positive voltage adjustment (> 0),
- * else false
- */
-static bool _cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg,
- const int *volt_adjust, const int *ro_scale, const char *label)
-{
- int i, j, quot_adjust;
- bool is_increasing = false;
- u32 prev_quot;
-
- for (i = 0; i < vreg->corner_count; i++) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j]) {
- quot_adjust = cpr3_quot_adjustment(
- ro_scale[i * CPR3_RO_COUNT + j],
- volt_adjust[i]);
- if (quot_adjust) {
- prev_quot = vreg->corner[i].
- target_quot[j];
- vreg->corner[i].target_quot[j]
- += quot_adjust;
- cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
- i, j, label, prev_quot,
- vreg->corner[i].target_quot[j],
- volt_adjust[i]);
- }
- }
- }
- if (volt_adjust[i] > 0)
- is_increasing = true;
- }
-
- return is_increasing;
-}
-
-/**
- * cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
- * corner according to device tree values and fuse values
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static int cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
-{
- int i, rc;
- int *volt_adjust, *ro_scale;
- bool explicit_adjustment, fused_adjustment, is_increasing;
-
- explicit_adjustment = of_find_property(vreg->of_node,
- "qcom,cpr-closed-loop-voltage-adjustment", NULL);
- fused_adjustment = of_find_property(vreg->of_node,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
-
- if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
- /* No adjustment required. */
- return 0;
- } else if (!of_find_property(vreg->of_node,
- "qcom,cpr-ro-scaling-factor", NULL)) {
- cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
- return -EINVAL;
- }
-
- volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
- GFP_KERNEL);
- ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
- sizeof(*ro_scale), GFP_KERNEL);
- if (!volt_adjust || !ro_scale) {
- rc = -ENOMEM;
- goto done;
- }
-
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
- if (rc) {
- cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
- rc);
- goto done;
- }
-
- for (i = 0; i < vreg->corner_count; i++)
- memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
- sizeof(*ro_scale) * CPR3_RO_COUNT);
-
- if (explicit_adjustment) {
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-closed-loop-voltage-adjustment",
- 1, volt_adjust);
- if (rc) {
- cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
- rc);
- goto done;
- }
-
- _cpr3_mmss_adjust_target_quotients(vreg, volt_adjust, ro_scale,
- "from DT");
- cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
- }
-
- if (fused_adjustment) {
- memset(volt_adjust, 0,
- sizeof(*volt_adjust) * vreg->corner_count);
-
- rc = cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(vreg,
- volt_adjust);
- if (rc) {
- cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
- rc);
- goto done;
- }
-
- is_increasing = _cpr3_mmss_adjust_target_quotients(vreg,
- volt_adjust, ro_scale, "from fuse");
- if (is_increasing)
- cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
- else
- cpr3_mmss_enforce_dec_quotient_monotonicity(vreg);
- }
-
-done:
- kfree(volt_adjust);
- kfree(ro_scale);
return rc;
}
@@ -1112,7 +879,7 @@ static int cpr3_mmss_init_thread(struct cpr3_thread *thread)
return rc;
}
- rc = cpr3_mmss_adjust_target_quotients(vreg);
+ rc = cpr3_msm8996_mmss_adjust_target_quotients(vreg);
if (rc) {
cpr3_err(vreg, "unable to adjust target quotients, rc=%d\n",
rc);
diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h
index 2e997b526b90..f0230b8ae2e5 100644
--- a/drivers/regulator/cpr3-regulator.h
+++ b/drivers/regulator/cpr3-regulator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -904,6 +904,8 @@ int cpr3_apm_init(struct cpr3_controller *ctrl);
int cpr3_mem_acc_init(struct cpr3_regulator *vreg);
void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg);
void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg);
+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust);
#else
@@ -1084,6 +1086,12 @@ static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
{
}
+static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust)
+{
+ return 0;
+}
+
#endif /* CONFIG_REGULATOR_CPR3 */
#endif /* __REGULATOR_CPR_REGULATOR_H__ */
diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c
index 7f712d4f6ee4..0a1a1c56bd16 100644
--- a/drivers/regulator/cpr3-util.c
+++ b/drivers/regulator/cpr3-util.c
@@ -2147,3 +2147,259 @@ void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
corner->ceiling_volt, corner->open_loop_volt);
}
}
+
+/**
+ * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage
+ * adjustments by the amounts that are needed for this
+ * fuse combo
+ * @vreg: Pointer to the CPR3 regulator
+ * @volt_adjust: Array of closed-loop voltage adjustment values of length
+ * vreg->corner_count which is further adjusted based upon
+ * offset voltage fuse values.
+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
+ * vreg->fuse_corner_count.
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg,
+ int *volt_adjust, int *fuse_volt_adjust)
+{
+ u32 *corner_map;
+ int rc = 0, i;
+
+ if (!of_find_property(vreg->of_node,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
+ /* No closed-loop offset required. */
+ return 0;
+ }
+
+ corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
+ GFP_KERNEL);
+ if (!corner_map)
+ return -ENOMEM;
+
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
+ 1, corner_map);
+ if (rc)
+ goto done;
+
+ for (i = 0; i < vreg->corner_count; i++) {
+ if (corner_map[i] == 0) {
+ continue;
+ } else if (corner_map[i] > vreg->fuse_corner_count) {
+ cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
+ i, corner_map[i]);
+ rc = -EINVAL;
+ goto done;
+ }
+
+ volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1];
+ }
+
+done:
+ kfree(corner_map);
+ return rc;
+}
+
+/**
+ * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients
+ * increase monotonically from lower to higher corners
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg)
+{
+ int i, j;
+
+ for (i = 1; i < vreg->corner_count; i++) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i].target_quot[j]
+ && vreg->corner[i].target_quot[j]
+ < vreg->corner[i - 1].target_quot[j]) {
+ cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
+ i, j,
+ vreg->corner[i].target_quot[j],
+ i - 1, j,
+ vreg->corner[i - 1].target_quot[j],
+ i, j,
+ vreg->corner[i - 1].target_quot[j]);
+ vreg->corner[i].target_quot[j]
+ = vreg->corner[i - 1].target_quot[j];
+ }
+ }
+ }
+}
+
+/**
+ * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients
+ * decrease monotonically from higher to lower corners
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg)
+{
+ int i, j;
+
+ for (i = vreg->corner_count - 2; i >= 0; i--) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i + 1].target_quot[j]
+ && vreg->corner[i].target_quot[j]
+ > vreg->corner[i + 1].target_quot[j]) {
+ cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
+ i, j,
+ vreg->corner[i].target_quot[j],
+ i + 1, j,
+ vreg->corner[i + 1].target_quot[j],
+ i, j,
+ vreg->corner[i + 1].target_quot[j]);
+ vreg->corner[i].target_quot[j]
+ = vreg->corner[i + 1].target_quot[j];
+ }
+ }
+ }
+}
+
+/**
+ * _cpr3_adjust_target_quotients() - adjust the target quotients for each
+ * corner of the regulator according to input adjustment and
+ * scaling arrays
+ * @vreg: Pointer to the CPR3 regulator
+ * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
+ * with units of microvolts. The array must have
+ * vreg->corner_count number of elements.
+ * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
+ * The array must have an inner dimension of CPR3_RO_COUNT
+ * and an outer dimension of vreg->corner_count
+ * @label: Null terminated string providing a label for the type
+ * of adjustment.
+ *
+ * Return: true if any corners received a positive voltage adjustment (> 0),
+ * else false
+ */
+static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ const int *volt_adjust, const int *ro_scale, const char *label)
+{
+ int i, j, quot_adjust;
+ bool is_increasing = false;
+ u32 prev_quot;
+
+ for (i = 0; i < vreg->corner_count; i++) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i].target_quot[j]) {
+ quot_adjust = cpr3_quot_adjustment(
+ ro_scale[i * CPR3_RO_COUNT + j],
+ volt_adjust[i]);
+ if (quot_adjust) {
+ prev_quot = vreg->corner[i].
+ target_quot[j];
+ vreg->corner[i].target_quot[j]
+ += quot_adjust;
+ cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
+ i, j, label, prev_quot,
+ vreg->corner[i].target_quot[j],
+ volt_adjust[i]);
+ }
+ }
+ }
+ if (volt_adjust[i] > 0)
+ is_increasing = true;
+ }
+
+ return is_increasing;
+}
+
+/**
+ * cpr3_adjust_target_quotients() - adjust the target quotients for each
+ * corner according to device tree values and fuse values
+ * @vreg: Pointer to the CPR3 regulator
+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
+ * vreg->fuse_corner_count. This parameter could be null
+ * pointer when no fused adjustments are needed.
+ *
+ * Return: 0 on success, errno on failure
+ */
+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust)
+{
+ int i, rc;
+ int *volt_adjust, *ro_scale;
+ bool explicit_adjustment, fused_adjustment, is_increasing;
+
+ explicit_adjustment = of_find_property(vreg->of_node,
+ "qcom,cpr-closed-loop-voltage-adjustment", NULL);
+ fused_adjustment = of_find_property(vreg->of_node,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
+
+ if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
+ /* No adjustment required. */
+ return 0;
+ } else if (!of_find_property(vreg->of_node,
+ "qcom,cpr-ro-scaling-factor", NULL)) {
+ cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
+ return -EINVAL;
+ }
+
+ volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
+ GFP_KERNEL);
+ ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
+ sizeof(*ro_scale), GFP_KERNEL);
+ if (!volt_adjust || !ro_scale) {
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
+ if (rc) {
+ cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ for (i = 0; i < vreg->corner_count; i++)
+ memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
+ sizeof(*ro_scale) * CPR3_RO_COUNT);
+
+ if (explicit_adjustment) {
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-closed-loop-voltage-adjustment",
+ 1, volt_adjust);
+ if (rc) {
+ cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale,
+ "from DT");
+ cpr3_enforce_inc_quotient_monotonicity(vreg);
+ }
+
+ if (fused_adjustment && fuse_volt_adjust) {
+ memset(volt_adjust, 0,
+ sizeof(*volt_adjust) * vreg->corner_count);
+
+ rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust,
+ fuse_volt_adjust);
+ if (rc) {
+ cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust,
+ ro_scale, "from fuse");
+ if (is_increasing)
+ cpr3_enforce_inc_quotient_monotonicity(vreg);
+ else
+ cpr3_enforce_dec_quotient_monotonicity(vreg);
+ }
+
+done:
+ kfree(volt_adjust);
+ kfree(ro_scale);
+ return rc;
+}
diff --git a/drivers/regulator/cpr4-mmss-ldo-regulator.c b/drivers/regulator/cpr4-mmss-ldo-regulator.c
index 2843f71745fc..f8e3ea40ddac 100644
--- a/drivers/regulator/cpr4-mmss-ldo-regulator.c
+++ b/drivers/regulator/cpr4-mmss-ldo-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -417,6 +417,45 @@ done:
}
/**
+ * cpr4_sdm660_mmss_adjust_target_quotients() - adjust the target quotients for
+ * each corner according to device tree values and fuse values
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int cpr4_sdm660_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
+{
+ struct cpr4_sdm660_mmss_fuses *fuse = vreg->platform_fuses;
+ const struct cpr3_fuse_param (*offset_param)[2];
+ int *volt_offset;
+ int i, fuse_len, rc = 0;
+
+ volt_offset = kcalloc(vreg->fuse_corner_count, sizeof(*volt_offset),
+ GFP_KERNEL);
+ if (!volt_offset)
+ return -ENOMEM;
+
+ offset_param = sdm660_mmss_offset_voltage_param;
+ for (i = 0; i < vreg->fuse_corner_count; i++) {
+ fuse_len = offset_param[i][0].bit_end + 1
+ - offset_param[i][0].bit_start;
+ volt_offset[i] = cpr3_convert_open_loop_voltage_fuse(
+ 0, SDM660_MMSS_OFFSET_FUSE_STEP_VOLT,
+ fuse->offset_voltage[i], fuse_len);
+ if (volt_offset[i])
+ cpr3_info(vreg, "fuse_corner[%d] offset=%7d uV\n",
+ i, volt_offset[i]);
+ }
+
+ rc = cpr3_adjust_target_quotients(vreg, volt_offset);
+ if (rc)
+ cpr3_err(vreg, "adjust target quotients failed, rc=%d\n", rc);
+
+ kfree(volt_offset);
+ return rc;
+}
+
+/**
* cpr4_mmss_print_settings() - print out MMSS CPR configuration settings into
* the kernel log for debugging purposes
* @vreg: Pointer to the CPR3 regulator
@@ -489,6 +528,13 @@ static int cpr4_mmss_init_thread(struct cpr3_thread *thread)
return rc;
}
+ rc = cpr4_sdm660_mmss_adjust_target_quotients(vreg);
+ if (rc) {
+ cpr3_err(vreg, "unable to adjust target quotients, rc=%d\n",
+ rc);
+ return rc;
+ }
+
rc = cpr4_sdm660_mmss_calculate_open_loop_voltages(vreg);
if (rc) {
cpr3_err(vreg, "unable to calculate open-loop voltages, rc=%d\n",
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c
index 8dbe3080873c..40c62c355188 100644
--- a/drivers/regulator/qpnp-labibb-regulator.c
+++ b/drivers/regulator/qpnp-labibb-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -333,7 +333,7 @@ enum ibb_mode {
IBB_HW_SW_CONTROL,
};
-static const int ibb_discharge_resistor_table[] = {
+static const int ibb_dischg_res_table[] = {
300,
64,
32,
@@ -946,38 +946,27 @@ static int qpnp_ibb_soft_start_ctl_v1(struct qpnp_labibb *labibb,
rc = of_property_read_u32(of_node, "qcom,qpnp-ibb-discharge-resistor",
&tmp);
+ if (!rc) {
+ for (val = 0; val < ARRAY_SIZE(ibb_dischg_res_table); val++) {
+ if (ibb_dischg_res_table[val] == tmp)
+ break;
+ }
- if (rc < 0) {
- pr_err("qcom,qpnp-ibb-discharge-resistor is missing, rc = %d\n",
- rc);
- return rc;
- }
-
- if (labibb->mode == QPNP_LABIBB_AMOLED_MODE) {
- /*
- * AMOLED mode needs ibb discharge resistor to be
- * configured for 300KOhm
- */
- if (tmp < ibb_discharge_resistor_table[0])
- tmp = ibb_discharge_resistor_table[0];
- }
-
- for (val = 0; val < ARRAY_SIZE(ibb_discharge_resistor_table); val++)
- if (ibb_discharge_resistor_table[val] == tmp)
- break;
+ if (val == ARRAY_SIZE(ibb_dischg_res_table)) {
+ pr_err("Invalid value in qcom,qpnp-ibb-discharge-resistor\n");
+ return -EINVAL;
+ }
- if (val == ARRAY_SIZE(ibb_discharge_resistor_table)) {
- pr_err("Invalid value in qcom,qpnp-ibb-discharge-resistor\n");
- return -EINVAL;
+ rc = qpnp_labibb_write(labibb, labibb->ibb_base +
+ REG_IBB_SOFT_START_CTL, &val, 1);
+ if (rc < 0) {
+ pr_err("write to register %x failed rc = %d\n",
+ REG_IBB_SOFT_START_CTL, rc);
+ return rc;
+ }
}
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_SOFT_START_CTL, &val, 1);
- if (rc < 0)
- pr_err("write to register %x failed rc = %d\n",
- REG_IBB_SOFT_START_CTL, rc);
-
- return rc;
+ return 0;
}
static int qpnp_ibb_soft_start_ctl_v2(struct qpnp_labibb *labibb,
@@ -2643,7 +2632,8 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
return rc;
}
- if (labibb->mode == QPNP_LABIBB_AMOLED_MODE) {
+ if (labibb->mode == QPNP_LABIBB_AMOLED_MODE &&
+ labibb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) {
/*
* default to 1.5 times current gain if
* user doesn't specify the current-sense
@@ -2684,7 +2674,7 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN;
rc = qpnp_labibb_sec_write(labibb, labibb->lab_base,
- REG_LAB_IBB_EN_RDY, val);
+ REG_LAB_IBB_EN_RDY, val);
if (rc < 0) {
pr_err("qpnp_lab_sec_write register %x failed rc = %d\n",
@@ -3331,7 +3321,7 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
struct regulator_init_data *init_data;
struct regulator_desc *rdesc = &labibb->ibb_vreg.rdesc;
struct regulator_config cfg = {};
- u8 val, ibb_enable_ctl;
+ u8 val, ibb_enable_ctl, index;
u32 tmp;
if (!of_node) {
@@ -3407,7 +3397,8 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
* before by the bootloader.
*/
if (labibb->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE)
- labibb->swire_control = val & IBB_ENABLE_CTL_SWIRE_RDY;
+ labibb->swire_control = ibb_enable_ctl &
+ IBB_ENABLE_CTL_SWIRE_RDY;
if (ibb_enable_ctl &
(IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) {
@@ -3460,11 +3451,11 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
return rc;
}
- labibb->ibb_vreg.pwrup_dly = ibb_pwrup_dly_table[
- (val &
- IBB_PWRUP_PWRDN_CTL_1_DLY1_MASK)];
- labibb->ibb_vreg.pwrdn_dly = ibb_pwrdn_dly_table[val &
- IBB_PWRUP_PWRDN_CTL_1_DLY2_MASK];
+ index = (val & IBB_PWRUP_PWRDN_CTL_1_DLY1_MASK) >>
+ IBB_PWRUP_PWRDN_CTL_1_DLY1_SHIFT;
+ labibb->ibb_vreg.pwrup_dly = ibb_pwrup_dly_table[index];
+ index = val & IBB_PWRUP_PWRDN_CTL_1_DLY2_MASK;
+ labibb->ibb_vreg.pwrdn_dly = ibb_pwrdn_dly_table[index];
labibb->ibb_vreg.vreg_enabled = 1;
} else {
@@ -3829,9 +3820,10 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
}
}
dev_set_drvdata(&pdev->dev, labibb);
- pr_info("LAB/IBB registered successfully, lab_vreg enable=%d ibb_vreg enable=%d\n",
+ pr_info("LAB/IBB registered successfully, lab_vreg enable=%d ibb_vreg enable=%d swire_control=%d\n",
labibb->lab_vreg.vreg_enabled,
- labibb->ibb_vreg.vreg_enabled);
+ labibb->ibb_vreg.vreg_enabled,
+ labibb->swire_control);
return 0;
diff --git a/drivers/regulator/qpnp-oledb-regulator.c b/drivers/regulator/qpnp-oledb-regulator.c
index dd52b74b11b6..587538cca474 100644
--- a/drivers/regulator/qpnp-oledb-regulator.c
+++ b/drivers/regulator/qpnp-oledb-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -152,6 +152,8 @@ struct qpnp_oledb {
struct qpnp_oledb_fast_precharge_ctl fast_prechg_ctl;
u32 base;
+ u8 mod_enable;
+ u8 ext_pinctl_state;
int current_voltage;
int default_voltage;
int vout_mv;
@@ -162,10 +164,8 @@ struct qpnp_oledb {
int nlimit_enable;
int sc_en;
int sc_dbnc_time;
- bool mod_enable;
bool swire_control;
bool ext_pin_control;
- bool ext_pinctl_state;
bool dynamic_ext_pinctl_config;
bool pbs_control;
};
@@ -292,12 +292,15 @@ static int qpnp_oledb_regulator_disable(struct regulator_dev *rdev)
* Disable ext-pin-ctl after display-supply is turned off. This is to
* avoid glitches on the external pin.
*/
- if (oledb->ext_pin_control && oledb->dynamic_ext_pinctl_config) {
- rc = qpnp_oledb_masked_write(oledb, oledb->base +
+ if (oledb->ext_pin_control) {
+ if (oledb->dynamic_ext_pinctl_config) {
+ rc = qpnp_oledb_masked_write(oledb, oledb->base +
OLEDB_EXT_PIN_CTL, OLEDB_EXT_PIN_CTL_BIT, 0);
- if (rc < 0) {
- pr_err("Failed to write EXT_PIN_CTL rc=%d\n", rc);
- return rc;
+ if (rc < 0) {
+ pr_err("Failed to write EXT_PIN_CTL rc=%d\n",
+ rc);
+ return rc;
+ }
}
pr_debug("ext-pin-ctrl mode disabled\n");
} else {
@@ -635,14 +638,14 @@ static int qpnp_oledb_hw_init(struct qpnp_oledb *oledb)
}
rc = qpnp_oledb_read(oledb, oledb->base + OLEDB_MODULE_ENABLE,
- (u8 *)&oledb->mod_enable, 1);
+ &oledb->mod_enable, 1);
if (rc < 0) {
pr_err("Failed to read MODULE_ENABLE rc=%d\n", rc);
return rc;
}
rc = qpnp_oledb_read(oledb, oledb->base + OLEDB_EXT_PIN_CTL,
- (u8 *)&oledb->ext_pinctl_state, 1);
+ &oledb->ext_pinctl_state, 1);
if (rc < 0) {
pr_err("Failed to read EXT_PIN_CTL rc=%d\n", rc);
return rc;
@@ -652,7 +655,12 @@ static int qpnp_oledb_hw_init(struct qpnp_oledb *oledb)
if (rc < 0)
return rc;
- if (!((val & OLEDB_EXT_PIN_CTL_BIT) || oledb->mod_enable)) {
+ /*
+ * Go through if the module is not enabled either through
+ * external pin control or SPMI interface.
+ */
+ if (!((oledb->ext_pinctl_state & OLEDB_EXT_PIN_CTL_BIT)
+ || oledb->mod_enable)) {
if (oledb->warmup_delay != -EINVAL) {
for (i = 0; i < ARRAY_SIZE(oledb_warmup_dly_ns); i++) {
if (oledb->warmup_delay ==
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index 070d27df6b49..85f82b2251c1 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/blkdev.h>
+#include <linux/spinlock.h>
#include <crypto/ice.h>
#include "ufs-qcom-ice.h"
@@ -168,6 +169,7 @@ out:
static void ufs_qcom_ice_cfg_work(struct work_struct *work)
{
+ unsigned long flags;
struct ice_data_setting ice_set;
struct ufs_qcom_host *qcom_host =
container_of(work, struct ufs_qcom_host, ice_cfg_work);
@@ -185,12 +187,17 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
qcom_host->req_pending, &ice_set, false);
+ spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
+ qcom_host->req_pending = NULL;
+ spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
+
/*
* Resume with requests processing. We assume config_start has been
* successful, but even if it wasn't we still must resume in order to
* allow for the request to be retried.
*/
ufshcd_scsi_unblock_requests(qcom_host->hba);
+
}
/**
@@ -246,6 +253,7 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
struct ice_data_setting ice_set;
char cmd_op = cmd->cmnd[0];
int err;
+ unsigned long flags;
if (!qcom_host->ice.pdev || !qcom_host->ice.vops) {
dev_dbg(qcom_host->hba->dev, "%s: ice device is not enabled\n",
@@ -272,14 +280,36 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
__func__);
- qcom_host->req_pending = cmd->request;
- if (schedule_work(&qcom_host->ice_cfg_work))
+
+ spin_lock_irqsave(
+ &qcom_host->ice_work_lock, flags);
+
+ if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
qcom_host->hba);
+ qcom_host->req_pending = cmd->request;
+ if (!schedule_work(
+ &qcom_host->ice_cfg_work)) {
+ qcom_host->req_pending = NULL;
+
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ ufshcd_scsi_unblock_requests(
+ qcom_host->hba);
+ return err;
+ }
+ }
+
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock, flags);
+
} else {
- dev_err(qcom_host->hba->dev,
- "%s: error in ice_vops->config %d\n",
- __func__, err);
+ if (err != -EBUSY)
+ dev_err(qcom_host->hba->dev,
+ "%s: error in ice_vops->config %d\n",
+ __func__, err);
}
return err;
@@ -320,6 +350,7 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
unsigned int bypass = 0;
struct request *req;
char cmd_op;
+ unsigned long flags;
if (!qcom_host->ice.pdev || !qcom_host->ice.vops) {
dev_dbg(dev, "%s: ice device is not enabled\n", __func__);
@@ -365,12 +396,43 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
* request processing.
*/
if (err == -EAGAIN) {
- qcom_host->req_pending = req;
- if (schedule_work(&qcom_host->ice_cfg_work))
+
+ dev_dbg(qcom_host->hba->dev,
+ "%s: scheduling task for ice setup\n",
+ __func__);
+
+ spin_lock_irqsave(
+ &qcom_host->ice_work_lock, flags);
+
+ if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
+ qcom_host->hba);
+ qcom_host->req_pending = cmd->request;
+ if (!schedule_work(
+ &qcom_host->ice_cfg_work)) {
+ qcom_host->req_pending = NULL;
+
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ ufshcd_scsi_unblock_requests(
qcom_host->hba);
+ return err;
+ }
+ }
+
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock, flags);
+
+ } else {
+ if (err != -EBUSY)
+ dev_err(qcom_host->hba->dev,
+ "%s: error in ice_vops->config %d\n",
+ __func__, err);
}
- goto out;
+
+ return err;
}
}
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 2b0731b8358c..03b222d8be93 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1981,6 +1981,8 @@ static int ufs_qcom_init(struct ufs_hba *hba)
/* Make a two way bind between the qcom host and the hba */
host->hba = hba;
+ spin_lock_init(&host->ice_work_lock);
+
ufshcd_set_variant(hba, host);
err = ufs_qcom_ice_get_dev(host);
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 394de8302fd2..74d8a7a30ad6 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -370,6 +370,7 @@ struct ufs_qcom_host {
u32 dbg_print_en;
struct ufs_qcom_testbus testbus;
+ spinlock_t ice_work_lock;
struct work_struct ice_cfg_work;
struct request *req_pending;
};
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1e6db2a76fa5..d4acc3c911f5 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -48,6 +48,7 @@
#include "ufshci.h"
#include "ufs_quirks.h"
#include "ufs-debugfs.h"
+#include "ufs-qcom.h"
#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
@@ -2884,11 +2885,11 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
"%s: failed to compose upiu %d\n",
__func__, err);
- lrbp->cmd = NULL;
- clear_bit_unlock(tag, &hba->lrb_in_use);
- ufshcd_release_all(hba);
- ufshcd_vops_pm_qos_req_end(hba, cmd->request, true);
- goto out;
+ lrbp->cmd = NULL;
+ clear_bit_unlock(tag, &hba->lrb_in_use);
+ ufshcd_release_all(hba);
+ ufshcd_vops_pm_qos_req_end(hba, cmd->request, true);
+ goto out;
}
err = ufshcd_map_sg(lrbp);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 281e83d90970..86e29199b2b1 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -625,6 +625,14 @@ config MSM_ADSP_LOADER
for the platforms that use APRv2.
Say M if you want to enable this module.
+config MSM_CDSP_LOADER
+ tristate "CDSP loader support"
+ help
+ Enable CDSP image loader.
+ The CDSP loader brings CDSP out of reset
+ during boot.
+ Say M if you want to enable this module.
+
config MSM_PERFORMANCE
tristate "msm_performance driver to support perflock request"
help
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 84f346385f18..f2d2aece6846 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -51,7 +51,7 @@
#define RPM_MAX_TOC_ENTRIES 20
#define RPM_FIFO_ADDR_ALIGN_BYTES 3
#define TRACER_PKT_FEATURE BIT(2)
-
+#define DEFERRED_CMDS_THRESHOLD 25
/**
* enum command_types - definition of the types of commands sent/received
* @VERSION_CMD: Version and feature set supported
@@ -181,6 +181,7 @@ struct mailbox_config_info {
* processing.
* @deferred_cmds: List of deferred commands that need to be
* processed in process context.
+ * @deferred_cmds_cnt: Number of deferred commands in queue.
* @num_pw_states: Size of @ramp_time_us.
* @ramp_time_us: Array of ramp times in microseconds where array
* index position represents a power state.
@@ -218,6 +219,7 @@ struct edge_info {
bool in_ssr;
spinlock_t rx_lock;
struct list_head deferred_cmds;
+ uint32_t deferred_cmds_cnt;
uint32_t num_pw_states;
unsigned long *ramp_time_us;
struct mailbox_config_info *mailbox;
@@ -768,6 +770,7 @@ static bool queue_cmd(struct edge_info *einfo, void *cmd, void *data)
d_cmd->param2 = _cmd->param2;
d_cmd->data = data;
list_add_tail(&d_cmd->list_node, &einfo->deferred_cmds);
+ einfo->deferred_cmds_cnt++;
queue_kthread_work(&einfo->kworker, &einfo->kwork);
return true;
}
@@ -877,10 +880,15 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
if (einfo->in_ssr)
break;
+ if (atomic_ctx && !einfo->intentless &&
+ einfo->deferred_cmds_cnt >= DEFERRED_CMDS_THRESHOLD)
+ break;
+
if (!atomic_ctx && !list_empty(&einfo->deferred_cmds)) {
d_cmd = list_first_entry(&einfo->deferred_cmds,
struct deferred_cmd, list_node);
list_del(&d_cmd->list_node);
+ einfo->deferred_cmds_cnt--;
cmd.id = d_cmd->id;
cmd.param1 = d_cmd->param1;
cmd.param2 = d_cmd->param2;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 44d086656a12..873416944b19 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1661,10 +1661,8 @@ static int icnss_driver_event_server_arrive(void *data)
if (ret < 0)
goto err_setup_msa;
- ret = wlfw_dynamic_feature_mask_send_sync_msg(penv,
- dynamic_feature_mask);
- if (ret < 0)
- goto err_setup_msa;
+ wlfw_dynamic_feature_mask_send_sync_msg(penv,
+ dynamic_feature_mask);
icnss_init_vph_monitor(penv);
@@ -2068,7 +2066,7 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
icnss_pr_info("Modem went down, state: %lx\n", priv->state);
- event_data = kzalloc(sizeof(*data), GFP_KERNEL);
+ event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (event_data == NULL)
return notifier_from_errno(-ENOMEM);
@@ -2143,7 +2141,7 @@ static int icnss_service_notifier_notify(struct notifier_block *nb,
case SERVREG_NOTIF_SERVICE_STATE_DOWN_V01:
icnss_pr_info("Service down, data: 0x%p, state: 0x%lx\n", data,
priv->state);
- event_data = kzalloc(sizeof(*data), GFP_KERNEL);
+ event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (event_data == NULL)
return notifier_from_errno(-ENOMEM);
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 5726c3277456..76f9ed046120 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@ static void mem_share_svc_recv_msg(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg);
static struct workqueue_struct *mem_share_svc_workqueue;
static uint64_t bootup_request;
+static bool ramdump_event;
static void *memshare_ramdump_dev[MAX_CLIENTS];
static struct device *memshare_dev[MAX_CLIENTS];
@@ -337,18 +338,25 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
bootup_request++;
break;
+ case SUBSYS_RAMDUMP_NOTIFICATION:
+ ramdump_event = 1;
+ break;
+
case SUBSYS_BEFORE_POWERUP:
- if (_cmd)
+ if (_cmd) {
notifdata = (struct notif_data *) _cmd;
- else
+ } else {
+ ramdump_event = 0;
break;
+ }
- if (notifdata->enable_ramdump) {
+ if (notifdata->enable_ramdump && ramdump_event) {
pr_info("memshare: %s, Ramdump collection is enabled\n",
__func__);
ret = mem_share_do_ramdump();
if (ret)
pr_err("Ramdump collection failed\n");
+ ramdump_event = 0;
}
break;
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index 9c4d89ac704d..d3f44ab75f67 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -1222,12 +1222,18 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
LOG_ERR("Smem partition %d cached heap exceeds size\n", num);
BUG();
}
- if (hdr->host0 == SMEM_COMM_HOST && hdr->host1 == SMEM_COMM_HOST) {
- comm_partition.partition_num = num;
- comm_partition.offset = entry->offset;
- comm_partition.size_cacheline = entry->size_cacheline;
- SMEM_INFO("Common Partition %d offset:%x\n", num,
- entry->offset);
+ if (is_comm_partition) {
+ if (hdr->host0 == SMEM_COMM_HOST
+ && hdr->host1 == SMEM_COMM_HOST) {
+ comm_partition.partition_num = num;
+ comm_partition.offset = entry->offset;
+ comm_partition.size_cacheline = entry->size_cacheline;
+ SMEM_INFO("Common Partition %d offset:%x\n", num,
+ entry->offset);
+ } else {
+ LOG_ERR("Smem Comm partition hosts don't match TOC\n");
+ WARN_ON(1);
+ }
return;
}
if (hdr->host0 != SMEM_APPS && hdr->host1 != SMEM_APPS) {
diff --git a/drivers/soc/qcom/qdsp6v2/Makefile b/drivers/soc/qcom/qdsp6v2/Makefile
index f3505bab1a34..8c5b0d0e81c8 100644
--- a/drivers/soc/qcom/qdsp6v2/Makefile
+++ b/drivers/soc/qcom/qdsp6v2/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_QDSP6_SSR) += audio_ssr.o
obj-$(CONFIG_MSM_QDSP6_PDR) += audio_pdr.o
obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += audio_notifier.o
+obj-$(CONFIG_MSM_CDSP_LOADER) += cdsp-loader.o
diff --git a/drivers/soc/qcom/qdsp6v2/cdsp-loader.c b/drivers/soc/qcom/qdsp6v2/cdsp-loader.c
new file mode 100644
index 000000000000..0b801c5cd7dd
--- /dev/null
+++ b/drivers/soc/qcom/qdsp6v2/cdsp-loader.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2012-2014,2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <soc/qcom/subsystem_restart.h>
+
+#define BOOT_CMD 1
+#define IMAGE_UNLOAD_CMD 0
+
+#define CDSP_SUBSYS_DOWN 0
+#define CDSP_SUBSYS_LOADED 1
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count);
+
+struct cdsp_loader_private {
+ void *pil_h;
+ struct kobject *boot_cdsp_obj;
+ struct attribute_group *attr_group;
+};
+
+static struct kobj_attribute cdsp_boot_attribute =
+ __ATTR(boot, 0220, NULL, cdsp_boot_store);
+
+static struct attribute *attrs[] = {
+ &cdsp_boot_attribute.attr,
+ NULL,
+};
+
+static u32 cdsp_state = CDSP_SUBSYS_DOWN;
+static struct platform_device *cdsp_private;
+static void cdsp_loader_unload(struct platform_device *pdev);
+
+static int cdsp_loader_do(struct platform_device *pdev)
+{
+
+ struct cdsp_loader_private *priv = NULL;
+
+ int rc = 0;
+ const char *img_name;
+
+ if (!pdev) {
+ dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
+ goto fail;
+ }
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev,
+ "%s: Device tree information missing\n", __func__);
+
+ goto fail;
+ }
+
+ rc = of_property_read_string(pdev->dev.of_node,
+ "qcom,proc-img-to-load",
+ &img_name);
+
+ if (rc)
+ goto fail;
+
+ if (!strcmp(img_name, "cdsp")) {
+ /* cdsp_state always returns "0".*/
+ if (cdsp_state == CDSP_SUBSYS_DOWN) {
+ priv = platform_get_drvdata(pdev);
+ if (!priv) {
+ dev_err(&pdev->dev,
+ " %s: Private data get failed\n", __func__);
+ goto fail;
+ }
+
+ priv->pil_h = subsystem_get("cdsp");
+ if (IS_ERR(priv->pil_h)) {
+ dev_err(&pdev->dev, "%s: pil get failed,\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Set the state of the CDSP.*/
+ cdsp_state = CDSP_SUBSYS_LOADED;
+ } else if (cdsp_state == CDSP_SUBSYS_LOADED) {
+ dev_dbg(&pdev->dev,
+ "%s: CDSP state = %x\n", __func__, cdsp_state);
+ }
+
+ dev_dbg(&pdev->dev, "%s: CDSP image is loaded\n", __func__);
+ return rc;
+ }
+
+fail:
+ dev_err(&pdev->dev, "%s: CDSP image loading failed\n", __func__);
+ return rc;
+}
+
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int boot = 0, ret = 0;
+
+ ret = sscanf(buf, "%du", &boot);
+
+ if (ret != 1)
+ pr_debug("%s: invalid arguments for cdsp_loader.\n", __func__);
+
+ if (boot == BOOT_CMD) {
+ pr_debug("%s: going to call cdsp_loader_do\n", __func__);
+ cdsp_loader_do(cdsp_private);
+ } else if (boot == IMAGE_UNLOAD_CMD) {
+ pr_debug("%s: going to call adsp_unloader\n", __func__);
+ cdsp_loader_unload(cdsp_private);
+ }
+ return count;
+}
+
+static void cdsp_loader_unload(struct platform_device *pdev)
+{
+ struct cdsp_loader_private *priv = NULL;
+
+ priv = platform_get_drvdata(pdev);
+
+ if (!priv)
+ return;
+
+ if (priv->pil_h) {
+ dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__);
+ subsystem_put(priv->pil_h);
+ priv->pil_h = NULL;
+ }
+}
+
+static int cdsp_loader_init_sysfs(struct platform_device *pdev)
+{
+ int ret = -EINVAL;
+ struct cdsp_loader_private *priv = NULL;
+
+ cdsp_private = NULL;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ priv->pil_h = NULL;
+ priv->boot_cdsp_obj = NULL;
+ priv->attr_group = devm_kzalloc(&pdev->dev,
+ sizeof(*(priv->attr_group)),
+ GFP_KERNEL);
+ if (!priv->attr_group) {
+ dev_err(&pdev->dev, "%s: malloc attr_group failed\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error_return;
+ }
+
+ priv->attr_group->attrs = attrs;
+
+ priv->boot_cdsp_obj = kobject_create_and_add("boot_cdsp", kernel_kobj);
+ if (!priv->boot_cdsp_obj) {
+ dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error_return;
+ }
+
+ ret = sysfs_create_group(priv->boot_cdsp_obj, priv->attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: sysfs create group failed %d\n",
+ __func__, ret);
+ goto error_return;
+ }
+
+ cdsp_private = pdev;
+
+ return 0;
+
+error_return:
+
+ if (priv->boot_cdsp_obj) {
+ kobject_del(priv->boot_cdsp_obj);
+ priv->boot_cdsp_obj = NULL;
+ }
+
+ return ret;
+}
+
+static int cdsp_loader_remove(struct platform_device *pdev)
+{
+ struct cdsp_loader_private *priv = NULL;
+
+ priv = platform_get_drvdata(pdev);
+
+ if (!priv)
+ return 0;
+
+ if (priv->pil_h) {
+ subsystem_put(priv->pil_h);
+ priv->pil_h = NULL;
+ }
+
+ if (priv->boot_cdsp_obj) {
+ sysfs_remove_group(priv->boot_cdsp_obj, priv->attr_group);
+ kobject_del(priv->boot_cdsp_obj);
+ priv->boot_cdsp_obj = NULL;
+ }
+
+ return 0;
+}
+
+static int cdsp_loader_probe(struct platform_device *pdev)
+{
+ int ret = cdsp_loader_init_sysfs(pdev);
+
+ if (ret != 0) {
+ dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id cdsp_loader_dt_match[] = {
+ { .compatible = "qcom,cdsp-loader" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cdsp_loader_dt_match);
+
+static struct platform_driver cdsp_loader_driver = {
+ .driver = {
+ .name = "cdsp-loader",
+ .owner = THIS_MODULE,
+ .of_match_table = cdsp_loader_dt_match,
+ },
+ .probe = cdsp_loader_probe,
+ .remove = cdsp_loader_remove,
+};
+
+static int __init cdsp_loader_init(void)
+{
+ return platform_driver_register(&cdsp_loader_driver);
+}
+module_init(cdsp_loader_init);
+
+static void __exit cdsp_loader_exit(void)
+{
+ platform_driver_unregister(&cdsp_loader_driver);
+}
+module_exit(cdsp_loader_exit);
+
+MODULE_DESCRIPTION("CDSP Loader module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index e7307c46a895..8a501d4d0615 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -215,7 +215,7 @@ static void send_ind_ack(struct work_struct *work)
if (QMI_RESP_BIT_SHIFT(resp.resp.result) != QMI_RESULT_SUCCESS_V01)
pr_err("QMI request failed 0x%x\n",
QMI_RESP_BIT_SHIFT(resp.resp.error));
- pr_debug("Indication ACKed for transid %d, service %s, instance %d!\n",
+ pr_info("Indication ACKed for transid %d, service %s, instance %d!\n",
data->ind_msg.transaction_id, data->ind_msg.service_path,
data->instance_id);
}
@@ -240,7 +240,7 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
return;
}
- pr_debug("Indication received from %s, state: 0x%x, trans-id: %d\n",
+ pr_info("Indication received from %s, state: 0x%x, trans-id: %d\n",
ind_msg.service_name, ind_msg.curr_state,
ind_msg.transaction_id);
diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c
index 27e66dc5d204..1ceded4db79f 100644
--- a/drivers/soc/qcom/wcd-dsp-glink.c
+++ b/drivers/soc/qcom/wcd-dsp-glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,8 +25,10 @@
#include "sound/wcd-dsp-glink.h"
#define WDSP_GLINK_DRIVER_NAME "wcd-dsp-glink"
-#define WDSP_MAX_WRITE_SIZE (512 * 1024)
+#define WDSP_MAX_WRITE_SIZE (256 * 1024)
#define WDSP_MAX_READ_SIZE (4 * 1024)
+#define WDSP_MAX_NO_OF_INTENTS (20)
+#define WDSP_MAX_NO_OF_CHANNELS (10)
#define MINOR_NUMBER_COUNT 1
#define WDSP_EDGE "wdsp"
@@ -532,15 +534,30 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
payload = (u8 *)pkt->payload;
no_of_channels = pkt->no_of_channels;
+ if (no_of_channels > WDSP_MAX_NO_OF_CHANNELS) {
+ dev_info(wpriv->dev, "%s: no_of_channels = %d are limited to %d\n",
+ __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS);
+ no_of_channels = WDSP_MAX_NO_OF_CHANNELS;
+ }
ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *),
GFP_KERNEL);
if (!ch) {
ret = -ENOMEM;
goto done;
}
+ wpriv->ch = ch;
+ wpriv->no_of_channels = no_of_channels;
for (i = 0; i < no_of_channels; i++) {
ch_cfg = (struct wdsp_glink_ch_cfg *)payload;
+
+ if (ch_cfg->no_of_intents > WDSP_MAX_NO_OF_INTENTS) {
+ dev_err(wpriv->dev, "%s: Invalid no_of_intents = %d\n",
+ __func__, ch_cfg->no_of_intents);
+ ret = -EINVAL;
+ goto err_ch_mem;
+ }
+
ch_cfg_size = sizeof(struct wdsp_glink_ch_cfg) +
(sizeof(u32) * ch_cfg->no_of_intents);
ch_size = sizeof(struct wdsp_glink_ch) +
@@ -564,8 +581,6 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk);
init_waitqueue_head(&ch[i]->ch_connect_wait);
}
- wpriv->ch = ch;
- wpriv->no_of_channels = no_of_channels;
INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk);
@@ -746,15 +761,17 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
goto done;
}
- dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
-
- if (count > WDSP_MAX_WRITE_SIZE) {
- dev_info(wpriv->dev, "%s: count = %zd is more than WDSP_MAX_WRITE_SIZE\n",
+ if ((count < sizeof(struct wdsp_write_pkt)) ||
+ (count > WDSP_MAX_WRITE_SIZE)) {
+ dev_err(wpriv->dev, "%s: Invalid count = %zd\n",
__func__, count);
- count = WDSP_MAX_WRITE_SIZE;
+ ret = -EINVAL;
+ goto done;
}
- tx_buf_size = count + sizeof(struct wdsp_glink_tx_buf);
+ dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
+
+ tx_buf_size = WDSP_MAX_WRITE_SIZE + sizeof(struct wdsp_glink_tx_buf);
tx_buf = kzalloc(tx_buf_size, GFP_KERNEL);
if (!tx_buf) {
ret = -ENOMEM;
@@ -772,6 +789,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
wpkt = (struct wdsp_write_pkt *)tx_buf->buf;
switch (wpkt->pkt_type) {
case WDSP_REG_PKT:
+ if (count <= (sizeof(struct wdsp_write_pkt) +
+ sizeof(struct wdsp_reg_pkt))) {
+ dev_err(wpriv->dev, "%s: Invalid reg pkt size = %zd\n",
+ __func__, count);
+ ret = -EINVAL;
+ goto free_buf;
+ }
ret = wdsp_glink_ch_info_init(wpriv,
(struct wdsp_reg_pkt *)wpkt->payload);
if (IS_ERR_VALUE(ret))
@@ -794,6 +818,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
kfree(tx_buf);
break;
case WDSP_CMD_PKT:
+ if (count <= (sizeof(struct wdsp_write_pkt) +
+ sizeof(struct wdsp_cmd_pkt))) {
+ dev_err(wpriv->dev, "%s: Invalid cmd pkt size = %zd\n",
+ __func__, count);
+ ret = -EINVAL;
+ goto free_buf;
+ }
mutex_lock(&wpriv->glink_mutex);
if (wpriv->glink_state.link_state == GLINK_LINK_STATE_DOWN) {
mutex_unlock(&wpriv->glink_mutex);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 7aa04a4fa156..b81348ceb469 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -45,8 +45,6 @@
#include <linux/msm-bus-board.h>
#include "spi_qsd.h"
-#define SPI_MAX_BYTES_PER_WORD (4)
-
static int msm_spi_pm_resume_runtime(struct device *device);
static int msm_spi_pm_suspend_runtime(struct device *device);
static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd);
@@ -440,12 +438,10 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd)
u32 data_in;
int i;
int shift;
- int read_bytes = (dd->pack_words ?
- SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word);
data_in = readl_relaxed(dd->base + SPI_INPUT_FIFO);
if (dd->read_buf) {
- for (i = 0; (i < read_bytes) &&
+ for (i = 0; (i < dd->bytes_per_word) &&
dd->rx_bytes_remaining; i++) {
/* The data format depends on bytes_per_word:
4 bytes: 0x12345678
@@ -458,8 +454,8 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd)
dd->rx_bytes_remaining--;
}
} else {
- if (dd->rx_bytes_remaining >= read_bytes)
- dd->rx_bytes_remaining -= read_bytes;
+ if (dd->rx_bytes_remaining >= dd->bytes_per_word)
+ dd->rx_bytes_remaining -= dd->bytes_per_word;
else
dd->rx_bytes_remaining = 0;
}
@@ -556,7 +552,7 @@ msm_spi_set_bpw_and_no_io_flags(struct msm_spi *dd, u32 *config, int n)
if (n != (*config & SPI_CFG_N))
*config = (*config & ~SPI_CFG_N) | n;
- if (dd->tx_mode == SPI_BAM_MODE) {
+ if (dd->mode == SPI_BAM_MODE) {
if (dd->read_buf == NULL)
*config |= SPI_NO_INPUT;
if (dd->write_buf == NULL)
@@ -621,34 +617,25 @@ static void msm_spi_set_spi_config(struct msm_spi *dd, int bpw)
static void msm_spi_set_mx_counts(struct msm_spi *dd, u32 n_words)
{
/*
- * For FIFO mode:
- * - Set the MX_OUTPUT_COUNT/MX_INPUT_COUNT registers to 0
- * - Set the READ/WRITE_COUNT registers to 0 (infinite mode)
- * or num bytes (finite mode) if less than fifo worth of data.
- * For Block mode:
- * - Set the MX_OUTPUT/MX_INPUT_COUNT registers to num xfer bytes.
- * - Set the READ/WRITE_COUNT registers to 0.
+ * n_words cannot exceed fifo_size, and only one READ COUNT
+ * interrupt is generated per transaction, so for transactions
+ * larger than fifo size READ COUNT must be disabled.
+ * For those transactions we usually move to Data Mover mode.
*/
- if (dd->tx_mode != SPI_BAM_MODE) {
- if (dd->tx_mode == SPI_FIFO_MODE) {
- if (n_words <= dd->input_fifo_size)
- msm_spi_set_write_count(dd, n_words);
- else
- msm_spi_set_write_count(dd, 0);
- writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT);
- } else
- writel_relaxed(n_words, dd->base + SPI_MX_OUTPUT_COUNT);
-
- if (dd->rx_mode == SPI_FIFO_MODE) {
- if (n_words <= dd->input_fifo_size)
- writel_relaxed(n_words,
- dd->base + SPI_MX_READ_COUNT);
- else
- writel_relaxed(0,
- dd->base + SPI_MX_READ_COUNT);
+ if (dd->mode == SPI_FIFO_MODE) {
+ if (n_words <= dd->input_fifo_size) {
+ writel_relaxed(n_words,
+ dd->base + SPI_MX_READ_COUNT);
+ msm_spi_set_write_count(dd, n_words);
+ } else {
+ writel_relaxed(0, dd->base + SPI_MX_READ_COUNT);
+ msm_spi_set_write_count(dd, 0);
+ }
+ if (dd->qup_ver == SPI_QUP_VERSION_BFAM) {
+ /* must be zero for FIFO */
writel_relaxed(0, dd->base + SPI_MX_INPUT_COUNT);
- } else
- writel_relaxed(n_words, dd->base + SPI_MX_INPUT_COUNT);
+ writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT);
+ }
} else {
/* must be zero for BAM and DMOV */
writel_relaxed(0, dd->base + SPI_MX_READ_COUNT);
@@ -895,7 +882,7 @@ xfr_err:
static int
msm_spi_bam_next_transfer(struct msm_spi *dd)
{
- if (dd->tx_mode != SPI_BAM_MODE)
+ if (dd->mode != SPI_BAM_MODE)
return 0;
if (dd->tx_bytes_remaining > 0) {
@@ -914,7 +901,7 @@ msm_spi_bam_next_transfer(struct msm_spi *dd)
static int msm_spi_dma_send_next(struct msm_spi *dd)
{
int ret = 0;
- if (dd->tx_mode == SPI_BAM_MODE)
+ if (dd->mode == SPI_BAM_MODE)
ret = msm_spi_bam_next_transfer(dd);
return ret;
}
@@ -945,38 +932,32 @@ static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id)
}
op = readl_relaxed(dd->base + SPI_OPERATIONAL);
- writel_relaxed(op, dd->base + SPI_OPERATIONAL);
- /*
- * Ensure service flag was cleared before further
- * processing of interrupt.
- */
- mb();
if (op & SPI_OP_INPUT_SERVICE_FLAG) {
+ writel_relaxed(SPI_OP_INPUT_SERVICE_FLAG,
+ dd->base + SPI_OPERATIONAL);
+ /*
+ * Ensure service flag was cleared before further
+ * processing of interrupt.
+ */
+ mb();
ret |= msm_spi_input_irq(irq, dev_id);
}
if (op & SPI_OP_OUTPUT_SERVICE_FLAG) {
+ writel_relaxed(SPI_OP_OUTPUT_SERVICE_FLAG,
+ dd->base + SPI_OPERATIONAL);
+ /*
+ * Ensure service flag was cleared before further
+ * processing of interrupt.
+ */
+ mb();
ret |= msm_spi_output_irq(irq, dev_id);
}
- if (dd->tx_mode != SPI_BAM_MODE) {
- if (!dd->rx_done) {
- if (dd->rx_bytes_remaining == 0)
- dd->rx_done = true;
- }
- if (!dd->tx_done) {
- if (!dd->tx_bytes_remaining &&
- (op & SPI_OP_IP_FIFO_NOT_EMPTY)) {
- dd->tx_done = true;
- }
- }
- }
- if (dd->tx_done && dd->rx_done) {
- msm_spi_set_state(dd, SPI_OP_STATE_RESET);
- dd->tx_done = false;
- dd->rx_done = false;
+ if (dd->done) {
complete(&dd->rx_transfer_complete);
complete(&dd->tx_transfer_complete);
+ dd->done = 0;
}
return ret;
}
@@ -987,23 +968,17 @@ static irqreturn_t msm_spi_input_irq(int irq, void *dev_id)
dd->stat_rx++;
- if (dd->rx_mode == SPI_MODE_NONE)
+ if (dd->mode == SPI_MODE_NONE)
return IRQ_HANDLED;
- if (dd->rx_mode == SPI_FIFO_MODE) {
+ if (dd->mode == SPI_FIFO_MODE) {
while ((readl_relaxed(dd->base + SPI_OPERATIONAL) &
SPI_OP_IP_FIFO_NOT_EMPTY) &&
(dd->rx_bytes_remaining > 0)) {
msm_spi_read_word_from_fifo(dd);
}
- } else if (dd->rx_mode == SPI_BLOCK_MODE) {
- int count = 0;
-
- while (dd->rx_bytes_remaining &&
- (count < dd->input_block_size)) {
- msm_spi_read_word_from_fifo(dd);
- count += SPI_MAX_BYTES_PER_WORD;
- }
+ if (dd->rx_bytes_remaining == 0)
+ msm_spi_complete(dd);
}
return IRQ_HANDLED;
@@ -1014,20 +989,18 @@ static void msm_spi_write_word_to_fifo(struct msm_spi *dd)
u32 word;
u8 byte;
int i;
- int write_bytes =
- (dd->pack_words ? SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word);
word = 0;
if (dd->write_buf) {
- for (i = 0; (i < write_bytes) &&
+ for (i = 0; (i < dd->bytes_per_word) &&
dd->tx_bytes_remaining; i++) {
dd->tx_bytes_remaining--;
byte = *dd->write_buf++;
word |= (byte << (BITS_PER_BYTE * i));
}
} else
- if (dd->tx_bytes_remaining > write_bytes)
- dd->tx_bytes_remaining -= write_bytes;
+ if (dd->tx_bytes_remaining > dd->bytes_per_word)
+ dd->tx_bytes_remaining -= dd->bytes_per_word;
else
dd->tx_bytes_remaining = 0;
dd->write_xfr_cnt++;
@@ -1039,22 +1012,11 @@ static inline void msm_spi_write_rmn_to_fifo(struct msm_spi *dd)
{
int count = 0;
- if (dd->tx_mode == SPI_FIFO_MODE) {
- while ((dd->tx_bytes_remaining > 0) &&
- (count < dd->input_fifo_size) &&
- !(readl_relaxed(dd->base + SPI_OPERATIONAL)
- & SPI_OP_OUTPUT_FIFO_FULL)) {
- msm_spi_write_word_to_fifo(dd);
- count++;
- }
- }
-
- if (dd->tx_mode == SPI_BLOCK_MODE) {
- while (dd->tx_bytes_remaining &&
- (count < dd->output_block_size)) {
- msm_spi_write_word_to_fifo(dd);
- count += SPI_MAX_BYTES_PER_WORD;
- }
+ while ((dd->tx_bytes_remaining > 0) && (count < dd->input_fifo_size) &&
+ !(readl_relaxed(dd->base + SPI_OPERATIONAL) &
+ SPI_OP_OUTPUT_FIFO_FULL)) {
+ msm_spi_write_word_to_fifo(dd);
+ count++;
}
}
@@ -1064,11 +1026,11 @@ static irqreturn_t msm_spi_output_irq(int irq, void *dev_id)
dd->stat_tx++;
- if (dd->tx_mode == SPI_MODE_NONE)
+ if (dd->mode == SPI_MODE_NONE)
return IRQ_HANDLED;
/* Output FIFO is empty. Transmit any outstanding write data. */
- if ((dd->tx_mode == SPI_FIFO_MODE) || (dd->tx_mode == SPI_BLOCK_MODE))
+ if (dd->mode == SPI_FIFO_MODE)
msm_spi_write_rmn_to_fifo(dd);
return IRQ_HANDLED;
@@ -1144,7 +1106,7 @@ error:
static int msm_spi_dma_map_buffers(struct msm_spi *dd)
{
int ret = 0;
- if (dd->tx_mode == SPI_BAM_MODE)
+ if (dd->mode == SPI_BAM_MODE)
ret = msm_spi_bam_map_buffers(dd);
return ret;
}
@@ -1173,7 +1135,7 @@ static void msm_spi_bam_unmap_buffers(struct msm_spi *dd)
static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd)
{
- if (dd->tx_mode == SPI_BAM_MODE)
+ if (dd->mode == SPI_BAM_MODE)
msm_spi_bam_unmap_buffers(dd);
}
@@ -1235,11 +1197,9 @@ static void
msm_spi_set_transfer_mode(struct msm_spi *dd, u8 bpw, u32 read_count)
{
if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) {
- dd->tx_mode = SPI_BAM_MODE;
- dd->rx_mode = SPI_BAM_MODE;
+ dd->mode = SPI_BAM_MODE;
} else {
- dd->rx_mode = SPI_FIFO_MODE;
- dd->tx_mode = SPI_FIFO_MODE;
+ dd->mode = SPI_FIFO_MODE;
dd->read_len = dd->cur_transfer->len;
dd->write_len = dd->cur_transfer->len;
}
@@ -1255,19 +1215,14 @@ static void msm_spi_set_qup_io_modes(struct msm_spi *dd)
spi_iom = readl_relaxed(dd->base + SPI_IO_MODES);
/* Set input and output transfer mode: FIFO, DMOV, or BAM */
spi_iom &= ~(SPI_IO_M_INPUT_MODE | SPI_IO_M_OUTPUT_MODE);
- spi_iom = (spi_iom | (dd->tx_mode << OUTPUT_MODE_SHIFT));
- spi_iom = (spi_iom | (dd->rx_mode << INPUT_MODE_SHIFT));
- /* Always enable packing for all % 8 bits_per_word */
- if (dd->cur_transfer->bits_per_word &&
- ((dd->cur_transfer->bits_per_word == 8) ||
- (dd->cur_transfer->bits_per_word == 16) ||
- (dd->cur_transfer->bits_per_word == 32))) {
+ spi_iom = (spi_iom | (dd->mode << OUTPUT_MODE_SHIFT));
+ spi_iom = (spi_iom | (dd->mode << INPUT_MODE_SHIFT));
+ /* Turn on packing for data mover */
+ if (dd->mode == SPI_BAM_MODE)
spi_iom |= SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN;
- dd->pack_words = true;
- } else {
+ else {
spi_iom &= ~(SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN);
spi_iom |= SPI_IO_M_OUTPUT_BIT_SHIFT_EN;
- dd->pack_words = false;
}
/*if (dd->mode == SPI_BAM_MODE) {
@@ -1325,7 +1280,7 @@ static void msm_spi_set_qup_op_mask(struct msm_spi *dd)
{
/* mask INPUT and OUTPUT service flags in to prevent IRQs on FIFO status
* change in BAM mode */
- u32 mask = (dd->tx_mode == SPI_BAM_MODE) ?
+ u32 mask = (dd->mode == SPI_BAM_MODE) ?
QUP_OP_MASK_OUTPUT_SERVICE_FLAG | QUP_OP_MASK_INPUT_SERVICE_FLAG
: 0;
writel_relaxed(mask, dd->base + QUP_OPERATIONAL_MASK);
@@ -1366,8 +1321,6 @@ static int msm_spi_process_transfer(struct msm_spi *dd)
dd->rx_bytes_remaining = dd->cur_msg_len;
dd->read_buf = dd->cur_transfer->rx_buf;
dd->write_buf = dd->cur_transfer->tx_buf;
- dd->tx_done = false;
- dd->rx_done = false;
init_completion(&dd->tx_transfer_complete);
init_completion(&dd->rx_transfer_complete);
if (dd->cur_transfer->bits_per_word)
@@ -1398,12 +1351,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd)
msm_spi_set_transfer_mode(dd, bpw, read_count);
msm_spi_set_mx_counts(dd, read_count);
- if (dd->tx_mode == SPI_BAM_MODE) {
+ if (dd->mode == SPI_BAM_MODE) {
ret = msm_spi_dma_map_buffers(dd);
if (ret < 0) {
pr_err("Mapping DMA buffers\n");
- dd->tx_mode = SPI_MODE_NONE;
- dd->rx_mode = SPI_MODE_NONE;
return ret;
}
}
@@ -1417,11 +1368,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd)
the first. Restricting this to one write avoids contention
issues and race conditions between this thread and the int handler
*/
- if (dd->tx_mode != SPI_BAM_MODE) {
+ if (dd->mode == SPI_FIFO_MODE) {
if (msm_spi_prepare_for_write(dd))
goto transfer_end;
msm_spi_start_write(dd, read_count);
- } else {
+ } else if (dd->mode == SPI_BAM_MODE) {
if ((msm_spi_bam_begin_transfer(dd)) < 0) {
dev_err(dd->dev, "%s: BAM transfer setup failed\n",
__func__);
@@ -1437,11 +1388,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd)
* might fire before the first word is written resulting in a
* possible race condition.
*/
- if (dd->tx_mode != SPI_BAM_MODE)
+ if (dd->mode != SPI_BAM_MODE)
if (msm_spi_set_state(dd, SPI_OP_STATE_RUN)) {
dev_warn(dd->dev,
"%s: Failed to set QUP to run-state. Mode:%d",
- __func__, dd->tx_mode);
+ __func__, dd->mode);
goto transfer_end;
}
@@ -1471,11 +1422,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd)
msm_spi_udelay(dd->xfrs_delay_usec);
transfer_end:
- if ((dd->tx_mode == SPI_BAM_MODE) && status)
+ if ((dd->mode == SPI_BAM_MODE) && status)
msm_spi_bam_flush(dd);
msm_spi_dma_unmap_buffers(dd);
- dd->tx_mode = SPI_MODE_NONE;
- dd->rx_mode = SPI_MODE_NONE;
+ dd->mode = SPI_MODE_NONE;
msm_spi_set_state(dd, SPI_OP_STATE_RESET);
if (!dd->cur_transfer->cs_change)
@@ -2403,8 +2353,7 @@ static int init_resources(struct platform_device *pdev)
pclk_enabled = 0;
dd->transfer_pending = 0;
- dd->tx_mode = SPI_MODE_NONE;
- dd->rx_mode = SPI_MODE_NONE;
+ dd->mode = SPI_MODE_NONE;
rc = msm_spi_request_irq(dd, pdev, master);
if (rc)
diff --git a/drivers/spi/spi_qsd.h b/drivers/spi/spi_qsd.h
index e8e6cdce1a02..53ec1e600594 100644
--- a/drivers/spi/spi_qsd.h
+++ b/drivers/spi/spi_qsd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -113,8 +113,6 @@
#define INPUT_MODE_SHIFT QSD_REG(10) QUP_REG(12)
/* SPI_OPERATIONAL fields */
-#define SPI_OP_IN_BLK_RD_REQ_FLAG 0x00002000
-#define SPI_OP_OUT_BLK_WR_REQ_FLAG 0x00001000
#define SPI_OP_MAX_INPUT_DONE_FLAG 0x00000800
#define SPI_OP_MAX_OUTPUT_DONE_FLAG 0x00000400
#define SPI_OP_INPUT_SERVICE_FLAG 0x00000200
@@ -316,8 +314,7 @@ struct msm_spi {
bool transfer_pending;
wait_queue_head_t continue_suspend;
/* DMA data */
- enum msm_spi_mode tx_mode;
- enum msm_spi_mode rx_mode;
+ enum msm_spi_mode mode;
bool use_dma;
int tx_dma_chan;
int tx_dma_crci;
@@ -349,8 +346,7 @@ struct msm_spi {
#endif
struct msm_spi_platform_data *pdata; /* Platform data */
/* When set indicates multiple transfers in a single message */
- bool rx_done;
- bool tx_done;
+ bool done;
u32 cur_msg_len;
/* Used in FIFO mode to keep track of the transfer being processed */
struct spi_transfer *cur_tx_transfer;
@@ -368,7 +364,6 @@ struct msm_spi {
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_sleep;
bool is_init_complete;
- bool pack_words;
};
/* Forward declaration */
@@ -522,8 +517,7 @@ static inline void msm_spi_set_write_count(struct msm_spi *dd, int val)
static inline void msm_spi_complete(struct msm_spi *dd)
{
- dd->tx_done = true;
- dd->rx_done = true;
+ dd->done = 1;
}
static inline void msm_spi_enable_error_flags(struct msm_spi *dd)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index bc0e0184a917..1e252febc783 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -156,6 +156,7 @@ struct dwc3_msm {
struct clk *xo_clk;
struct clk *core_clk;
long core_clk_rate;
+ long core_clk_rate_hs;
struct clk *iface_clk;
struct clk *sleep_clk;
struct clk *utmi_clk;
@@ -195,6 +196,7 @@ struct dwc3_msm {
struct power_supply *usb_psy;
struct work_struct vbus_draw_work;
bool in_host_mode;
+ enum usb_device_speed max_rh_port_speed;
unsigned int tx_fifo_size;
bool vbus_active;
bool suspend;
@@ -342,6 +344,23 @@ static inline void dwc3_msm_write_readback(void *base, u32 offset,
__func__, val, offset);
}
+static bool dwc3_msm_is_ss_rhport_connected(struct dwc3_msm *mdwc)
+{
+ int i, num_ports;
+ u32 reg;
+
+ reg = dwc3_msm_read_reg(mdwc->base, USB3_HCSPARAMS1);
+ num_ports = HCS_MAX_PORTS(reg);
+
+ for (i = 0; i < num_ports; i++) {
+ reg = dwc3_msm_read_reg(mdwc->base, USB3_PORTSC + i*0x10);
+ if ((reg & PORT_CONNECT) && DEV_SUPERSPEED(reg))
+ return true;
+ }
+
+ return false;
+}
+
static bool dwc3_msm_is_host_superspeed(struct dwc3_msm *mdwc)
{
int i, num_ports;
@@ -2128,6 +2147,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
static int dwc3_msm_resume(struct dwc3_msm *mdwc)
{
int ret;
+ long core_clk_rate;
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
@@ -2175,7 +2195,15 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
clk_prepare_enable(mdwc->iface_clk);
if (mdwc->noc_aggr_clk)
clk_prepare_enable(mdwc->noc_aggr_clk);
- clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate);
+
+ core_clk_rate = mdwc->core_clk_rate;
+ if (mdwc->in_host_mode && mdwc->max_rh_port_speed == USB_SPEED_HIGH) {
+ core_clk_rate = mdwc->core_clk_rate_hs;
+ dev_dbg(mdwc->dev, "%s: set hs core clk rate %ld\n", __func__,
+ core_clk_rate);
+ }
+
+ clk_set_rate(mdwc->core_clk, core_clk_rate);
clk_prepare_enable(mdwc->core_clk);
/* set Memory core: ON, Memory periphery: ON */
@@ -2496,6 +2524,11 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
if (ret)
dev_err(mdwc->dev, "fail to set core_clk freq:%d\n", ret);
+ if (of_property_read_u32(mdwc->dev->of_node, "qcom,core-clk-rate-hs",
+ (u32 *)&mdwc->core_clk_rate_hs)) {
+ dev_dbg(mdwc->dev, "USB core-clk-rate-hs is not present\n");
+ mdwc->core_clk_rate_hs = mdwc->core_clk_rate;
+ }
mdwc->core_reset = devm_reset_control_get(mdwc->dev, "core_reset");
if (IS_ERR(mdwc->core_reset)) {
@@ -2723,6 +2756,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node, *dwc3_node;
struct device *dev = &pdev->dev;
+ union power_supply_propval pval = {0};
struct dwc3_msm *mdwc;
struct dwc3 *dwc;
struct resource *res;
@@ -3016,10 +3050,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
*/
mdwc->lpm_flags = MDWC3_POWER_COLLAPSE | MDWC3_SS_PHY_SUSPEND;
atomic_set(&dwc->in_lpm, 1);
- pm_runtime_set_suspended(mdwc->dev);
pm_runtime_set_autosuspend_delay(mdwc->dev, 1000);
pm_runtime_use_autosuspend(mdwc->dev);
- pm_runtime_enable(mdwc->dev);
device_init_wakeup(mdwc->dev, 1);
if (of_property_read_bool(node, "qcom,disable-dev-mode-pm"))
@@ -3036,18 +3068,32 @@ static int dwc3_msm_probe(struct platform_device *pdev)
mdwc->pm_qos_latency = 0;
}
+ mdwc->usb_psy = power_supply_get_by_name("usb");
+ if (!mdwc->usb_psy) {
+ dev_warn(mdwc->dev, "Could not get usb power_supply\n");
+ pval.intval = -EINVAL;
+ } else {
+ power_supply_get_property(mdwc->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ }
+
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))
dwc3_msm_vbus_notifier(&mdwc->vbus_nb, true, mdwc->extcon_vbus);
- if (mdwc->extcon_id && extcon_get_cable_state_(mdwc->extcon_id,
+ else if (mdwc->extcon_id && extcon_get_cable_state_(mdwc->extcon_id,
EXTCON_USB_HOST))
dwc3_msm_id_notifier(&mdwc->id_nb, true, mdwc->extcon_id);
+ else if (!pval.intval) {
+ /* USB cable is not connected */
+ schedule_delayed_work(&mdwc->sm_work, 0);
+ } else {
+ if (pval.intval > 0)
+ dev_info(mdwc->dev, "charger detection in progress\n");
+ }
device_create_file(&pdev->dev, &dev_attr_mode);
- schedule_delayed_work(&mdwc->sm_work, 0);
-
host_mode = usb_get_dr_mode(&mdwc->dwc3->dev) == USB_DR_MODE_HOST;
if (!dwc->is_drd && host_mode) {
dev_dbg(&pdev->dev, "DWC3 in host only mode\n");
@@ -3166,10 +3212,26 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb,
if (udev->parent && !udev->parent->parent &&
udev->dev.parent->parent == &dwc->xhci->dev) {
if (event == USB_DEVICE_ADD && udev->actconfig) {
+ if (!dwc3_msm_is_ss_rhport_connected(mdwc)) {
+ /*
+ * Core clock rate can be reduced only if root
+ * hub SS port is not enabled/connected.
+ */
+ clk_set_rate(mdwc->core_clk,
+ mdwc->core_clk_rate_hs);
+ dev_dbg(mdwc->dev,
+ "set hs core clk rate %ld\n",
+ mdwc->core_clk_rate_hs);
+ mdwc->max_rh_port_speed = USB_SPEED_HIGH;
+ } else {
+ mdwc->max_rh_port_speed = USB_SPEED_SUPER;
+ }
+
if (udev->speed >= USB_SPEED_SUPER)
max_power = udev->actconfig->desc.bMaxPower * 8;
else
max_power = udev->actconfig->desc.bMaxPower * 2;
+
dev_dbg(mdwc->dev, "%s configured bMaxPower:%d (mA)\n",
dev_name(&udev->dev), max_power);
@@ -3181,6 +3243,7 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb,
pval.intval = 0;
power_supply_set_property(mdwc->usb_psy,
POWER_SUPPLY_PROP_BOOST_CURRENT, &pval);
+ mdwc->max_rh_port_speed = USB_SPEED_UNKNOWN;
}
}
@@ -3538,13 +3601,25 @@ static void dwc3_otg_sm_work(struct work_struct *w)
/* Check OTG state */
switch (mdwc->otg_state) {
case OTG_STATE_UNDEFINED:
- /* Do nothing if no cable connected */
+ /* put controller and phy in suspend if no cable connected */
if (test_bit(ID, &mdwc->inputs) &&
- !test_bit(B_SESS_VLD, &mdwc->inputs))
+ !test_bit(B_SESS_VLD, &mdwc->inputs)) {
+ dbg_event(0xFF, "undef_id_!bsv", 0);
+ pm_runtime_set_active(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
+ pm_runtime_get_noresume(mdwc->dev);
+ dwc3_msm_resume(mdwc);
+ pm_runtime_put_sync(mdwc->dev);
+ dbg_event(0xFF, "Undef NoUSB",
+ atomic_read(&mdwc->dev->power.usage_count));
+ mdwc->otg_state = OTG_STATE_B_IDLE;
break;
+ }
dbg_event(0xFF, "Exit UNDEF", 0);
mdwc->otg_state = OTG_STATE_B_IDLE;
+ pm_runtime_set_suspended(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
/* fall-through */
case OTG_STATE_B_IDLE:
if (!test_bit(ID, &mdwc->inputs)) {
diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c
index fe428e8bb781..da02ad557d34 100644
--- a/drivers/usb/gadget/function/f_diag.c
+++ b/drivers/usb/gadget/function/f_diag.c
@@ -352,9 +352,11 @@ struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
ch->priv = priv;
ch->notify = notify;
- spin_lock_irqsave(&ch_lock, flags);
- list_add_tail(&ch->list, &usb_diag_ch_list);
- spin_unlock_irqrestore(&ch_lock, flags);
+ if (!found) {
+ spin_lock_irqsave(&ch_lock, flags);
+ list_add_tail(&ch->list, &usb_diag_ch_list);
+ spin_unlock_irqrestore(&ch_lock, flags);
+ }
return ch;
}
@@ -828,6 +830,7 @@ static struct diag_context *diag_context_init(const char *name)
struct diag_context *dev;
struct usb_diag_ch *_ch;
int found = 0;
+ unsigned long flags;
pr_debug("%s\n", __func__);
@@ -837,9 +840,19 @@ static struct diag_context *diag_context_init(const char *name)
break;
}
}
+
if (!found) {
- pr_err("%s: unable to get diag usb channel\n", __func__);
- return ERR_PTR(-ENODEV);
+ pr_warn("%s: unable to get diag usb channel\n", __func__);
+
+ _ch = kzalloc(sizeof(*_ch), GFP_KERNEL);
+ if (_ch == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ _ch->name = name;
+
+ spin_lock_irqsave(&ch_lock, flags);
+ list_add_tail(&_ch->list, &usb_diag_ch_list);
+ spin_unlock_irqrestore(&ch_lock, flags);
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index f3715d85aedc..97d86b6ac69b 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -454,13 +454,23 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
struct fsg_buffhd *bh = req->context;
if (req->status || req->actual != req->length)
- DBG(common, "%s --> %d, %u/%u\n", __func__,
+ pr_debug("%s --> %d, %u/%u\n", __func__,
req->status, req->actual, req->length);
if (req->status == -ECONNRESET) /* Request was cancelled */
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
smp_wmb();
+ /*
+ * Disconnect and completion might race each other and driver data
+ * is set to NULL during ep disable. So, add a check if that is case.
+ */
+ if (!common) {
+ bh->inreq_busy = 0;
+ bh->state = BUF_STATE_EMPTY;
+ return;
+ }
+
spin_lock(&common->lock);
bh->inreq_busy = 0;
bh->state = BUF_STATE_EMPTY;
@@ -473,15 +483,24 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
struct fsg_common *common = ep->driver_data;
struct fsg_buffhd *bh = req->context;
- dump_msg(common, "bulk-out", req->buf, req->actual);
if (req->status || req->actual != bh->bulk_out_intended_length)
- DBG(common, "%s --> %d, %u/%u\n", __func__,
+ pr_debug("%s --> %d, %u/%u\n", __func__,
req->status, req->actual, bh->bulk_out_intended_length);
if (req->status == -ECONNRESET) /* Request was cancelled */
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
smp_wmb();
+ /*
+ * Disconnect and completion might race each other and driver data
+ * is set to NULL during ep disable. So, add a check if that is case.
+ */
+ if (!common) {
+ bh->outreq_busy = 0;
+ return;
+ }
+
+ dump_msg(common, "bulk-out", req->buf, req->actual);
spin_lock(&common->lock);
bh->outreq_busy = 0;
bh->state = BUF_STATE_FULL;
@@ -2471,8 +2490,14 @@ static void handle_exception(struct fsg_common *common)
case FSG_STATE_CONFIG_CHANGE:
do_set_interface(common, common->new_fsg);
- if (common->new_fsg)
+ if (common->new_fsg) {
+ /*
+ * make sure delayed_status flag updated when set_alt
+ * returned.
+ */
+ msleep(200);
usb_composite_setup_continue(common->cdev);
+ }
break;
case FSG_STATE_EXIT:
diff --git a/drivers/usb/gadget/function/f_qc_rndis.c b/drivers/usb/gadget/function/f_qc_rndis.c
index 11c73f584594..061095b78c37 100644
--- a/drivers/usb/gadget/function/f_qc_rndis.c
+++ b/drivers/usb/gadget/function/f_qc_rndis.c
@@ -683,6 +683,7 @@ static int rndis_qc_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0 */
+ opts = container_of(f->fi, struct f_rndis_qc_opts, func_inst);
if (intf == rndis->ctrl_id) {
if (rndis->notify->driver_data) {
VDBG(cdev, "reset rndis control %d\n", intf);
diff --git a/drivers/usb/gadget/function/u_ctrl_qti.c b/drivers/usb/gadget/function/u_ctrl_qti.c
index 8ef223370827..013c54da0d0a 100644
--- a/drivers/usb/gadget/function/u_ctrl_qti.c
+++ b/drivers/usb/gadget/function/u_ctrl_qti.c
@@ -485,7 +485,7 @@ qti_ctrl_write(struct file *fp, const char __user *buf, size_t count,
port->copied_from_modem++;
spin_lock_irqsave(&port->lock, flags);
- if (port && port->port_usb) {
+ if (port->port_usb) {
if (port->port_type == QTI_PORT_RMNET) {
g_rmnet = (struct grmnet *)port->port_usb;
} else {
diff --git a/drivers/usb/gadget/function/u_data_ipa.c b/drivers/usb/gadget/function/u_data_ipa.c
index bf9e0fa9950b..6c18a04f6c1c 100644
--- a/drivers/usb/gadget/function/u_data_ipa.c
+++ b/drivers/usb/gadget/function/u_data_ipa.c
@@ -1107,18 +1107,18 @@ static void bam2bam_data_resume_work(struct work_struct *w)
unsigned long flags;
int ret;
- if (!port->port_usb->cdev) {
- pr_err("!port->port_usb->cdev is NULL");
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (!port->port_usb || !port->port_usb->cdev) {
+ pr_err("port->port_usb or cdev is NULL");
goto exit;
}
if (!port->port_usb->cdev->gadget) {
- pr_err("!port->port_usb->cdev->gadget is NULL");
+ pr_err("port->port_usb->cdev->gadget is NULL");
goto exit;
}
pr_debug("%s: resume started\n", __func__);
- spin_lock_irqsave(&port->port_lock, flags);
gadget = port->port_usb->cdev->gadget;
if (!gadget) {
spin_unlock_irqrestore(&port->port_lock, flags);
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index f3e17b84efff..f1360f20ffe4 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2017, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 0cdf91da920c..06e4812a8bd4 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -281,7 +281,7 @@ struct mdss_data_type {
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
struct regulator *fs;
- struct regulator *venus;
+ struct regulator *core_gdsc;
struct regulator *vdd_cx;
u32 vdd_cx_min_uv;
u32 vdd_cx_max_uv;
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index f499cdfd85ef..14d998d14eeb 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
* Copyright (C) 1994 Martin Schaller
*
* 2001 - Documented with DocBook
@@ -938,6 +938,7 @@ static int __to_user_pcc_coeff_v1_7(
struct mdp_pcc_data_v1_7_32 pcc_cfg_payload32;
struct mdp_pcc_data_v1_7 pcc_cfg_payload;
+ memset(&pcc_cfg_payload32, 0, sizeof(pcc_cfg_payload32));
if (copy_from_user(&pcc_cfg_payload,
pcc_cfg->cfg_payload,
sizeof(struct mdp_pcc_data_v1_7))) {
@@ -2133,6 +2134,7 @@ static int __to_user_pa_data_v1_7(
struct mdp_pa_data_v1_7_32 pa_cfg_payload32;
struct mdp_pa_data_v1_7 pa_cfg_payload;
+ memset(&pa_cfg_payload32, 0, sizeof(pa_cfg_payload32));
if (copy_from_user(&pa_cfg_payload,
pa_v2_cfg->cfg_payload,
sizeof(pa_cfg_payload))) {
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index ccf8a0d34a6c..f3c36c5c6b5a 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,9 +56,58 @@ struct mdss_dp_attention_node {
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv);
static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata);
-static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp);
+static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp,
+ bool lt_needed);
static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv);
static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 events);
+static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
+ enum notification_status status);
+static int mdss_dp_process_phy_test_pattern_request(
+ struct mdss_dp_drv_pdata *dp);
+
+static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
+{
+ dp->test_data = (const struct dpcd_test_request){ 0 };
+ dp->test_data.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
+ hdmi_edid_config_override(dp->panel_data.panel_info.edid_data,
+ false, 0);
+}
+
+static inline bool mdss_dp_is_link_status_updated(struct mdss_dp_drv_pdata *dp)
+{
+ return dp->link_status.link_status_updated;
+}
+
+static inline bool mdss_dp_is_downstream_port_status_changed(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return dp->link_status.downstream_port_status_changed;
+}
+
+static inline bool mdss_dp_is_audio_pattern_requested(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return (dp->test_data.test_requested & TEST_AUDIO_PATTERN);
+}
+
+static inline bool mdss_dp_is_link_training_requested(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return (dp->test_data.test_requested == TEST_LINK_TRAINING);
+}
+
+static inline bool mdss_dp_is_video_pattern_requested(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return (dp->test_data.test_requested & TEST_VIDEO_PATTERN)
+ && !(dp->test_data.test_requested & TEST_AUDIO_DISABLED_VIDEO);
+}
+
+static inline bool mdss_dp_is_phy_test_pattern_requested(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return (dp->test_data.test_requested == PHY_TEST_PATTERN);
+}
static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power)
@@ -798,9 +847,11 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
{
struct dpcd_cap *cap;
struct display_timing_desc *timing;
+ struct mdss_panel_info *pinfo;
u32 data = 0;
timing = &dp->edid.timing[0];
+ pinfo = &dp->panel_data.panel_info;
cap = &dp->dpcd;
@@ -823,8 +874,8 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
if (cap->scrambler_reset)
data |= (1 << 10);
- if (dp->edid.color_depth != 6)
- data |= 0x100; /* Default: 8 bits */
+ /* Bits per components */
+ data |= (mdss_dp_bpp_to_test_bit_depth(pinfo->bpp) << 8);
/* Num of Lanes */
data |= ((dp->lane_cnt - 1) << 4);
@@ -840,7 +891,7 @@ void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *dp)
mdss_dp_configuration_ctrl(&dp->ctrl_io, data);
}
-int mdss_dp_wait4train(struct mdss_dp_drv_pdata *dp_drv)
+static int mdss_dp_wait4video_ready(struct mdss_dp_drv_pdata *dp_drv)
{
int ret = 0;
@@ -882,9 +933,7 @@ static int dp_get_cable_status(struct platform_device *pdev, u32 vote)
return -ENODEV;
}
- mutex_lock(&dp_ctrl->pd_msg_mutex);
hpd = dp_ctrl->cable_connected;
- mutex_unlock(&dp_ctrl->pd_msg_mutex);
return hpd;
}
@@ -905,7 +954,7 @@ static int dp_audio_info_setup(struct platform_device *pdev,
return -ENODEV;
}
- mdss_dp_audio_setup_sdps(&dp_ctrl->ctrl_io);
+ mdss_dp_audio_setup_sdps(&dp_ctrl->ctrl_io, params->num_of_channels);
mdss_dp_config_audio_acr_ctrl(&dp_ctrl->ctrl_io, dp_ctrl->link_rate);
mdss_dp_set_safe_to_exit_level(&dp_ctrl->ctrl_io, dp_ctrl->lane_cnt);
mdss_dp_audio_enable(&dp_ctrl->ctrl_io, true);
@@ -983,6 +1032,55 @@ end:
return ret;
}
+static u32 mdss_dp_get_bpp(struct mdss_dp_drv_pdata *dp)
+{
+ u32 bpp;
+ u32 bit_depth;
+
+ /*
+ * Set bpp value based on whether a test video pattern is requested.
+ * For test pattern, the test data has the bit depth per color
+ * component. Otherwise, set it based on EDID.
+ */
+ if (dp->override_config || mdss_dp_is_video_pattern_requested(dp))
+ bit_depth = dp->test_data.test_bit_depth;
+ else
+ bit_depth = dp->edid.color_depth;
+
+ if (!mdss_dp_is_test_bit_depth_valid(bit_depth)) {
+ pr_debug("invalid bit_depth=%d. fall back to default\n",
+ bit_depth);
+ bit_depth = DP_TEST_BIT_DEPTH_8; /* default to 24bpp */
+ }
+
+ bpp = mdss_dp_test_bit_depth_to_bpp(bit_depth);
+ return bpp;
+}
+
+static u32 mdss_dp_get_colorimetry_config(struct mdss_dp_drv_pdata *dp)
+{
+ u32 cc;
+ enum dynamic_range dr;
+
+ /* unless a video pattern CTS test is ongoing, use CEA_VESA */
+ if (mdss_dp_is_video_pattern_requested(dp))
+ dr = dp->test_data.test_dyn_range;
+ else
+ dr = DP_DYNAMIC_RANGE_RGB_VESA;
+
+ /* Only RGB_VESA nd RGB_CEA supported for now */
+ switch (dr) {
+ case DP_DYNAMIC_RANGE_RGB_CEA:
+ cc = BIT(3);
+ break;
+ case DP_DYNAMIC_RANGE_RGB_VESA:
+ default:
+ cc = 0;
+ }
+
+ return cc;
+}
+
static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
{
struct mdss_panel_info *pinfo;
@@ -993,13 +1091,17 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
DEV_ERR("invalid input\n");
return -EINVAL;
}
-
- ret = hdmi_get_supported_mode(&timing, 0, vic);
pinfo = &dp_drv->panel_data.panel_info;
- if (ret || !timing.supported || !pinfo) {
- DEV_ERR("%s: invalid timing data\n", __func__);
- return -EINVAL;
+ if (vic != HDMI_VFRMT_UNKNOWN) {
+ ret = hdmi_get_supported_mode(&timing, 0, vic);
+
+ if (ret || !timing.supported || !pinfo) {
+ DEV_ERR("%s: invalid timing data\n", __func__);
+ return -EINVAL;
+ }
+ } else {
+ pr_debug("reset panel info to zeroes\n");
}
dp_drv->vic = vic;
@@ -1010,14 +1112,15 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
pinfo->lcdc.h_back_porch = timing.back_porch_h;
pinfo->lcdc.h_front_porch = timing.front_porch_h;
pinfo->lcdc.h_pulse_width = timing.pulse_width_h;
+ pinfo->lcdc.h_active_low = timing.active_low_h;
pinfo->lcdc.v_back_porch = timing.back_porch_v;
pinfo->lcdc.v_front_porch = timing.front_porch_v;
pinfo->lcdc.v_pulse_width = timing.pulse_width_v;
+ pinfo->lcdc.v_active_low = timing.active_low_v;
pinfo->type = DP_PANEL;
pinfo->pdest = DISPLAY_4;
pinfo->wait_cycle = 0;
- pinfo->bpp = 24;
pinfo->fb_num = 1;
pinfo->lcdc.border_clr = 0; /* blk */
@@ -1025,8 +1128,8 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
pinfo->lcdc.hsync_skew = 0;
pinfo->is_pluggable = true;
- dp_drv->bpp = pinfo->bpp;
-
+ pinfo->bpp = mdss_dp_get_bpp(dp_drv);
+ pr_debug("bpp=%d\n", pinfo->bpp);
pr_debug("update res. vic= %d, pclk_rate = %llu\n",
dp_drv->vic, pinfo->clk_rate);
@@ -1151,13 +1254,17 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
mdss_dp_fill_link_cfg(dp);
mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
mdss_dp_config_ctrl(dp);
+ mdss_dp_config_misc(dp,
+ mdss_dp_bpp_to_test_bit_depth(mdss_dp_get_bpp(dp)),
+ mdss_dp_get_colorimetry_config(dp));
mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io);
mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info);
}
/**
- * mdss_dp_train_main_link() - initiates training of DP main link
+ * mdss_dp_setup_main_link() - initiates training of DP main link
* @dp: Display Port Driver data
+ * @train: specify if link training should be done or not
*
* Initiates training of the DP main link and checks the state of the main
* link after the training is complete.
@@ -1165,64 +1272,90 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
* Return: error code. -EINVAL if any invalid data or -EAGAIN if retraining
* is required.
*/
-static int mdss_dp_train_main_link(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_setup_main_link(struct mdss_dp_drv_pdata *dp, bool train)
{
int ret = 0;
int ready = 0;
pr_debug("enter\n");
+ mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
+ mdss_dp_aux_set_sink_power_state(dp, SINK_POWER_ON);
+ reinit_completion(&dp->video_comp);
+
+ if (mdss_dp_is_phy_test_pattern_requested(dp))
+ goto end;
+
+ if (!train)
+ goto send_video;
+
+ /*
+ * As part of previous calls, DP controller state might have
+ * transitioned to PUSH_IDLE. In order to start transmitting a link
+ * training pattern, we have to first to a DP software reset.
+ */
+ mdss_dp_ctrl_reset(&dp->ctrl_io);
ret = mdss_dp_link_train(dp);
if (ret)
goto end;
- mdss_dp_wait4train(dp);
+send_video:
+ /*
+ * Set up transfer unit values and set controller state to send
+ * video.
+ */
+ mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate, dp->lane_cnt,
+ dp->vic, &dp->panel_data.panel_info);
+ mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
+ mdss_dp_wait4video_ready(dp);
ready = mdss_dp_mainlink_ready(dp, BIT(0));
-
pr_debug("main link %s\n", ready ? "READY" : "NOT READY");
+
end:
return ret;
}
-static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
+static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed)
{
int ret = 0;
struct lane_mapping ln_map;
/* wait until link training is completed */
- pr_debug("enter\n");
+ pr_debug("enter, lt_needed=%s\n", lt_needed ? "true" : "false");
do {
- if (ret == -EAGAIN) {
- mdss_dp_mainlink_push_idle(&dp_drv->panel_data);
- mdss_dp_off_irq(dp_drv);
- }
+ if (ret == -EAGAIN)
+ mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
mutex_lock(&dp_drv->train_mutex);
+ dp_init_panel_info(dp_drv, dp_drv->vic);
ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation,
&ln_map);
- if (ret) {
- mutex_unlock(&dp_drv->train_mutex);
- goto exit;
- }
+ if (ret)
+ goto exit_loop;
mdss_dp_phy_share_lane_config(&dp_drv->phy_io,
dp_drv->orientation,
dp_drv->dpcd.max_lane_count);
- ret = mdss_dp_enable_mainlink_clocks(dp_drv);
- if (ret) {
- mutex_unlock(&dp_drv->train_mutex);
- goto exit;
+ if (lt_needed) {
+ /*
+ * Diasable and re-enable the mainlink clock since the
+ * link clock might have been adjusted as part of the
+ * link maintenance.
+ */
+ if (!mdss_dp_is_phy_test_pattern_requested(dp_drv))
+ mdss_dp_disable_mainlink_clocks(dp_drv);
+ ret = mdss_dp_enable_mainlink_clocks(dp_drv);
+ if (ret)
+ goto exit_loop;
}
- mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
+ mdss_dp_configure_source_params(dp_drv, &ln_map);
reinit_completion(&dp_drv->idle_comp);
- mdss_dp_configure_source_params(dp_drv, &ln_map);
-
dp_drv->power_on = true;
if (dp_drv->psm_enabled) {
@@ -1230,18 +1363,22 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
if (ret) {
pr_err("Failed to exit low power mode, rc=%d\n",
ret);
- goto exit;
+ goto exit_loop;
}
}
- ret = mdss_dp_train_main_link(dp_drv);
+ ret = mdss_dp_setup_main_link(dp_drv, lt_needed);
+exit_loop:
mutex_unlock(&dp_drv->train_mutex);
} while (ret == -EAGAIN);
pr_debug("end\n");
-exit:
+ /* Send a connect notification */
+ if (!mdss_dp_is_phy_test_pattern_requested(dp_drv))
+ mdss_dp_notify_clients(dp_drv, NOTIFY_CONNECT_IRQ_HPD);
+
return ret;
}
@@ -1274,12 +1411,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv)
if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
dp_init_panel_info(dp_drv, dp_drv->new_vic);
- dp_drv->link_rate =
- mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info,
- dp_drv->dpcd.max_lane_count);
-
- pr_debug("link_rate=0x%x, Max rate supported by sink=0x%x\n",
- dp_drv->link_rate, dp_drv->dpcd.max_link_rate);
+ dp_drv->link_rate = mdss_dp_gen_link_clk(dp_drv);
if (!dp_drv->link_rate) {
pr_err("Unable to configure required link rate\n");
ret = -EINVAL;
@@ -1289,14 +1421,10 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_phy_share_lane_config(&dp_drv->phy_io, dp_drv->orientation,
dp_drv->dpcd.max_lane_count);
- pr_debug("link_rate = 0x%x\n", dp_drv->link_rate);
-
ret = mdss_dp_enable_mainlink_clocks(dp_drv);
if (ret)
goto exit;
- mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
-
reinit_completion(&dp_drv->idle_comp);
mdss_dp_configure_source_params(dp_drv, &ln_map);
@@ -1313,7 +1441,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv)
link_training:
dp_drv->power_on = true;
- while (-EAGAIN == mdss_dp_train_main_link(dp_drv))
+ while (-EAGAIN == mdss_dp_setup_main_link(dp_drv, true))
pr_debug("MAIN LINK TRAINING RETRY\n");
dp_drv->cont_splash = 0;
@@ -1338,42 +1466,12 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
panel_data);
- return mdss_dp_on_hpd(dp_drv);
-}
-
-static inline void mdss_dp_reset_test_data(struct mdss_dp_drv_pdata *dp)
-{
- dp->test_data = (const struct dpcd_test_request){ 0 };
-}
-
-static inline bool mdss_dp_is_link_status_updated(struct mdss_dp_drv_pdata *dp)
-{
- return dp->link_status.link_status_updated;
-}
-
-static inline bool mdss_dp_is_downstream_port_status_changed(
- struct mdss_dp_drv_pdata *dp)
-{
- return dp->link_status.downstream_port_status_changed;
-}
-
-static inline bool mdss_dp_is_link_training_requested(
- struct mdss_dp_drv_pdata *dp)
-{
- return (dp->test_data.test_requested == TEST_LINK_TRAINING);
-}
-
-static inline bool mdss_dp_is_phy_test_pattern_requested(
- struct mdss_dp_drv_pdata *dp)
-{
- return (dp->test_data.test_requested == PHY_TEST_PATTERN);
-}
+ if (dp_drv->power_on) {
+ pr_debug("Link already setup, return\n");
+ return 0;
+ }
-static inline bool mdss_dp_soft_hpd_reset(struct mdss_dp_drv_pdata *dp)
-{
- return (mdss_dp_is_link_training_requested(dp) ||
- mdss_dp_is_phy_test_pattern_requested(dp)) &&
- dp->alt_mode.dp_status.hpd_irq;
+ return mdss_dp_on_hpd(dp_drv);
}
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv)
@@ -1389,16 +1487,13 @@ static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv)
pr_debug("start\n");
mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
-
mdss_dp_audio_enable(&dp_drv->ctrl_io, false);
-
- /* Make sure the DP main link is disabled before clk disable */
+ /* Make sure DP mainlink and audio engines are disabled */
wmb();
- mdss_dp_disable_mainlink_clocks(dp_drv);
- dp_drv->power_on = false;
- dp_drv->sink_info_read = false;
+ mdss_dp_ack_state(dp_drv, false);
mutex_unlock(&dp_drv->train_mutex);
+
complete_all(&dp_drv->irq_comp);
pr_debug("end\n");
@@ -1445,8 +1540,10 @@ static int mdss_dp_off_hpd(struct mdss_dp_drv_pdata *dp_drv)
dp_drv->power_on = false;
dp_drv->sink_info_read = false;
+ dp_init_panel_info(dp_drv, HDMI_VFRMT_UNKNOWN);
mdss_dp_ack_state(dp_drv, false);
+ mdss_dp_reset_test_data(dp_drv);
mutex_unlock(&dp_drv->train_mutex);
pr_debug("DP off done\n");
@@ -1464,7 +1561,7 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return -EINVAL;
}
- if (mdss_dp_soft_hpd_reset(dp))
+ if (dp->hpd_irq_on)
return mdss_dp_off_irq(dp);
else
return mdss_dp_off_hpd(dp);
@@ -1482,8 +1579,13 @@ static int mdss_dp_send_cable_notification(
goto end;
}
- if (mdss_dp_is_dvi_mode(dp))
- flags |= MSM_EXT_DISP_HPD_NO_AUDIO;
+ flags |= MSM_EXT_DISP_HPD_VIDEO;
+
+ if (!mdss_dp_is_dvi_mode(dp) || dp->audio_test_req) {
+ dp->audio_test_req = false;
+
+ flags |= MSM_EXT_DISP_HPD_AUDIO;
+ }
if (dp->ext_audio_data.intf_ops.hpd)
ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
@@ -1493,11 +1595,6 @@ end:
return ret;
}
-static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, bool enable)
-{
- return mdss_dp_send_cable_notification(dp, enable);
-}
-
static void mdss_dp_set_default_resolution(struct mdss_dp_drv_pdata *dp)
{
hdmi_edid_set_video_resolution(dp->panel_data.panel_info.edid_data,
@@ -1606,6 +1703,93 @@ vreg_error:
return ret;
}
+/**
+ * mdss_dp_notify_clients() - notifies DP clients of cable connection
+ * @dp: Display Port Driver data
+ * @status: HPD notification status requested
+ *
+ * This function will send a notification to display/audio clients of change
+ * in DP connection status.
+ */
+static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
+ enum notification_status status)
+{
+ const int irq_comp_timeout = HZ * 2;
+ int ret = 0;
+
+ mutex_lock(&dp->pd_msg_mutex);
+ if (status == dp->hpd_notification_status) {
+ pr_debug("No change in status %s --> %s\n",
+ mdss_dp_notification_status_to_string(status),
+ mdss_dp_notification_status_to_string(
+ dp->hpd_notification_status));
+ goto end;
+ }
+
+ switch (status) {
+ case NOTIFY_CONNECT_IRQ_HPD:
+ if (dp->hpd_notification_status != NOTIFY_DISCONNECT_IRQ_HPD)
+ goto invalid_request;
+ /* Follow the same programming as for NOTIFY_CONNECT */
+ mdss_dp_host_init(&dp->panel_data);
+ mdss_dp_send_cable_notification(dp, true);
+ break;
+ case NOTIFY_CONNECT:
+ if ((dp->hpd_notification_status == NOTIFY_CONNECT_IRQ_HPD) ||
+ (dp->hpd_notification_status ==
+ NOTIFY_DISCONNECT_IRQ_HPD))
+ goto invalid_request;
+ mdss_dp_host_init(&dp->panel_data);
+ mdss_dp_send_cable_notification(dp, true);
+ break;
+ case NOTIFY_DISCONNECT:
+ mdss_dp_send_cable_notification(dp, false);
+ break;
+ case NOTIFY_DISCONNECT_IRQ_HPD:
+ if (dp->hpd_notification_status == NOTIFY_DISCONNECT)
+ goto invalid_request;
+
+ mdss_dp_send_cable_notification(dp, false);
+ if (!IS_ERR_VALUE(ret) && ret) {
+ reinit_completion(&dp->irq_comp);
+ ret = wait_for_completion_timeout(&dp->irq_comp,
+ irq_comp_timeout);
+ if (ret <= 0) {
+ pr_warn("irq_comp timed out\n");
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ }
+ }
+ break;
+ default:
+ pr_err("Invalid notification status = %d\n", status);
+ ret = -EINVAL;
+ break;
+ }
+
+ goto end;
+
+invalid_request:
+ pr_err("Invalid request %s --> %s\n",
+ mdss_dp_notification_status_to_string(
+ dp->hpd_notification_status),
+ mdss_dp_notification_status_to_string(status));
+ ret = -EINVAL;
+
+end:
+ if (!ret) {
+ pr_debug("Successfully sent notification %s --> %s\n",
+ mdss_dp_notification_status_to_string(
+ dp->hpd_notification_status),
+ mdss_dp_notification_status_to_string(status));
+ dp->hpd_notification_status = status;
+ }
+
+ mutex_unlock(&dp->pd_msg_mutex);
+ return ret;
+}
+
static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
{
int ret;
@@ -1613,6 +1797,8 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
if (dp->sink_info_read)
return 0;
+ pr_debug("start\n");
+
mdss_dp_dpcd_cap_read(dp);
ret = mdss_dp_edid_read(dp);
@@ -1620,20 +1806,35 @@ static int mdss_dp_process_hpd_high(struct mdss_dp_drv_pdata *dp)
pr_debug("edid read error, setting default resolution\n");
mdss_dp_set_default_resolution(dp);
- goto end;
+ goto notify;
}
ret = hdmi_edid_parser(dp->panel_data.panel_info.edid_data);
if (ret) {
pr_err("edid parse failed\n");
- goto end;
+ goto notify;
}
dp->sink_info_read = true;
-end:
- mdss_dp_update_cable_status(dp, true);
- mdss_dp_notify_clients(dp, true);
+notify:
+ /* Check if there is a PHY_TEST_PATTERN request when we get HPD high.
+ * Update the DP driver with the test parameters including link rate,
+ * lane count, voltage level, and pre-emphasis level. Do not notify
+ * the userspace of the connection, just power on the DP controller
+ * and mainlink with the new settings.
+ */
+ if (mdss_dp_is_phy_test_pattern_requested(dp)) {
+ pr_info("PHY_TEST_PATTERN requested by sink\n");
+ mdss_dp_process_phy_test_pattern_request(dp);
+ pr_info("skip client notification\n");
+ goto end;
+ }
+
+ mdss_dp_notify_clients(dp, NOTIFY_CONNECT);
+
+end:
+ pr_debug("end\n");
return ret;
}
@@ -1676,6 +1877,13 @@ end:
return rc;
}
+static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv)
+{
+ return dp_drv->hdcp.feature_enabled &&
+ (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) &&
+ dp_drv->hdcp.ops;
+}
+
static void mdss_dp_hdcp_cb_work(struct work_struct *work)
{
struct mdss_dp_drv_pdata *dp;
@@ -1688,6 +1896,13 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work)
dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work);
base = dp->base;
+
+ if (dp->hdcp_status == HDCP_STATE_AUTHENTICATING &&
+ mdss_dp_is_audio_pattern_requested(dp)) {
+ pr_debug("no hdcp for audio tests\n");
+ return;
+ }
+
hdcp_auth_state = (dp_read(base + DP_HDCP_STATUS) >> 20) & 0x3;
pr_debug("hdcp auth state %d\n", hdcp_auth_state);
@@ -1874,7 +2089,7 @@ static ssize_t mdss_dp_sysfs_rda_s3d_mode(struct device *dev,
static bool mdss_dp_is_test_ongoing(struct mdss_dp_drv_pdata *dp)
{
- return dp->hpd_irq_clients_notified;
+ return (dp->hpd_notification_status == NOTIFY_DISCONNECT_IRQ_HPD);
}
/**
@@ -1916,7 +2131,7 @@ static int mdss_dp_psm_config(struct mdss_dp_drv_pdata *dp, bool enable)
mdss_dp_mainlink_push_idle(&dp->panel_data);
mdss_dp_off_irq(dp);
} else {
- mdss_dp_notify_clients(dp, false);
+ mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
}
} else {
/*
@@ -1928,10 +2143,10 @@ static int mdss_dp_psm_config(struct mdss_dp_drv_pdata *dp, bool enable)
* to user modules.
*/
if (mdss_dp_is_test_ongoing(dp)) {
- mdss_dp_link_retraining(dp);
+ mdss_dp_link_maintenance(dp, true);
} else {
mdss_dp_host_init(&dp->panel_data);
- mdss_dp_notify_clients(dp, true);
+ mdss_dp_notify_clients(dp, NOTIFY_CONNECT);
}
}
@@ -1993,7 +2208,7 @@ static ssize_t mdss_dp_rda_psm(struct device *dev,
static ssize_t mdss_dp_wta_hpd(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- int hpd;
+ int hpd, rc;
ssize_t ret = strnlen(buf, PAGE_SIZE);
struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
@@ -2003,9 +2218,10 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
goto end;
}
- ret = kstrtoint(buf, 10, &hpd);
- if (ret) {
- pr_err("kstrtoint failed. ret=%d\n", (int)ret);
+ rc = kstrtoint(buf, 10, &hpd);
+ if (rc) {
+ pr_err("kstrtoint failed. ret=%d\n", rc);
+ ret = rc;
goto end;
}
@@ -2020,7 +2236,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
dp_send_events(dp, EV_USBPD_DISCOVER_MODES);
}
} else if (!dp->hpd && dp->power_on) {
- mdss_dp_notify_clients(dp, false);
+ mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT);
}
end:
return ret;
@@ -2043,6 +2259,233 @@ static ssize_t mdss_dp_rda_hpd(struct device *dev,
return ret;
}
+static int mdss_dp_parse_config_value(char const *buf, char const *name,
+ u32 *val)
+{
+ int ret = 0;
+ char *buf1;
+ char *token;
+
+ buf1 = strnstr(buf, name, PAGE_SIZE);
+ if (buf1) {
+ buf1 = buf1 + strlen(name);
+ token = strsep(&buf1, " ");
+ ret = kstrtou32(token, 10, val);
+ if (ret) {
+ pr_err("kstrtoint failed. ret=%d\n", (int)ret);
+ goto end;
+ }
+ pr_debug("parsed %s(%d)\n", name, *val);
+ } else {
+ ret = -EINVAL;
+ }
+
+end:
+ return ret;
+}
+
+static ssize_t mdss_dp_wta_config(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ u32 val;
+ u32 bit_depth;
+ int ret;
+ char const *bpp_key = "bpp=";
+ char const *pattern_type_key = "pattern_type=";
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+
+ if (!dp) {
+ pr_err("invalid data\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = mdss_dp_parse_config_value(buf, bpp_key, &val);
+ if (ret) {
+ pr_debug("%s config not found\n", bpp_key);
+ goto pattern_type;
+ }
+
+ bit_depth = mdss_dp_bpp_to_test_bit_depth(val);
+ if (!mdss_dp_is_test_bit_depth_valid(bit_depth)) {
+ pr_err("invalid bpp = %d\n", val);
+ } else {
+ dp->test_data.test_bit_depth = bit_depth;
+ if (val != 0)
+ dp->override_config = true;
+ else
+ dp->override_config = false;
+ pr_debug("bpp=%d, test_bit_depth=%d\n", val,
+ dp->test_data.test_bit_depth);
+ }
+
+pattern_type:
+ ret = mdss_dp_parse_config_value(buf, pattern_type_key, &val);
+ if (ret) {
+ pr_debug("%s config not found\n", pattern_type_key);
+ goto end;
+ }
+
+ if (!mdss_dp_is_test_video_pattern_valid(val)) {
+ pr_err("invalid test video pattern = %d\n", val);
+ } else {
+ dp->test_data.test_video_pattern = val;
+ pr_debug("test_video_pattern=%d (%s)\n",
+ dp->test_data.test_video_pattern,
+ mdss_dp_test_video_pattern_to_string(
+ dp->test_data.test_video_pattern));
+ }
+
+end:
+ return count;
+}
+
+static ssize_t mdss_dp_rda_config(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ u32 bpp;
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ bpp = mdss_dp_get_bpp(dp);
+ ret = snprintf(buf, PAGE_SIZE, "bpp=%d\npattern_type=%d\n",
+ bpp, dp->test_data.test_video_pattern);
+
+ pr_debug("bpp: %d pattern_type=%d (%s)\n",
+ bpp, dp->test_data.test_video_pattern,
+ mdss_dp_test_video_pattern_to_string(
+ dp->test_data.test_video_pattern));
+
+ return ret;
+}
+
+static ssize_t mdss_dp_wta_frame_crc(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ u32 val;
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+ char const *ctl_crc_key = "ctl_crc_en=";
+ char const *sink_crc_key = "sink_crc_en=";
+ bool ctl_crc_en, sink_crc_en;
+
+ if (!dp) {
+ pr_err("invalid data\n");
+ goto end;
+ }
+
+ if (!dp->power_on) {
+ pr_err("DP controller not powered on\n");
+ goto end;
+ }
+
+ ret = mdss_dp_parse_config_value(buf, ctl_crc_key, &val);
+ if (ret) {
+ pr_debug("%s config not found\n", ctl_crc_key);
+ goto sink_crc;
+ }
+ ctl_crc_en = val ? true : false;
+ mdss_dp_config_ctl_frame_crc(dp, ctl_crc_en);
+
+sink_crc:
+ ret = mdss_dp_parse_config_value(buf, sink_crc_key, &val);
+ if (ret) {
+ pr_debug("%s config not found\n", sink_crc_key);
+ goto end;
+ }
+ sink_crc_en = val ? true : false;
+ mdss_dp_aux_config_sink_frame_crc(dp, sink_crc_en);
+
+end:
+ return count;
+}
+
+static ssize_t mdss_dp_print_crc_values(struct mdss_dp_drv_pdata *dp,
+ char *buf, ssize_t len)
+{
+ char line[] = "------------------------------";
+
+ mdss_dp_read_ctl_frame_crc(dp);
+ mdss_dp_aux_read_sink_frame_crc(dp);
+
+ return snprintf(buf, PAGE_SIZE,
+ "\t\t|R_Cr\t\t|G_y\t\t|B_Cb\n%s%s\nctl(%s)\t|0x%08x\t|0x%08x\t|0x%08x\nsink(%s)\t|0x%08x\t|0x%08x\t|0x%08x\n",
+ line, line, dp->ctl_crc.en ? "enabled" : "disabled",
+ dp->ctl_crc.r_cr, dp->ctl_crc.g_y, dp->ctl_crc.b_cb,
+ dp->sink_crc.en ? "enabled" : "disabled",
+ dp->sink_crc.r_cr, dp->sink_crc.g_y, dp->sink_crc.b_cb);
+}
+
+static ssize_t mdss_dp_rda_frame_crc(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ if (!dp->power_on) {
+ pr_err("DP controller not powered on\n");
+ return 0;
+ }
+
+ ret = mdss_dp_print_crc_values(dp, buf, PAGE_SIZE);
+
+ return ret;
+}
+
+static ssize_t mdss_dp_wta_hdcp_feature(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ u32 hdcp;
+ int rc;
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+
+ if (!dp) {
+ pr_err("invalid data\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ rc = kstrtoint(buf, 10, &hdcp);
+ if (rc) {
+ pr_err("kstrtoint failed. ret=%d\n", rc);
+ ret = rc;
+ goto end;
+ }
+
+ dp->hdcp.feature_enabled = !!hdcp;
+ pr_debug("hdcp=%d\n", dp->hdcp.feature_enabled);
+end:
+ return ret;
+}
+
+static ssize_t mdss_dp_rda_hdcp_feature(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", dp->hdcp.feature_enabled);
+ pr_debug("hdcp: %d\n", dp->hdcp.feature_enabled);
+
+ return ret;
+}
+
static DEVICE_ATTR(connected, S_IRUGO, mdss_dp_rda_connected, NULL);
static DEVICE_ATTR(s3d_mode, S_IRUGO | S_IWUSR, mdss_dp_sysfs_rda_s3d_mode,
mdss_dp_sysfs_wta_s3d_mode);
@@ -2050,13 +2493,21 @@ static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, mdss_dp_rda_hpd,
mdss_dp_wta_hpd);
static DEVICE_ATTR(psm, S_IRUGO | S_IWUSR, mdss_dp_rda_psm,
mdss_dp_wta_psm);
-
+static DEVICE_ATTR(config, S_IRUGO | S_IWUSR, mdss_dp_rda_config,
+ mdss_dp_wta_config);
+static DEVICE_ATTR(frame_crc, S_IRUGO | S_IWUSR, mdss_dp_rda_frame_crc,
+ mdss_dp_wta_frame_crc);
+static DEVICE_ATTR(hdcp_feature, S_IRUGO | S_IWUSR, mdss_dp_rda_hdcp_feature,
+ mdss_dp_wta_hdcp_feature);
static struct attribute *mdss_dp_fs_attrs[] = {
&dev_attr_connected.attr,
&dev_attr_s3d_mode.attr,
&dev_attr_hpd.attr,
&dev_attr_psm.attr,
+ &dev_attr_config.attr,
+ &dev_attr_frame_crc.attr,
+ &dev_attr_hdcp_feature.attr,
NULL,
};
@@ -2124,6 +2575,11 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
return;
}
+ if (!dp->hdcp.feature_enabled) {
+ pr_debug("feature not enabled\n");
+ return;
+ }
+
/* check first if hdcp2p2 is supported */
fd = dp->hdcp.hdcp2;
if (fd)
@@ -2153,13 +2609,6 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
}
}
-static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv)
-{
- return dp_drv->hdcp.feature_enabled &&
- (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) &&
- dp_drv->hdcp.ops;
-}
-
static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -2235,21 +2684,6 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
return rc;
}
-static int mdss_dp_remove(struct platform_device *pdev)
-{
- struct mdss_dp_drv_pdata *dp_drv = NULL;
-
- dp_drv = platform_get_drvdata(pdev);
- dp_hdcp2p2_deinit(dp_drv->hdcp.data);
-
- iounmap(dp_drv->ctrl_io.base);
- dp_drv->ctrl_io.base = NULL;
- iounmap(dp_drv->phy_io.base);
- dp_drv->phy_io.base = NULL;
-
- return 0;
-}
-
static int mdss_dp_device_register(struct mdss_dp_drv_pdata *dp_drv)
{
int ret;
@@ -2360,81 +2794,105 @@ static void mdss_dp_do_link_train(struct mdss_dp_drv_pdata *dp)
mdss_dp_link_train(dp);
}
-static void mdss_dp_event_work(struct work_struct *work)
+static int mdss_dp_event_thread(void *data)
{
- struct mdss_dp_drv_pdata *dp = NULL;
unsigned long flag;
u32 todo = 0, config;
- if (!work) {
- pr_err("invalid work structure\n");
- return;
- }
-
- dp = container_of(work, struct mdss_dp_drv_pdata, work);
-
- spin_lock_irqsave(&dp->event_lock, flag);
- todo = dp->current_event;
- dp->current_event = 0;
- spin_unlock_irqrestore(&dp->event_lock, flag);
+ struct mdss_dp_event_data *ev_data;
+ struct mdss_dp_event *ev;
+ struct mdss_dp_drv_pdata *dp = NULL;
- pr_debug("todo=%s\n", mdss_dp_ev_event_to_string(todo));
+ if (!data)
+ return -EINVAL;
- switch (todo) {
- case EV_EDID_READ:
- mdss_dp_edid_read(dp);
- break;
- case EV_DPCD_CAP_READ:
- mdss_dp_dpcd_cap_read(dp);
- break;
- case EV_DPCD_STATUS_READ:
- mdss_dp_dpcd_status_read(dp);
- break;
- case EV_LINK_TRAIN:
- mdss_dp_do_link_train(dp);
- break;
- case EV_VIDEO_READY:
- mdss_dp_video_ready(dp);
- break;
- case EV_IDLE_PATTERNS_SENT:
- mdss_dp_idle_patterns_sent(dp);
- break;
- case EV_USBPD_ATTENTION:
- mdss_dp_handle_attention(dp);
- break;
- case EV_USBPD_DISCOVER_MODES:
- usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_DISCOVER_MODES,
- SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0);
- break;
- case EV_USBPD_ENTER_MODE:
- usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_ENTER_MODE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
- break;
- case EV_USBPD_EXIT_MODE:
- usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_EXIT_MODE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
- break;
- case EV_USBPD_DP_STATUS:
- config = 0x1; /* DFP_D connected */
- usbpd_send_svdm(dp->pd, USB_C_DP_SID, DP_VDM_STATUS,
- SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
- break;
- case EV_USBPD_DP_CONFIGURE:
- config = mdss_dp_usbpd_gen_config_pkt(dp);
- usbpd_send_svdm(dp->pd, USB_C_DP_SID, DP_VDM_CONFIGURE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
- break;
- default:
- pr_err("Unknown event:%d\n", todo);
+ ev_data = (struct mdss_dp_event_data *)data;
+ init_waitqueue_head(&ev_data->event_q);
+ spin_lock_init(&ev_data->event_lock);
+
+ while (!kthread_should_stop()) {
+ wait_event(ev_data->event_q,
+ (ev_data->pndx != ev_data->gndx) ||
+ kthread_should_stop());
+ spin_lock_irqsave(&ev_data->event_lock, flag);
+ ev = &(ev_data->event_list[ev_data->gndx++]);
+ todo = ev->id;
+ dp = ev->dp;
+ ev->id = 0;
+ ev_data->gndx %= MDSS_DP_EVENT_Q_MAX;
+ spin_unlock_irqrestore(&ev_data->event_lock, flag);
+
+ pr_debug("todo=%s\n", mdss_dp_ev_event_to_string(todo));
+
+ switch (todo) {
+ case EV_EDID_READ:
+ mdss_dp_edid_read(dp);
+ break;
+ case EV_DPCD_CAP_READ:
+ mdss_dp_dpcd_cap_read(dp);
+ break;
+ case EV_DPCD_STATUS_READ:
+ mdss_dp_dpcd_status_read(dp);
+ break;
+ case EV_LINK_TRAIN:
+ mdss_dp_do_link_train(dp);
+ break;
+ case EV_VIDEO_READY:
+ mdss_dp_video_ready(dp);
+ break;
+ case EV_IDLE_PATTERNS_SENT:
+ mdss_dp_idle_patterns_sent(dp);
+ break;
+ case EV_USBPD_ATTENTION:
+ mdss_dp_handle_attention(dp);
+ break;
+ case EV_USBPD_DISCOVER_MODES:
+ usbpd_send_svdm(dp->pd, USB_C_DP_SID,
+ USBPD_SVDM_DISCOVER_MODES,
+ SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0);
+ break;
+ case EV_USBPD_ENTER_MODE:
+ usbpd_send_svdm(dp->pd, USB_C_DP_SID,
+ USBPD_SVDM_ENTER_MODE,
+ SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
+ break;
+ case EV_USBPD_EXIT_MODE:
+ usbpd_send_svdm(dp->pd, USB_C_DP_SID,
+ USBPD_SVDM_EXIT_MODE,
+ SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
+ break;
+ case EV_USBPD_DP_STATUS:
+ config = 0x1; /* DFP_D connected */
+ usbpd_send_svdm(dp->pd, USB_C_DP_SID, DP_VDM_STATUS,
+ SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
+ break;
+ case EV_USBPD_DP_CONFIGURE:
+ config = mdss_dp_usbpd_gen_config_pkt(dp);
+ usbpd_send_svdm(dp->pd, USB_C_DP_SID, DP_VDM_CONFIGURE,
+ SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
+ break;
+ default:
+ pr_err("Unknown event:%d\n", todo);
+ }
}
+
+ return 0;
}
-static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 events)
+static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 event)
{
- spin_lock(&dp->event_lock);
- dp->current_event = events;
- queue_work(dp->workq, &dp->work);
- spin_unlock(&dp->event_lock);
+ struct mdss_dp_event *ev;
+ struct mdss_dp_event_data *ev_data = &dp->dp_event;
+
+ pr_debug("event=%s\n", mdss_dp_ev_event_to_string(event));
+
+ spin_lock(&ev_data->event_lock);
+ ev = &ev_data->event_list[ev_data->pndx++];
+ ev->id = event;
+ ev->dp = dp;
+ ev_data->pndx %= MDSS_DP_EVENT_Q_MAX;
+ wake_up(&ev_data->event_q);
+ spin_unlock(&ev_data->event_lock);
}
irqreturn_t dp_isr(int irq, void *ptr)
@@ -2470,10 +2928,10 @@ irqreturn_t dp_isr(int irq, void *ptr)
}
if (isr2 & EDP_INTR_READY_FOR_VIDEO)
- dp_send_events(dp, EV_VIDEO_READY);
+ mdss_dp_video_ready(dp);
if (isr2 & EDP_INTR_IDLE_PATTERNs_SENT)
- dp_send_events(dp, EV_IDLE_PATTERNS_SENT);
+ mdss_dp_idle_patterns_sent(dp);
if (isr1 && dp->aux_cmd_busy) {
/* clear DP_AUX_TRANS_CTRL */
@@ -2488,7 +2946,7 @@ irqreturn_t dp_isr(int irq, void *ptr)
dp_aux_native_handler(dp, isr1);
}
- if (dp->hdcp.ops && dp->hdcp.ops->isr) {
+ if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->isr) {
if (dp->hdcp.ops->isr(dp->hdcp.data))
pr_err("dp_hdcp_isr failed\n");
}
@@ -2496,17 +2954,32 @@ irqreturn_t dp_isr(int irq, void *ptr)
return IRQ_HANDLED;
}
+static void mdss_dp_event_cleanup(struct mdss_dp_drv_pdata *dp)
+{
+ destroy_workqueue(dp->workq);
+
+ if (dp->ev_thread == current)
+ return;
+
+ kthread_stop(dp->ev_thread);
+}
+
static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp)
{
- spin_lock_init(&dp->event_lock);
+ dp->ev_thread = kthread_run(mdss_dp_event_thread,
+ (void *)&dp->dp_event, "mdss_dp_event");
+ if (IS_ERR(dp->ev_thread)) {
+ pr_err("unable to start event thread\n");
+ return PTR_ERR(dp->ev_thread);
+ }
+
dp->workq = create_workqueue("mdss_dp_hpd");
if (!dp->workq) {
pr_err("%s: Error creating workqueue\n", __func__);
return -EPERM;
}
- INIT_WORK(&dp->work, mdss_dp_event_work);
INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work);
INIT_LIST_HEAD(&dp->attention_head);
return 0;
@@ -2541,7 +3014,18 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
pr_debug("cable disconnected\n");
mdss_dp_update_cable_status(dp_drv, false);
dp_drv->alt_mode.current_state = UNKNOWN_STATE;
- mdss_dp_notify_clients(dp_drv, false);
+
+ /**
+ * Manually turn off the DP controller if we are in PHY
+ * testing mode.
+ */
+ if (mdss_dp_is_phy_test_pattern_requested(dp_drv)) {
+ pr_info("turning off DP controller for PHY testing\n");
+ mdss_dp_mainlink_push_idle(&dp_drv->panel_data);
+ mdss_dp_off_hpd(dp_drv);
+ } else {
+ mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
+ }
}
static int mdss_dp_validate_callback(u8 cmd,
@@ -2598,54 +3082,22 @@ static inline void mdss_dp_send_test_response(struct mdss_dp_drv_pdata *dp)
}
/**
- * mdss_dp_hpd_irq_notify_clients() - notifies DP clients of HPD IRQ tear down
+ * mdss_dp_link_maintenance() - initiates link maintenanace
* @dp: Display Port Driver data
+ * @lt_needed: link retraining needed
*
- * This function will send a notification to display/audio clients of DP tear
- * down during an HPD IRQ. This happens only if HPD IRQ is toggled,
- * in which case the user space proceeds with shutdown of DP driver, including
- * mainlink disable, and pushing the controller into idle state.
- */
-static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp)
-{
- const int irq_comp_timeout = HZ * 2;
- int ret = 0;
-
- if (dp->hpd_irq_toggled) {
- dp->hpd_irq_clients_notified = true;
-
- ret = mdss_dp_notify_clients(dp, false);
-
- if (!IS_ERR_VALUE(ret) && ret) {
- reinit_completion(&dp->irq_comp);
- ret = wait_for_completion_timeout(&dp->irq_comp,
- irq_comp_timeout);
- if (ret <= 0) {
- pr_warn("irq_comp timed out\n");
- ret = -EINVAL;
- } else {
- ret = 0;
- }
- }
- }
-
- return 0;
-}
-
-/**
- * mdss_dp_link_retraining() - initiates link retraining
- * @dp: Display Port Driver data
- *
- * This function will initiate link retraining by first notifying
+ * This function will perform link maintenance by first notifying
* DP clients and triggering DP shutdown, and then enabling DP after
- * notification is done successfully.
+ * notification is done successfully. It will perform link retraining
+ * if specified.
*/
-static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp)
+static inline void mdss_dp_link_maintenance(struct mdss_dp_drv_pdata *dp,
+ bool lt_needed)
{
- if (mdss_dp_hpd_irq_notify_clients(dp))
+ if (mdss_dp_notify_clients(dp, NOTIFY_DISCONNECT_IRQ_HPD))
return;
- mdss_dp_on_irq(dp);
+ mdss_dp_on_irq(dp, lt_needed);
}
/**
@@ -2670,7 +3122,7 @@ static int mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp)
mdss_dp_aux_channel_eq_done(dp),
mdss_dp_aux_clock_recovery_done(dp));
- mdss_dp_link_retraining(dp);
+ mdss_dp_link_maintenance(dp, true);
return 0;
}
@@ -2701,7 +3153,7 @@ static int mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
dp->test_data.test_lane_count;
dp->link_rate = dp->test_data.test_link_rate;
- mdss_dp_link_retraining(dp);
+ mdss_dp_link_maintenance(dp, true);
return 0;
}
@@ -2722,38 +3174,109 @@ static int mdss_dp_process_phy_test_pattern_request(
if (!mdss_dp_is_phy_test_pattern_requested(dp))
return -EINVAL;
- mdss_dp_send_test_response(dp);
-
test_link_rate = dp->test_data.test_link_rate;
test_lane_count = dp->test_data.test_lane_count;
- pr_info("%s link rate = 0x%x, lane count = 0x%x\n",
- mdss_dp_get_test_name(TEST_LINK_TRAINING),
- test_link_rate, test_lane_count);
+ if (!mdss_dp_aux_is_link_rate_valid(test_link_rate) ||
+ !mdss_dp_aux_is_lane_count_valid(test_lane_count)) {
+ pr_info("Invalid params: link rate = 0x%x, lane count = 0x%x\n",
+ test_link_rate, test_lane_count);
+ return -EINVAL;
+ }
+
+ pr_debug("start\n");
+
+ if (dp->power_on) {
+ pr_info("turning off DP controller for PHY testing\n");
+ mdss_dp_mainlink_push_idle(&dp->panel_data);
+ /*
+ * The global reset will need DP link ralated clocks to be
+ * running. Add the global reset just before disabling the
+ * link clocks and core clocks.
+ */
+ mdss_dp_ctrl_reset(&dp->ctrl_io);
+ mdss_dp_off_irq(dp);
+ }
/**
- * Retrain the mainlink if there is a change in link rate or lane
- * count.
+ * Set the timing information to 1920x1080p60. This resolution will be
+ * used when enabling the pixel clock.
*/
- if (mdss_dp_aux_is_link_rate_valid(test_link_rate) &&
- mdss_dp_aux_is_lane_count_valid(test_lane_count) &&
- ((dp->dpcd.max_lane_count != test_lane_count) ||
- (dp->link_rate != test_link_rate))) {
+ dp_init_panel_info(dp, HDMI_VFRMT_1920x1080p60_16_9);
- pr_info("updated link rate or lane count, retraining.\n");
+ pr_info("Current: link rate = 0x%x, lane count = 0x%x\n",
+ dp->dpcd.max_lane_count,
+ dp->link_rate);
- dp->dpcd.max_lane_count = dp->test_data.test_lane_count;
- dp->link_rate = dp->test_data.test_link_rate;
+ pr_info("Requested: link rate = 0x%x, lane count = 0x%x\n",
+ dp->test_data.test_link_rate,
+ dp->test_data.test_lane_count);
- mdss_dp_link_retraining(dp);
- }
+ dp->dpcd.max_lane_count = dp->test_data.test_lane_count;
+ dp->link_rate = dp->test_data.test_link_rate;
- mdss_dp_config_ctrl(dp);
+ mdss_dp_on_irq(dp, true);
+ /**
+ * Read the updated values for voltage and pre-emphasis levels and
+ * then program the DP controller PHY accordingly.
+ */
+ mdss_dp_aux_parse_vx_px(dp);
mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(dp);
mdss_dp_phy_send_test_pattern(dp);
+ mdss_dp_send_test_response(dp);
+
+ pr_debug("end\n");
+
+ return 0;
+}
+
+/**
+ * mdss_dp_process_audio_pattern_request() - process new audio pattern request
+ * @dp: Display Port Driver data
+ *
+ * This function will handle a new audio pattern request that is initiated by
+ * the sink. This is acheieved by sending the necessary secondary data packets
+ * to the sink. It is expected that any simulatenous requests for video
+ * patterns will be handled before the audio pattern is sent to the sink.
+ */
+static int mdss_dp_process_audio_pattern_request(struct mdss_dp_drv_pdata *dp)
+{
+ if (!mdss_dp_is_audio_pattern_requested(dp))
+ return -EINVAL;
+
+ if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) {
+ cancel_delayed_work(&dp->hdcp_cb_work);
+ dp->hdcp.ops->off(dp->hdcp.data);
+ }
+
+ pr_debug("sampling_rate=%s, channel_count=%d, pattern_type=%s\n",
+ mdss_dp_get_audio_sample_rate(
+ dp->test_data.test_audio_sampling_rate),
+ dp->test_data.test_audio_channel_count,
+ mdss_dp_get_audio_test_pattern(
+ dp->test_data.test_audio_pattern_type));
+
+ pr_debug("audio_period: ch1=0x%x, ch2=0x%x, ch3=0x%x, ch4=0x%x\n",
+ dp->test_data.test_audio_period_ch_1,
+ dp->test_data.test_audio_period_ch_2,
+ dp->test_data.test_audio_period_ch_3,
+ dp->test_data.test_audio_period_ch_4);
+
+ pr_debug("audio_period: ch5=0x%x, ch6=0x%x, ch7=0x%x, ch8=0x%x\n",
+ dp->test_data.test_audio_period_ch_5,
+ dp->test_data.test_audio_period_ch_6,
+ dp->test_data.test_audio_period_ch_7,
+ dp->test_data.test_audio_period_ch_8);
+
+ if (dp->ext_audio_data.intf_ops.hpd)
+ dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
+ dp->ext_audio_data.type, 1, MSM_EXT_DISP_HPD_AUDIO);
+
+ dp->audio_test_req = true;
+
return 0;
}
@@ -2777,6 +3300,81 @@ static int mdss_dp_process_downstream_port_status_change(
return mdss_dp_edid_read(dp);
}
+static bool mdss_dp_video_pattern_test_lt_needed(struct mdss_dp_drv_pdata *dp)
+{
+ char new_link_rate;
+
+ /*
+ * Link re-training for video format change is only needed if:
+ * 1. Link rate changes
+ * 2. Lane count changes
+ * For now, assume that lane count is not going to change
+ */
+ new_link_rate = mdss_dp_gen_link_clk(dp);
+ pr_debug("new link rate = 0x%x, current link rate = 0x%x\n",
+ new_link_rate, dp->link_rate);
+ if (new_link_rate != dp->link_rate) {
+ dp->link_rate = new_link_rate;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * mdss_dp_process_video_pattern_request() - process new video pattern request
+ * @dp: Display Port Driver data
+ *
+ * This function will handle a new video pattern request that are initiated by
+ * the sink. This is acheieved by first sending a disconnect notification to
+ * the sink followed by a subsequent connect notification to the user modules,
+ * where it is expected that the user modules would draw the required test
+ * pattern.
+ */
+static int mdss_dp_process_video_pattern_request(struct mdss_dp_drv_pdata *dp)
+{
+ bool lt_needed;
+ struct hdmi_edid_override_data ov_data = {0, 0, 1,
+ HDMI_VFRMT_640x480p59_4_3};
+ bool ov_res = false;
+
+ if (!mdss_dp_is_video_pattern_requested(dp))
+ goto end;
+
+ pr_info("%s: bit depth=%d(%d bpp) pattern=%s\n",
+ mdss_dp_get_test_name(TEST_VIDEO_PATTERN),
+ dp->test_data.test_bit_depth,
+ mdss_dp_test_bit_depth_to_bpp(dp->test_data.test_bit_depth),
+ mdss_dp_test_video_pattern_to_string(
+ dp->test_data.test_video_pattern));
+
+ if (dp->test_data.test_h_width == 640) {
+ pr_debug("Set resolution to 640x480p59");
+ if (dp->vic != HDMI_VFRMT_640x480p59_4_3) {
+ ov_res = true;
+ dp->vic = HDMI_VFRMT_640x480p59_4_3;
+ }
+ hdmi_edid_config_override(dp->panel_data.panel_info.edid_data,
+ true, &ov_data);
+ }
+
+ dp_init_panel_info(dp, dp->vic);
+ lt_needed = ov_res | mdss_dp_video_pattern_test_lt_needed(dp);
+
+ pr_debug("Link training needed: %s", lt_needed ? "yes" : "no");
+
+ mdss_dp_link_maintenance(dp, lt_needed);
+
+ if (mdss_dp_is_audio_pattern_requested(dp))
+ goto end;
+
+ mdss_dp_send_test_response(dp);
+
+ return 0;
+end:
+ return -EINVAL;
+}
+
/**
* mdss_dp_process_hpd_irq_high() - handle HPD IRQ transition to HIGH
* @dp: Display Port Driver data
@@ -2789,14 +3387,22 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
+ pr_debug("start\n");
+
dp->hpd_irq_on = true;
+ mdss_dp_reset_test_data(dp);
+
mdss_dp_aux_parse_sink_status_field(dp);
ret = mdss_dp_process_link_training_request(dp);
if (!ret)
goto exit;
+ ret = mdss_dp_process_phy_test_pattern_request(dp);
+ if (!ret)
+ goto exit;
+
ret = mdss_dp_process_link_status_update(dp);
if (!ret)
goto exit;
@@ -2805,41 +3411,19 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
if (!ret)
goto exit;
- ret = mdss_dp_process_phy_test_pattern_request(dp);
+ ret = mdss_dp_process_video_pattern_request(dp);
if (!ret)
goto exit;
- pr_debug("done\n");
-exit:
- mdss_dp_reset_test_data(dp);
-
- return ret;
-}
-/**
- * mdss_dp_process_hpd_irq_low() - handle HPD IRQ transition to LOW
- * @dp: Display Port Driver data
- *
- * This function will handle the HPD IRQ state transitions from HIGH to LOW,
- * indicating the end of a test request.
- */
-static int mdss_dp_process_hpd_irq_low(struct mdss_dp_drv_pdata *dp)
-{
- if (!dp->hpd_irq_clients_notified)
- return -EINVAL;
+ ret = mdss_dp_process_audio_pattern_request(dp);
+ if (!ret)
+ goto exit;
- pr_debug("enter: HPD IRQ low\n");
+ pr_debug("done\n");
+exit:
dp->hpd_irq_on = false;
- dp->hpd_irq_clients_notified = false;
-
- mdss_dp_update_cable_status(dp, false);
- mdss_dp_mainlink_push_idle(&dp->panel_data);
- mdss_dp_off_hpd(dp);
-
- mdss_dp_reset_test_data(dp);
-
- pr_debug("done\n");
- return 0;
+ return ret;
}
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
@@ -2900,6 +3484,7 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
case DP_VDM_CONFIGURE:
dp_drv->alt_mode.current_state |= DP_CONFIGURE_DONE;
pr_debug("Configure: config USBPD to DP done\n");
+ mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status);
mdss_dp_host_init(&dp_drv->panel_data);
@@ -2914,22 +3499,16 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
{
- dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on !=
- dp_drv->alt_mode.dp_status.hpd_irq;
-
if (dp_drv->alt_mode.dp_status.hpd_irq) {
pr_debug("Attention: hpd_irq high\n");
- if (dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) {
+ if (dp_is_hdcp_enabled(dp_drv) && dp_drv->hdcp.ops->cp_irq) {
if (!dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data))
return;
}
if (!mdss_dp_process_hpd_irq_high(dp_drv))
return;
- } else if (dp_drv->hpd_irq_toggled) {
- if (!mdss_dp_process_hpd_irq_low(dp_drv))
- return;
}
if (!dp_drv->alt_mode.dp_status.hpd_high) {
@@ -2940,16 +3519,23 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
dp_drv->hdcp.ops->off(dp_drv->hdcp.data);
}
- mdss_dp_update_cable_status(dp_drv, false);
- mdss_dp_notify_clients(dp_drv, false);
+ mdss_dp_notify_clients(dp_drv, NOTIFY_DISCONNECT);
pr_debug("Attention: Notified clients\n");
+
+ /**
+ * Manually turn off the DP controller if we are in PHY
+ * testing mode.
+ */
+ if (mdss_dp_is_phy_test_pattern_requested(dp_drv)) {
+ pr_info("turning off DP controller for PHY testing\n");
+ mdss_dp_mainlink_push_idle(&dp_drv->panel_data);
+ mdss_dp_off_hpd(dp_drv);
+ }
return;
}
pr_debug("Attention: HPD high\n");
- mdss_dp_update_cable_status(dp_drv, true);
-
dp_drv->alt_mode.current_state |= DP_STATUS_DONE;
if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) {
@@ -2963,6 +3549,7 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp)
{
int i = 0;
+ pr_debug("start\n");
while (!list_empty_careful(&dp->attention_head)) {
struct mdss_dp_attention_node *node;
@@ -2983,8 +3570,11 @@ static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp)
dp->alt_mode.dp_status.response = vdo;
mdss_dp_usbpd_ext_dp_status(&dp->alt_mode.dp_status);
mdss_dp_process_attention(dp);
+
+ pr_debug("done processing item %d in the list\n", i);
};
+ pr_debug("exit\n");
}
static int mdss_dp_usbpd_setup(struct mdss_dp_drv_pdata *dp_drv)
@@ -3063,6 +3653,11 @@ static int mdss_dp_probe(struct platform_device *pdev)
mutex_init(&dp_drv->attention_lock);
mutex_init(&dp_drv->hdcp_mutex);
spin_lock_init(&dp_drv->lock);
+ mutex_init(&dp_drv->aux_mutex);
+ mutex_init(&dp_drv->train_mutex);
+ init_completion(&dp_drv->aux_comp);
+ init_completion(&dp_drv->idle_comp);
+ init_completion(&dp_drv->video_comp);
if (mdss_dp_usbpd_setup(dp_drv)) {
pr_err("Error usbpd setup!\n");
@@ -3202,6 +3797,22 @@ static inline bool dp_is_stream_shareable(struct mdss_dp_drv_pdata *dp_drv)
return ret;
}
+static int mdss_dp_remove(struct platform_device *pdev)
+{
+ struct mdss_dp_drv_pdata *dp_drv = NULL;
+
+ dp_drv = platform_get_drvdata(pdev);
+ dp_hdcp2p2_deinit(dp_drv->hdcp.data);
+
+ mdss_dp_event_cleanup(dp_drv);
+ iounmap(dp_drv->ctrl_io.base);
+ dp_drv->ctrl_io.base = NULL;
+ iounmap(dp_drv->phy_io.base);
+ dp_drv->phy_io.base = NULL;
+
+ return 0;
+}
+
static const struct of_device_id msm_mdss_dp_dt_match[] = {
{.compatible = "qcom,mdss-dp"},
{}
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index b7a8583e5864..bf74a8a4d7df 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -269,6 +269,32 @@ struct dpcd_test_request {
u32 test_link_rate;
u32 test_lane_count;
u32 phy_test_pattern_sel;
+ u32 test_video_pattern;
+ u32 test_bit_depth;
+ u32 test_dyn_range;
+ u32 test_h_total;
+ u32 test_v_total;
+ u32 test_h_start;
+ u32 test_v_start;
+ u32 test_hsync_pol;
+ u32 test_hsync_width;
+ u32 test_vsync_pol;
+ u32 test_vsync_width;
+ u32 test_h_width;
+ u32 test_v_height;
+ u32 test_rr_d;
+ u32 test_rr_n;
+ u32 test_audio_sampling_rate;
+ u32 test_audio_channel_count;
+ u32 test_audio_pattern_type;
+ u32 test_audio_period_ch_1;
+ u32 test_audio_period_ch_2;
+ u32 test_audio_period_ch_3;
+ u32 test_audio_period_ch_4;
+ u32 test_audio_period_ch_5;
+ u32 test_audio_period_ch_6;
+ u32 test_audio_period_ch_7;
+ u32 test_audio_period_ch_8;
u32 response;
};
@@ -376,6 +402,28 @@ struct dp_hdcp {
bool feature_enabled;
};
+struct mdss_dp_event {
+ struct mdss_dp_drv_pdata *dp;
+ u32 id;
+};
+
+#define MDSS_DP_EVENT_Q_MAX 4
+
+struct mdss_dp_event_data {
+ wait_queue_head_t event_q;
+ u32 pndx;
+ u32 gndx;
+ struct mdss_dp_event event_list[MDSS_DP_EVENT_Q_MAX];
+ spinlock_t event_lock;
+};
+
+struct mdss_dp_crc_data {
+ bool en;
+ u32 r_cr;
+ u32 g_y;
+ u32 b_cb;
+};
+
struct mdss_dp_drv_pdata {
/* device driver */
int (*on) (struct mdss_panel_data *pdata);
@@ -402,6 +450,7 @@ struct mdss_dp_drv_pdata {
bool sink_info_read;
bool hpd;
bool psm_enabled;
+ bool audio_test_req;
/* dp specific */
unsigned char *base;
@@ -413,8 +462,11 @@ struct mdss_dp_drv_pdata {
struct dss_io_data hdcp_io;
int base_size;
unsigned char *mmss_cc_base;
+ bool override_config;
u32 mask1;
u32 mask2;
+ struct mdss_dp_crc_data ctl_crc;
+ struct mdss_dp_crc_data sink_crc;
struct mdss_panel_data panel_data;
struct mdss_util_intf *mdss_util;
@@ -451,7 +503,6 @@ struct mdss_dp_drv_pdata {
/* aux */
struct completion aux_comp;
- struct completion train_comp;
struct completion idle_comp;
struct completion video_comp;
struct completion irq_comp;
@@ -478,18 +529,15 @@ struct mdss_dp_drv_pdata {
char tu_desired;
char valid_boundary;
char delay_start;
- u32 bpp;
struct dp_statistic dp_stat;
bool hpd_irq_on;
- bool hpd_irq_toggled;
- bool hpd_irq_clients_notified;
+ u32 hpd_notification_status;
+
+ struct mdss_dp_event_data dp_event;
+ struct task_struct *ev_thread;
- /* event */
struct workqueue_struct *workq;
- struct work_struct work;
struct delayed_work hdcp_cb_work;
- u32 current_event;
- spinlock_t event_lock;
spinlock_t lock;
struct switch_dev sdev;
struct kobject *kobj;
@@ -512,6 +560,55 @@ enum dp_lane_count {
DP_LANE_COUNT_4 = 4,
};
+enum audio_pattern_type {
+ AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00,
+ AUDIO_TEST_PATTERN_SAWTOOTH = 0x01,
+};
+
+static inline char *mdss_dp_get_audio_test_pattern(u32 pattern)
+{
+ switch (pattern) {
+ case AUDIO_TEST_PATTERN_OPERATOR_DEFINED:
+ return DP_ENUM_STR(AUDIO_TEST_PATTERN_OPERATOR_DEFINED);
+ case AUDIO_TEST_PATTERN_SAWTOOTH:
+ return DP_ENUM_STR(AUDIO_TEST_PATTERN_SAWTOOTH);
+ default:
+ return "unknown";
+ }
+}
+
+enum audio_sample_rate {
+ AUDIO_SAMPLE_RATE_32_KHZ = 0x00,
+ AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01,
+ AUDIO_SAMPLE_RATE_48_KHZ = 0x02,
+ AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03,
+ AUDIO_SAMPLE_RATE_96_KHZ = 0x04,
+ AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05,
+ AUDIO_SAMPLE_RATE_192_KHZ = 0x06,
+};
+
+static inline char *mdss_dp_get_audio_sample_rate(u32 rate)
+{
+ switch (rate) {
+ case AUDIO_SAMPLE_RATE_32_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_32_KHZ);
+ case AUDIO_SAMPLE_RATE_44_1_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_44_1_KHZ);
+ case AUDIO_SAMPLE_RATE_48_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_48_KHZ);
+ case AUDIO_SAMPLE_RATE_88_2_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_88_2_KHZ);
+ case AUDIO_SAMPLE_RATE_96_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_96_KHZ);
+ case AUDIO_SAMPLE_RATE_176_4_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_176_4_KHZ);
+ case AUDIO_SAMPLE_RATE_192_KHZ:
+ return DP_ENUM_STR(AUDIO_SAMPLE_RATE_192_KHZ);
+ default:
+ return "unknown";
+ }
+}
+
enum phy_test_pattern {
PHY_TEST_PATTERN_NONE,
PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING,
@@ -608,17 +705,22 @@ static inline char *mdss_dp_get_test_response(u32 test_response)
enum test_type {
UNKNOWN_TEST = 0,
- TEST_LINK_TRAINING = BIT(0),
- PHY_TEST_PATTERN = BIT(3),
- TEST_EDID_READ = BIT(2),
+ TEST_LINK_TRAINING = 0x1,
+ TEST_VIDEO_PATTERN = 0x2,
+ PHY_TEST_PATTERN = 0x8,
+ TEST_EDID_READ = 0x4,
+ TEST_AUDIO_PATTERN = 32,
+ TEST_AUDIO_DISABLED_VIDEO = 64,
};
static inline char *mdss_dp_get_test_name(u32 test_requested)
{
switch (test_requested) {
case TEST_LINK_TRAINING: return DP_ENUM_STR(TEST_LINK_TRAINING);
+ case TEST_VIDEO_PATTERN: return DP_ENUM_STR(TEST_VIDEO_PATTERN);
case PHY_TEST_PATTERN: return DP_ENUM_STR(PHY_TEST_PATTERN);
case TEST_EDID_READ: return DP_ENUM_STR(TEST_EDID_READ);
+ case TEST_AUDIO_PATTERN: return DP_ENUM_STR(TEST_AUDIO_PATTERN);
default: return "unknown";
}
}
@@ -661,11 +763,252 @@ static inline char *mdss_dp_ev_event_to_string(int event)
return DP_ENUM_STR(EV_IDLE_PATTERNS_SENT);
case EV_VIDEO_READY:
return DP_ENUM_STR(EV_VIDEO_READY);
+ case EV_USBPD_DISCOVER_MODES:
+ return DP_ENUM_STR(EV_USBPD_DISCOVER_MODES);
+ case EV_USBPD_ENTER_MODE:
+ return DP_ENUM_STR(EV_USBPD_ENTER_MODE);
+ case EV_USBPD_DP_STATUS:
+ return DP_ENUM_STR(EV_USBPD_DP_STATUS);
+ case EV_USBPD_DP_CONFIGURE:
+ return DP_ENUM_STR(EV_USBPD_DP_CONFIGURE);
+ case EV_USBPD_CC_PIN_POLARITY:
+ return DP_ENUM_STR(EV_USBPD_CC_PIN_POLARITY);
+ case EV_USBPD_EXIT_MODE:
+ return DP_ENUM_STR(EV_USBPD_EXIT_MODE);
+ case EV_USBPD_ATTENTION:
+ return DP_ENUM_STR(EV_USBPD_ATTENTION);
+ default:
+ return "unknown";
+ }
+}
+
+enum dynamic_range {
+ DP_DYNAMIC_RANGE_RGB_VESA = 0x00,
+ DP_DYNAMIC_RANGE_RGB_CEA = 0x01,
+ DP_DYNAMIC_RANGE_UNKNOWN = 0xFFFFFFFF,
+};
+
+static inline char *mdss_dp_dynamic_range_to_string(u32 dr)
+{
+ switch (dr) {
+ case DP_DYNAMIC_RANGE_RGB_VESA:
+ return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_VESA);
+ case DP_DYNAMIC_RANGE_RGB_CEA:
+ return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_CEA);
+ case DP_DYNAMIC_RANGE_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
+
+/**
+ * mdss_dp_is_dynamic_range_valid() - validates the dynamic range
+ * @bit_depth: the dynamic range value to be checked
+ *
+ * Returns true if the dynamic range value is supported.
+ */
+static inline bool mdss_dp_is_dynamic_range_valid(u32 dr)
+{
+ switch (dr) {
+ case DP_DYNAMIC_RANGE_RGB_VESA:
+ case DP_DYNAMIC_RANGE_RGB_CEA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+enum test_bit_depth {
+ DP_TEST_BIT_DEPTH_6 = 0x00,
+ DP_TEST_BIT_DEPTH_8 = 0x01,
+ DP_TEST_BIT_DEPTH_10 = 0x02,
+ DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
+};
+
+static inline char *mdss_dp_test_bit_depth_to_string(u32 tbd)
+{
+ switch (tbd) {
+ case DP_TEST_BIT_DEPTH_6:
+ return DP_ENUM_STR(DP_TEST_BIT_DEPTH_6);
+ case DP_TEST_BIT_DEPTH_8:
+ return DP_ENUM_STR(DP_TEST_BIT_DEPTH_8);
+ case DP_TEST_BIT_DEPTH_10:
+ return DP_ENUM_STR(DP_TEST_BIT_DEPTH_10);
+ case DP_TEST_BIT_DEPTH_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
+
+/**
+ * mdss_dp_is_test_bit_depth_valid() - validates the bit depth requested
+ * @bit_depth: bit depth requested by the sink
+ *
+ * Returns true if the requested bit depth is supported.
+ */
+static inline bool mdss_dp_is_test_bit_depth_valid(u32 tbd)
+{
+ /* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */
+ switch (tbd) {
+ case DP_TEST_BIT_DEPTH_6:
+ case DP_TEST_BIT_DEPTH_8:
+ case DP_TEST_BIT_DEPTH_10:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
+ * @tbd: test bit depth
+ *
+ * Returns the bits per pixel (bpp) to be used corresponding to the
+ * git bit depth value. This function assumes that bit depth has
+ * already been validated.
+ */
+static inline u32 mdss_dp_test_bit_depth_to_bpp(enum test_bit_depth tbd)
+{
+ u32 bpp;
+
+ /*
+ * Few simplistic rules and assumptions made here:
+ * 1. Bit depth is per color component
+ * 2. If bit depth is unknown return 0
+ * 3. Assume 3 color components
+ */
+ switch (tbd) {
+ case DP_TEST_BIT_DEPTH_6:
+ bpp = 18;
+ break;
+ case DP_TEST_BIT_DEPTH_8:
+ bpp = 24;
+ break;
+ case DP_TEST_BIT_DEPTH_10:
+ bpp = 30;
+ break;
+ case DP_TEST_BIT_DEPTH_UNKNOWN:
+ default:
+ bpp = 0;
+ }
+
+ return bpp;
+}
+
+/**
+ * mdss_dp_bpp_to_test_bit_depth() - convert bpp to test bit depth
+ * &bpp: the bpp to be converted
+ *
+ * Return the bit depth per color component to used with the video
+ * test pattern data based on the bits per pixel value.
+ */
+static inline u32 mdss_dp_bpp_to_test_bit_depth(u32 bpp)
+{
+ enum test_bit_depth tbd;
+
+ /*
+ * Few simplistic rules and assumptions made here:
+ * 1. Test bit depth is bit depth per color component
+ * 2. Assume 3 color components
+ */
+ switch (bpp) {
+ case 18:
+ tbd = DP_TEST_BIT_DEPTH_6;
+ break;
+ case 24:
+ tbd = DP_TEST_BIT_DEPTH_8;
+ break;
+ case 30:
+ tbd = DP_TEST_BIT_DEPTH_10;
+ break;
+ default:
+ tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
+ break;
+ }
+
+ return tbd;
+}
+
+enum test_video_pattern {
+ DP_TEST_VIDEO_PATTERN_NONE = 0x00,
+ DP_TEST_VIDEO_PATTERN_COLOR_RAMPS = 0x01,
+ DP_TEST_VIDEO_PATTERN_BW_VERT_LINES = 0x02,
+ DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
+};
+
+static inline char *mdss_dp_test_video_pattern_to_string(u32 test_video_pattern)
+{
+ switch (test_video_pattern) {
+ case DP_TEST_VIDEO_PATTERN_NONE:
+ return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_NONE);
+ case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
+ return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_RAMPS);
+ case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
+ return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_BW_VERT_LINES);
+ case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
+ return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_SQUARE);
default:
return "unknown";
}
}
+/**
+ * mdss_dp_is_test_video_pattern_valid() - validates the video pattern
+ * @pattern: video pattern requested by the sink
+ *
+ * Returns true if the requested video pattern is supported.
+ */
+static inline bool mdss_dp_is_test_video_pattern_valid(u32 pattern)
+{
+ switch (pattern) {
+ case DP_TEST_VIDEO_PATTERN_NONE:
+ case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
+ case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
+ case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+enum notification_status {
+ NOTIFY_UNKNOWN,
+ NOTIFY_CONNECT,
+ NOTIFY_DISCONNECT,
+ NOTIFY_CONNECT_IRQ_HPD,
+ NOTIFY_DISCONNECT_IRQ_HPD,
+};
+
+static inline char const *mdss_dp_notification_status_to_string(
+ enum notification_status status)
+{
+ switch (status) {
+ case NOTIFY_UNKNOWN:
+ return DP_ENUM_STR(NOTIFY_UNKNOWN);
+ case NOTIFY_CONNECT:
+ return DP_ENUM_STR(NOTIFY_CONNECT);
+ case NOTIFY_DISCONNECT:
+ return DP_ENUM_STR(NOTIFY_DISCONNECT);
+ case NOTIFY_CONNECT_IRQ_HPD:
+ return DP_ENUM_STR(NOTIFY_CONNECT_IRQ_HPD);
+ case NOTIFY_DISCONNECT_IRQ_HPD:
+ return DP_ENUM_STR(NOTIFY_DISCONNECT_IRQ_HPD);
+ default:
+ return "unknown";
+ }
+}
+
+static inline void mdss_dp_reset_frame_crc_data(struct mdss_dp_crc_data *crc)
+{
+ if (!crc)
+ return;
+
+ crc->r_cr = 0;
+ crc->g_y = 0;
+ crc->b_cb = 0;
+ crc->en = false;
+}
+
void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
@@ -681,7 +1024,7 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep);
void mdss_dp_sink_power_down(struct mdss_dp_drv_pdata *ep);
void mdss_dp_lane_power_ctrl(struct mdss_dp_drv_pdata *ep, int up);
void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *ep);
-char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt);
+char mdss_dp_gen_link_clk(struct mdss_dp_drv_pdata *dp);
int mdss_dp_aux_set_sink_power_state(struct mdss_dp_drv_pdata *ep, char state);
int mdss_dp_aux_send_psm_request(struct mdss_dp_drv_pdata *dp, bool enable);
void mdss_dp_aux_send_test_response(struct mdss_dp_drv_pdata *ep);
@@ -694,5 +1037,9 @@ bool mdss_dp_aux_is_lane_count_valid(u32 lane_count);
int mdss_dp_aux_link_status_read(struct mdss_dp_drv_pdata *ep, int len);
void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
struct mdss_dp_drv_pdata *dp);
+int mdss_dp_aux_read_sink_frame_crc(struct mdss_dp_drv_pdata *dp);
+int mdss_dp_aux_config_sink_frame_crc(struct mdss_dp_drv_pdata *dp,
+ bool enable);
+int mdss_dp_aux_parse_vx_px(struct mdss_dp_drv_pdata *ep);
#endif /* MDSS_DP_H */
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index fa1af0d392e7..ca07e80d6613 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, 2014, 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -466,10 +466,8 @@ void dp_extract_edid_video_support(struct edp_edid *edid, char *buf)
edid->video_intf = *bp & 0x0f;
/* 6, 8, 10, 12, 14 and 16 bit per component */
edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
- if (edid->color_depth) {
- edid->color_depth *= 2;
- edid->color_depth += 4;
- }
+ /* decrement to match with the test_bit_depth enum definition */
+ edid->color_depth--;
pr_debug("Digital Video intf=%d color_depth=%d\n",
edid->video_intf, edid->color_depth);
} else {
@@ -501,12 +499,14 @@ void dp_extract_edid_feature(struct edp_edid *edid, char *buf)
edid->dpm, edid->color_format);
};
-char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt)
+char mdss_dp_gen_link_clk(struct mdss_dp_drv_pdata *dp)
{
const u32 encoding_factx10 = 8;
const u32 ln_to_link_ratio = 10;
u32 min_link_rate, reminder = 0;
char calc_link_rate = 0;
+ struct mdss_panel_info *pinfo = &dp->panel_data.panel_info;
+ char lane_cnt = dp->dpcd.max_lane_count;
pr_debug("clk_rate=%llu, bpp= %d, lane_cnt=%d\n",
pinfo->clk_rate, pinfo->bpp, lane_cnt);
@@ -545,6 +545,11 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt)
calc_link_rate = DP_LINK_RATE_540;
}
+ pr_debug("calc_link_rate=0x%x, Max rate supported by sink=0x%x\n",
+ dp->link_rate, dp->dpcd.max_link_rate);
+ if (calc_link_rate > dp->dpcd.max_link_rate)
+ calc_link_rate = dp->dpcd.max_link_rate;
+ pr_debug("calc_link_rate = 0x%x\n", calc_link_rate);
return calc_link_rate;
}
@@ -1112,6 +1117,84 @@ bool mdss_dp_aux_is_lane_count_valid(u32 lane_count)
(lane_count == DP_LANE_COUNT_4);
}
+int mdss_dp_aux_parse_vx_px(struct mdss_dp_drv_pdata *ep)
+{
+ char *bp;
+ char data;
+ struct edp_buf *rp;
+ int rlen;
+ int const param_len = 0x1;
+ int const addr1 = 0x206;
+ int const addr2 = 0x207;
+ int ret = 0;
+ u32 v0, p0, v1, p1, v2, p2, v3, p3;
+
+ pr_info("Parsing DPCP for updated voltage and pre-emphasis levels\n");
+
+ rlen = dp_aux_read_buf(ep, addr1, param_len, 0);
+ if (rlen < param_len) {
+ pr_err("failed reading lanes 0/1\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ pr_info("lanes 0/1 (Byte 0x206): 0x%x\n", data);
+
+ v0 = data & 0x3;
+ data = data >> 2;
+ p0 = data & 0x3;
+ data = data >> 2;
+
+ v1 = data & 0x3;
+ data = data >> 2;
+ p1 = data & 0x3;
+ data = data >> 2;
+
+ rlen = dp_aux_read_buf(ep, addr2, param_len, 0);
+ if (rlen < param_len) {
+ pr_err("failed reading lanes 2/3\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ pr_info("lanes 2/3 (Byte 0x207): 0x%x\n", data);
+
+ v2 = data & 0x3;
+ data = data >> 2;
+ p2 = data & 0x3;
+ data = data >> 2;
+
+ v3 = data & 0x3;
+ data = data >> 2;
+ p3 = data & 0x3;
+ data = data >> 2;
+
+ pr_info("vx: 0=%d, 1=%d, 2=%d, 3=%d\n", v0, v1, v2, v3);
+ pr_info("px: 0=%d, 1=%d, 2=%d, 3=%d\n", p0, p1, p2, p3);
+
+ /**
+ * Update the voltage and pre-emphasis levels as per DPCD request
+ * vector.
+ */
+ pr_info("Current: v_level = 0x%x, p_level = 0x%x\n",
+ ep->v_level, ep->p_level);
+ pr_info("Requested: v_level = 0x%x, p_level = 0x%x\n", v0, p0);
+ ep->v_level = v0;
+ ep->p_level = p0;
+
+ pr_info("Success\n");
+end:
+ return ret;
+}
+
/**
* dp_parse_link_training_params() - parses link training parameters from DPCD
* @ep: Display Port Driver data
@@ -1212,6 +1295,236 @@ static void dp_sink_parse_sink_count(struct mdss_dp_drv_pdata *ep)
ep->sink_count.count, ep->sink_count.cp_ready);
}
+static int dp_get_test_period(struct mdss_dp_drv_pdata *ep, int const addr)
+{
+ int ret = 0;
+ char *bp;
+ char data;
+ struct edp_buf *rp;
+ int rlen;
+ int const test_parameter_len = 0x1;
+ int const max_audio_period = 0xA;
+
+ /* TEST_AUDIO_PERIOD_CH_XX */
+ rlen = dp_aux_read_buf(ep, addr, test_parameter_len, 0);
+ if (rlen < test_parameter_len) {
+ pr_err("failed to read test_audio_period (0x%x)\n", addr);
+ ret = -EINVAL;
+ goto exit;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ /* Period - Bits 3:0 */
+ data = data & 0xF;
+ if ((int)data > max_audio_period) {
+ pr_err("invalid test_audio_period_ch_1 = 0x%x\n", data);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = data;
+
+exit:
+ return ret;
+}
+
+static int dp_parse_audio_channel_test_period(struct mdss_dp_drv_pdata *ep)
+{
+ int ret = 0;
+ int const test_audio_period_ch_1_addr = 0x273;
+ int const test_audio_period_ch_2_addr = 0x274;
+ int const test_audio_period_ch_3_addr = 0x275;
+ int const test_audio_period_ch_4_addr = 0x276;
+ int const test_audio_period_ch_5_addr = 0x277;
+ int const test_audio_period_ch_6_addr = 0x278;
+ int const test_audio_period_ch_7_addr = 0x279;
+ int const test_audio_period_ch_8_addr = 0x27A;
+
+ /* TEST_AUDIO_PERIOD_CH_1 (Byte 0x273) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_1_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_1 = ret;
+ pr_debug("test_audio_period_ch_1 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_2 (Byte 0x274) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_2_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_2 = ret;
+ pr_debug("test_audio_period_ch_2 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_3_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_3 = ret;
+ pr_debug("test_audio_period_ch_3 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_4 (Byte 0x276) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_4_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_4 = ret;
+ pr_debug("test_audio_period_ch_4 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_5 (Byte 0x277) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_5_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_5 = ret;
+ pr_debug("test_audio_period_ch_5 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_6 (Byte 0x278) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_6_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_6 = ret;
+ pr_debug("test_audio_period_ch_6 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_7 (Byte 0x279) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_7_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_7 = ret;
+ pr_debug("test_audio_period_ch_7 = 0x%x\n", ret);
+
+ /* TEST_AUDIO_PERIOD_CH_8 (Byte 0x27A) */
+ ret = dp_get_test_period(ep, test_audio_period_ch_8_addr);
+ if (ret == -EINVAL)
+ goto exit;
+
+ ep->test_data.test_audio_period_ch_8 = ret;
+ pr_debug("test_audio_period_ch_8 = 0x%x\n", ret);
+
+
+exit:
+ return ret;
+}
+
+static int dp_parse_audio_pattern_type(struct mdss_dp_drv_pdata *ep)
+{
+ int ret = 0;
+ char *bp;
+ char data;
+ struct edp_buf *rp;
+ int rlen;
+ int const test_parameter_len = 0x1;
+ int const test_audio_pattern_type_addr = 0x272;
+ int const max_audio_pattern_type = 0x1;
+
+ /* Read the requested audio pattern type (Byte 0x272). */
+ rlen = dp_aux_read_buf(ep, test_audio_pattern_type_addr,
+ test_parameter_len, 0);
+ if (rlen < test_parameter_len) {
+ pr_err("failed to read test audio mode data\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ /* Audio Pattern Type - Bits 7:0 */
+ if ((int)data > max_audio_pattern_type) {
+ pr_err("invalid audio pattern type = 0x%x\n", data);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ep->test_data.test_audio_pattern_type = data;
+ pr_debug("audio pattern type = %s\n",
+ mdss_dp_get_audio_test_pattern(data));
+
+exit:
+ return ret;
+}
+
+static int dp_parse_audio_mode(struct mdss_dp_drv_pdata *ep)
+{
+ int ret = 0;
+ char *bp;
+ char data;
+ struct edp_buf *rp;
+ int rlen;
+ int const test_parameter_len = 0x1;
+ int const test_audio_mode_addr = 0x271;
+ int const max_audio_sampling_rate = 0x6;
+ int const max_audio_channel_count = 0x8;
+ int sampling_rate = 0x0;
+ int channel_count = 0x0;
+
+ /* Read the requested audio mode (Byte 0x271). */
+ rlen = dp_aux_read_buf(ep, test_audio_mode_addr,
+ test_parameter_len, 0);
+ if (rlen < test_parameter_len) {
+ pr_err("failed to read test audio mode data\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ /* Sampling Rate - Bits 3:0 */
+ sampling_rate = data & 0xF;
+ if (sampling_rate > max_audio_sampling_rate) {
+ pr_err("sampling rate (0x%x) greater than max (0x%x)\n",
+ sampling_rate, max_audio_sampling_rate);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /* Channel Count - Bits 7:4 */
+ channel_count = ((data & 0xF0) >> 4) + 1;
+ if (channel_count > max_audio_channel_count) {
+ pr_err("channel_count (0x%x) greater than max (0x%x)\n",
+ channel_count, max_audio_channel_count);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ep->test_data.test_audio_sampling_rate = sampling_rate;
+ ep->test_data.test_audio_channel_count = channel_count;
+ pr_debug("sampling_rate = %s, channel_count = 0x%x\n",
+ mdss_dp_get_audio_sample_rate(sampling_rate), channel_count);
+
+exit:
+ return ret;
+}
+
+/**
+ * dp_parse_audio_pattern_params() - parses audio pattern parameters from DPCD
+ * @ep: Display Port Driver data
+ *
+ * Returns 0 if it successfully parses the audio test pattern parameters.
+ */
+static int dp_parse_audio_pattern_params(struct mdss_dp_drv_pdata *ep)
+{
+ int ret = 0;
+
+ ret = dp_parse_audio_mode(ep);
+ if (ret)
+ goto exit;
+
+ ret = dp_parse_audio_pattern_type(ep);
+ if (ret)
+ goto exit;
+
+ ret = dp_parse_audio_channel_test_period(ep);
+
+exit:
+ return ret;
+}
/**
* dp_parse_phy_test_params() - parses the phy test parameters
* @ep: Display Port Driver data
@@ -1227,7 +1540,6 @@ static int dp_parse_phy_test_params(struct mdss_dp_drv_pdata *ep)
int rlen;
int const param_len = 0x1;
int const phy_test_pattern_addr = 0x248;
- int const dpcd_version_1_2 = 0x12;
int ret = 0;
rlen = dp_aux_read_buf(ep, phy_test_pattern_addr, param_len, 0);
@@ -1241,11 +1553,6 @@ static int dp_parse_phy_test_params(struct mdss_dp_drv_pdata *ep)
bp = rp->data;
data = *bp++;
- if (ep->dpcd.major == dpcd_version_1_2)
- data = data & 0x7;
- else
- data = data & 0x3;
-
ep->test_data.phy_test_pattern_sel = data;
pr_debug("phy_test_pattern_sel = %s\n",
@@ -1258,6 +1565,256 @@ end:
return ret;
}
+static int dp_parse_test_timing_params1(struct mdss_dp_drv_pdata *ep,
+ int const addr, int const len, u32 *val)
+{
+ char *bp;
+ struct edp_buf *rp;
+ int rlen;
+
+ if (len < 2)
+ return -EINVAL;
+
+ /* Read the requested video test pattern (Byte 0x221). */
+ rlen = dp_aux_read_buf(ep, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read 0x%x\n", addr);
+ return -EINVAL;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+
+ *val = bp[1] | (bp[0] << 8);
+
+ return 0;
+}
+
+static int dp_parse_test_timing_params2(struct mdss_dp_drv_pdata *ep,
+ int const addr, int const len, u32 *val1, u32 *val2)
+{
+ char *bp;
+ struct edp_buf *rp;
+ int rlen;
+
+ if (len < 2)
+ return -EINVAL;
+
+ /* Read the requested video test pattern (Byte 0x221). */
+ rlen = dp_aux_read_buf(ep, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read 0x%x\n", addr);
+ return -EINVAL;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+
+ *val1 = (bp[0] & BIT(7)) >> 7;
+ *val2 = bp[1] | ((bp[0] & 0x7F) << 8);
+
+ return 0;
+}
+
+static int dp_parse_test_timing_params3(struct mdss_dp_drv_pdata *ep,
+ int const addr, u32 *val)
+{
+ char *bp;
+ struct edp_buf *rp;
+ int rlen;
+
+ /* Read the requested video test pattern (Byte 0x221). */
+ rlen = dp_aux_read_buf(ep, addr, 1, 0);
+ if (rlen < 1) {
+ pr_err("failed to read 0x%x\n", addr);
+ return -EINVAL;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ *val = bp[0];
+
+ return 0;
+}
+
+/**
+ * dp_parse_video_pattern_params() - parses video pattern parameters from DPCD
+ * @ep: Display Port Driver data
+ *
+ * Returns 0 if it successfully parses the video test pattern and the test
+ * bit depth requested by the sink and, and if the values parsed are valid.
+ */
+static int dp_parse_video_pattern_params(struct mdss_dp_drv_pdata *ep)
+{
+ int ret = 0;
+ char *bp;
+ char data;
+ struct edp_buf *rp;
+ int rlen;
+ u32 dyn_range;
+ int const test_parameter_len = 0x1;
+ int const test_video_pattern_addr = 0x221;
+ int const test_misc_addr = 0x232;
+
+ /* Read the requested video test pattern (Byte 0x221). */
+ rlen = dp_aux_read_buf(ep, test_video_pattern_addr,
+ test_parameter_len, 0);
+ if (rlen < test_parameter_len) {
+ pr_err("failed to read test video pattern\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ if (!mdss_dp_is_test_video_pattern_valid(data)) {
+ pr_err("invalid test video pattern = 0x%x\n", data);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ep->test_data.test_video_pattern = data;
+ pr_debug("test video pattern = 0x%x (%s)\n",
+ ep->test_data.test_video_pattern,
+ mdss_dp_test_video_pattern_to_string(
+ ep->test_data.test_video_pattern));
+
+ /* Read the requested color bit depth and dynamic range (Byte 0x232) */
+ rlen = dp_aux_read_buf(ep, test_misc_addr, test_parameter_len, 0);
+ if (rlen < test_parameter_len) {
+ pr_err("failed to read test bit depth\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ data = *bp++;
+
+ /* Dynamic Range */
+ dyn_range = (data & BIT(3)) >> 3;
+ if (!mdss_dp_is_dynamic_range_valid(dyn_range)) {
+ pr_err("invalid test dynamic range = 0x%x", dyn_range);
+ ret = -EINVAL;
+ goto exit;
+ }
+ ep->test_data.test_dyn_range = dyn_range;
+ pr_debug("test dynamic range = 0x%x (%s)\n",
+ ep->test_data.test_dyn_range,
+ mdss_dp_dynamic_range_to_string(ep->test_data.test_dyn_range));
+
+ /* Color bit depth */
+ data &= (BIT(5) | BIT(6) | BIT(7));
+ data >>= 5;
+ if (!mdss_dp_is_test_bit_depth_valid(data)) {
+ pr_err("invalid test bit depth = 0x%x\n", data);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ep->test_data.test_bit_depth = data;
+ pr_debug("test bit depth = 0x%x (%s)\n",
+ ep->test_data.test_bit_depth,
+ mdss_dp_test_bit_depth_to_string(ep->test_data.test_bit_depth));
+
+ /* resolution timing params */
+ ret = dp_parse_test_timing_params1(ep, 0x222, 2,
+ &ep->test_data.test_h_total);
+ if (ret) {
+ pr_err("failed to parse test_h_total (0x222)\n");
+ goto exit;
+ }
+ pr_debug("TEST_H_TOTAL = %d\n", ep->test_data.test_h_total);
+
+ ret = dp_parse_test_timing_params1(ep, 0x224, 2,
+ &ep->test_data.test_v_total);
+ if (ret) {
+ pr_err("failed to parse test_v_total (0x224)\n");
+ goto exit;
+ }
+ pr_debug("TEST_V_TOTAL = %d\n", ep->test_data.test_v_total);
+
+ ret = dp_parse_test_timing_params1(ep, 0x226, 2,
+ &ep->test_data.test_h_start);
+ if (ret) {
+ pr_err("failed to parse test_h_start (0x226)\n");
+ goto exit;
+ }
+ pr_debug("TEST_H_START = %d\n", ep->test_data.test_h_start);
+
+ ret = dp_parse_test_timing_params1(ep, 0x228, 2,
+ &ep->test_data.test_v_start);
+ if (ret) {
+ pr_err("failed to parse test_v_start (0x228)\n");
+ goto exit;
+ }
+ pr_debug("TEST_V_START = %d\n", ep->test_data.test_v_start);
+
+ ret = dp_parse_test_timing_params2(ep, 0x22A, 2,
+ &ep->test_data.test_hsync_pol,
+ &ep->test_data.test_hsync_width);
+ if (ret) {
+ pr_err("failed to parse (0x22A)\n");
+ goto exit;
+ }
+ pr_debug("TEST_HSYNC_POL = %d\n", ep->test_data.test_hsync_pol);
+ pr_debug("TEST_HSYNC_WIDTH = %d\n", ep->test_data.test_hsync_width);
+
+ ret = dp_parse_test_timing_params2(ep, 0x22C, 2,
+ &ep->test_data.test_vsync_pol,
+ &ep->test_data.test_vsync_width);
+ if (ret) {
+ pr_err("failed to parse (0x22C)\n");
+ goto exit;
+ }
+ pr_debug("TEST_VSYNC_POL = %d\n", ep->test_data.test_vsync_pol);
+ pr_debug("TEST_VSYNC_WIDTH = %d\n", ep->test_data.test_vsync_width);
+
+ ret = dp_parse_test_timing_params1(ep, 0x22E, 2,
+ &ep->test_data.test_h_width);
+ if (ret) {
+ pr_err("failed to parse test_h_width (0x22E)\n");
+ goto exit;
+ }
+ pr_debug("TEST_H_WIDTH = %d\n", ep->test_data.test_h_width);
+
+ ret = dp_parse_test_timing_params1(ep, 0x230, 2,
+ &ep->test_data.test_v_height);
+ if (ret) {
+ pr_err("failed to parse test_v_height (0x230)\n");
+ goto exit;
+ }
+ pr_debug("TEST_V_HEIGHT = %d\n", ep->test_data.test_v_height);
+
+ ret = dp_parse_test_timing_params3(ep, 0x233, &ep->test_data.test_rr_d);
+ ep->test_data.test_rr_d &= BIT(0);
+ if (ret) {
+ pr_err("failed to parse test_rr_d (0x233)\n");
+ goto exit;
+ }
+ pr_debug("TEST_REFRESH_DENOMINATOR = %d\n", ep->test_data.test_rr_d);
+
+ ret = dp_parse_test_timing_params3(ep, 0x234, &ep->test_data.test_rr_n);
+ if (ret) {
+ pr_err("failed to parse test_rr_n (0x234)\n");
+ goto exit;
+ }
+ pr_debug("TEST_REFRESH_NUMERATOR = %d\n", ep->test_data.test_rr_n);
+
+exit:
+ return ret;
+}
+
+/**
+ * mdss_dp_is_video_audio_test_requested() - checks for audio/video test request
+ * @test: test requested by the sink
+ *
+ * Returns true if the requested test is a permitted audio/video test.
+ */
+static bool mdss_dp_is_video_audio_test_requested(u32 test)
+{
+ return (test == TEST_VIDEO_PATTERN) ||
+ (test == (TEST_AUDIO_PATTERN | TEST_VIDEO_PATTERN)) ||
+ (test == TEST_AUDIO_PATTERN) ||
+ (test == (TEST_AUDIO_PATTERN | TEST_AUDIO_DISABLED_VIDEO));
+}
/**
* dp_is_test_supported() - checks if test requested by sink is supported
@@ -1269,7 +1826,8 @@ static bool dp_is_test_supported(u32 test_requested)
{
return (test_requested == TEST_LINK_TRAINING) ||
(test_requested == TEST_EDID_READ) ||
- (test_requested == PHY_TEST_PATTERN);
+ (test_requested == PHY_TEST_PATTERN) ||
+ mdss_dp_is_video_audio_test_requested(test_requested);
}
/**
@@ -1289,6 +1847,7 @@ static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep)
int const test_parameter_len = 0x1;
int const device_service_irq_addr = 0x201;
int const test_request_addr = 0x218;
+ char buf[4];
/**
* Read the device service IRQ vector (Byte 0x201) to determine
@@ -1330,23 +1889,31 @@ static void dp_sink_parse_test_request(struct mdss_dp_drv_pdata *ep)
return;
}
- pr_debug("%s requested\n", mdss_dp_get_test_name(data));
+ pr_debug("%s (0x%x) requested\n", mdss_dp_get_test_name(data), data);
ep->test_data.test_requested = data;
- switch (ep->test_data.test_requested) {
- case PHY_TEST_PATTERN:
+ if (ep->test_data.test_requested == PHY_TEST_PATTERN) {
ret = dp_parse_phy_test_params(ep);
if (ret)
- break;
- case TEST_LINK_TRAINING:
+ goto end;
ret = dp_parse_link_training_params(ep);
- break;
- default:
- pr_debug("test 0x%x not supported\n",
- ep->test_data.test_requested);
- return;
}
+ if (ep->test_data.test_requested == TEST_LINK_TRAINING)
+ ret = dp_parse_link_training_params(ep);
+
+ if (mdss_dp_is_video_audio_test_requested(
+ ep->test_data.test_requested)) {
+ ret = dp_parse_video_pattern_params(ep);
+ if (ret)
+ goto end;
+ ret = dp_parse_audio_pattern_params(ep);
+ }
+end:
+ /* clear the test request IRQ */
+ buf[0] = 1;
+ dp_aux_write_buf(ep, test_request_addr, buf, 1, 0);
+
/**
* Send a TEST_ACK if all test parameters are valid, otherwise send
* a TEST_NACK.
@@ -1568,7 +2135,7 @@ char vm_voltage_swing[4][4] = {
{0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
};
-static void dp_aux_set_voltage_and_pre_emphasis_lvl(
+void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
struct mdss_dp_drv_pdata *dp)
{
u32 value0 = 0;
@@ -1605,45 +2172,13 @@ static void dp_aux_set_voltage_and_pre_emphasis_lvl(
QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL,
value1);
- pr_debug("value0=0x%x value1=0x%x",
+ pr_debug("host PHY settings: value0=0x%x value1=0x%x",
value0, value1);
dp_lane_set_write(dp, dp->v_level, dp->p_level);
}
}
-/**
- * mdss_dp_aux_update_voltage_and_pre_emphasis_lvl() - updates DP PHY settings
- * @ep: Display Port Driver data
- *
- * Updates the DP PHY with the requested voltage swing and pre-emphasis
- * levels if they are different from the current settings.
- */
-void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
- struct mdss_dp_drv_pdata *dp)
-{
- int const num_bytes = 6;
- struct dpcd_link_status *status = &dp->link_status;
-
- /* Read link status for updated voltage and pre-emphasis levels. */
- mdss_dp_aux_link_status_read(dp, num_bytes);
-
- pr_info("Current: v_level = %d, p_level = %d\n",
- dp->v_level, dp->p_level);
- pr_info("Requested: v_level = %d, p_level = %d\n",
- status->req_voltage_swing[0],
- status->req_pre_emphasis[0]);
-
- if ((status->req_voltage_swing[0] != dp->v_level) ||
- (status->req_pre_emphasis[0] != dp->p_level)) {
- dp->v_level = status->req_voltage_swing[0];
- dp->p_level = status->req_pre_emphasis[0];
-
- dp_aux_set_voltage_and_pre_emphasis_lvl(dp);
- }
-
- pr_debug("end\n");
-}
static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
{
int tries, old_v_level;
@@ -1653,10 +2188,14 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
pr_debug("Entered++");
+ dp_write(ep->base + DP_STATE_CTRL, 0x0);
+ /* Make sure to clear the current pattern before starting a new one */
+ wmb();
+
+ dp_host_train_set(ep, 0x01); /* train_1 */
dp_cap_lane_rate_set(ep);
dp_train_pattern_set_write(ep, 0x21); /* train_1 */
- dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
- dp_host_train_set(ep, 0x01); /* train_1 */
+ mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
tries = 0;
old_v_level = ep->v_level;
@@ -1687,7 +2226,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
}
dp_sink_train_set_adjust(ep);
- dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
+ mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
}
return ret;
@@ -1708,11 +2247,15 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
else
pattern = 0x02;
+ dp_write(ep->base + DP_STATE_CTRL, 0x0);
+ /* Make sure to clear the current pattern before starting a new one */
+ wmb();
+
+ dp_host_train_set(ep, pattern);
+ mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
dp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
do {
- dp_host_train_set(ep, pattern);
-
usleep_time = ep->dpcd.training_read_interval;
usleep_range(usleep_time, usleep_time);
@@ -1723,14 +2266,14 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
break;
}
- tries++;
if (tries > maximum_retries) {
ret = -1;
break;
}
+ tries++;
dp_sink_train_set_adjust(ep);
- dp_aux_set_voltage_and_pre_emphasis_lvl(ep);
+ mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(ep);
} while (1);
return ret;
@@ -1787,25 +2330,20 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
ret = dp_aux_chan_ready(dp);
if (ret) {
pr_err("LINK Train failed: aux chan NOT ready\n");
- complete(&dp->train_comp);
return ret;
}
- dp_write(dp->base + DP_MAINLINK_CTRL, 0x1);
-
- mdss_dp_aux_set_sink_power_state(dp, SINK_POWER_ON);
-
dp->v_level = 0; /* start from default level */
dp->p_level = 0;
mdss_dp_config_ctrl(dp);
mdss_dp_state_ctrl(&dp->ctrl_io, 0);
- dp_clear_training_pattern(dp);
ret = dp_start_link_train_1(dp);
if (ret < 0) {
if (!dp_link_rate_down_shift(dp)) {
pr_debug("retry with lower rate\n");
+ dp_clear_training_pattern(dp);
return -EAGAIN;
} else {
pr_err("Training 1 failed\n");
@@ -1816,10 +2354,15 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
pr_debug("Training 1 completed successfully\n");
+ dp_write(dp->base + DP_STATE_CTRL, 0x0);
+ /* Make sure to clear the current pattern before starting a new one */
+ wmb();
+
ret = dp_start_link_train_2(dp);
if (ret < 0) {
if (!dp_link_rate_down_shift(dp)) {
pr_debug("retry with lower rate\n");
+ dp_clear_training_pattern(dp);
return -EAGAIN;
} else {
pr_err("Training 2 failed\n");
@@ -1830,19 +2373,13 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
pr_debug("Training 2 completed successfully\n");
+ dp_write(dp->base + DP_STATE_CTRL, 0x0);
+ /* Make sure to clear the current pattern before starting a new one */
+ wmb();
+
clear:
dp_clear_training_pattern(dp);
- if (ret != -EINVAL) {
- mdss_dp_config_misc_settings(&dp->ctrl_io,
- &dp->panel_data.panel_info);
- mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate,
- dp->lane_cnt, dp->vic,
- &dp->panel_data.panel_info);
- mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
- pr_debug("State_ctrl set to SEND_VIDEO\n");
- }
- complete(&dp->train_comp);
return ret;
}
@@ -1885,15 +2422,129 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep)
}
+/**
+ * mdss_dp_aux_config_sink_frame_crc() - enable/disable per frame CRC calc
+ * @dp: Display Port Driver data
+ * @enable: true - start CRC calculation, false - stop CRC calculation
+ *
+ * Program the sink DPCD register 0x270 to start/stop CRC calculation.
+ * This would take effect with the next frame.
+ */
+int mdss_dp_aux_config_sink_frame_crc(struct mdss_dp_drv_pdata *dp,
+ bool enable)
+{
+ int rlen;
+ struct edp_buf *rp;
+ u8 *bp;
+ u8 buf[4];
+ u8 crc_supported;
+ u32 const test_sink_addr = 0x270;
+ u32 const test_sink_misc_addr = 0x246;
+
+ if (dp->sink_crc.en == enable) {
+ pr_debug("sink crc already %s\n",
+ enable ? "enabled" : "disabled");
+ return 0;
+ }
+
+ rlen = dp_aux_read_buf(dp, test_sink_misc_addr, 1, 0);
+ if (rlen < 1) {
+ pr_err("failed to TEST_SINK_ADDR\n");
+ return -EPERM;
+ }
+ rp = &dp->rxp;
+ bp = rp->data;
+ crc_supported = bp[0] & BIT(5);
+ pr_debug("crc supported=%s\n", crc_supported ? "true" : "false");
+
+ if (!crc_supported) {
+ pr_err("sink does not support CRC generation\n");
+ return -EINVAL;
+ }
+
+ buf[0] = enable ? 1 : 0;
+ dp_aux_write_buf(dp, test_sink_addr, buf, BIT(0), 0);
+
+ if (!enable)
+ mdss_dp_reset_frame_crc_data(&dp->sink_crc);
+ dp->sink_crc.en = enable;
+ pr_debug("TEST_SINK_START (CRC calculation) %s\n",
+ enable ? "enabled" : "disabled");
+
+ return 0;
+}
+
+/**
+ * mdss_dp_aux_read_sink_frame_crc() - read frame CRC values from the sink
+ * @dp: Display Port Driver data
+ */
+int mdss_dp_aux_read_sink_frame_crc(struct mdss_dp_drv_pdata *dp)
+{
+ int rlen;
+ struct edp_buf *rp;
+ u8 *bp;
+ u32 addr, len;
+ struct mdss_dp_crc_data *crc = &dp->sink_crc;
+
+ addr = 0x270; /* TEST_SINK */
+ len = 1; /* one byte */
+ rlen = dp_aux_read_buf(dp, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read TEST SINK\n");
+ return -EPERM;
+ }
+ rp = &dp->rxp;
+ bp = rp->data;
+ if (!(bp[0] & BIT(0))) {
+ pr_err("Sink side CRC calculation not enabled, TEST_SINK=0x%08x\n",
+ (u32)bp[0]);
+ return -EINVAL;
+ }
+
+ addr = 0x240; /* TEST_CRC_R_Cr */
+ len = 2; /* 2 bytes */
+ rlen = dp_aux_read_buf(dp, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read TEST_CRC_R_Cr\n");
+ return -EPERM;
+ }
+ rp = &dp->rxp;
+ bp = rp->data;
+ crc->r_cr = bp[0] | (bp[1] << 8);
+
+ addr = 0x242; /* TEST_CRC_G_Y */
+ len = 2; /* 2 bytes */
+ rlen = dp_aux_read_buf(dp, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read TEST_CRC_G_Y\n");
+ return -EPERM;
+ }
+ rp = &dp->rxp;
+ bp = rp->data;
+ crc->g_y = bp[0] | (bp[1] << 8);
+
+ addr = 0x244; /* TEST_CRC_B_Cb */
+ len = 2; /* 2 bytes */
+ rlen = dp_aux_read_buf(dp, addr, len, 0);
+ if (rlen < len) {
+ pr_err("failed to read TEST_CRC_B_Cb\n");
+ return -EPERM;
+ }
+ rp = &dp->rxp;
+ bp = rp->data;
+ crc->b_cb = bp[0] | (bp[1] << 8);
+
+ pr_debug("r_cr=0x%08x\t g_y=0x%08x\t b_cb=0x%08x\n",
+ crc->r_cr, crc->g_y, crc->b_cb);
+
+ return 0;
+}
+
void mdss_dp_aux_init(struct mdss_dp_drv_pdata *ep)
{
- mutex_init(&ep->aux_mutex);
- mutex_init(&ep->train_mutex);
- init_completion(&ep->aux_comp);
- init_completion(&ep->train_comp);
- init_completion(&ep->idle_comp);
- init_completion(&ep->video_comp);
- complete(&ep->train_comp); /* make non block at first time */
+ reinit_completion(&ep->aux_comp);
+ reinit_completion(&ep->idle_comp);
+ reinit_completion(&ep->video_comp);
complete(&ep->video_comp); /* make non block at first time */
dp_buf_init(&ep->txp, ep->txbuf, sizeof(ep->txbuf));
diff --git a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
index 73b9ad65482f..3bcacf945761 100644
--- a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -370,6 +370,8 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
dp_hdcp2p2_set_interrupts(ctrl, false);
+ atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
+
/* notify DP about HDCP failure */
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
HDCP_STATE_AUTH_FAIL);
@@ -625,6 +627,12 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work)
return;
}
+ if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
+ atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+ pr_err("invalid hdcp state\n");
+ return;
+ }
+
cdata.context = ctrl->lib_ctx;
if (ctrl->sink_rx_status & ctrl->abort_mask) {
@@ -685,6 +693,13 @@ static int dp_hdcp2p2_cp_irq(void *input)
return -EINVAL;
}
+ if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
+ atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+ pr_err("invalid hdcp state\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
ctrl->sink_rx_status = 0;
rc = mdss_dp_aux_read_rx_status(ctrl->init_data.cb_data,
&ctrl->sink_rx_status);
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index a7f42ba8c261..1dcf83f094c1 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -202,6 +202,45 @@ void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data)
writel_relaxed(data, ctrl_io->base + DP_CONFIGURATION_CTRL);
}
+void mdss_dp_config_ctl_frame_crc(struct mdss_dp_drv_pdata *dp, bool enable)
+{
+ if (dp->ctl_crc.en == enable) {
+ pr_debug("CTL crc already %s\n",
+ enable ? "enabled" : "disabled");
+ return;
+ }
+
+ writel_relaxed(BIT(8), dp->ctrl_io.base + MMSS_DP_TIMING_ENGINE_EN);
+ if (!enable)
+ mdss_dp_reset_frame_crc_data(&dp->ctl_crc);
+ dp->ctl_crc.en = enable;
+
+ pr_debug("CTL crc %s\n", enable ? "enabled" : "disabled");
+}
+
+int mdss_dp_read_ctl_frame_crc(struct mdss_dp_drv_pdata *dp)
+{
+ u32 data;
+ u32 crc_rg = 0;
+ struct mdss_dp_crc_data *crc = &dp->ctl_crc;
+
+ data = readl_relaxed(dp->ctrl_io.base + MMSS_DP_TIMING_ENGINE_EN);
+ if (!(data & BIT(8))) {
+ pr_debug("frame CRC calculation not enabled\n");
+ return -EPERM;
+ }
+
+ crc_rg = readl_relaxed(dp->ctrl_io.base + MMSS_DP_PSR_CRC_RG);
+ crc->r_cr = crc_rg & 0xFFFF;
+ crc->g_y = crc_rg >> 16;
+ crc->b_cb = readl_relaxed(dp->ctrl_io.base + MMSS_DP_PSR_CRC_B);
+
+ pr_debug("r_cr=0x%08x\t g_y=0x%08x\t b_cb=0x%08x\n",
+ crc->r_cr, crc->g_y, crc->b_cb);
+
+ return 0;
+}
+
/* DP state controller*/
void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data)
{
@@ -735,7 +774,9 @@ void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io,
data = pinfo->lcdc.v_pulse_width;
data <<= 16;
+ data |= (pinfo->lcdc.v_active_low << 31);
data |= pinfo->lcdc.h_pulse_width;
+ data |= (pinfo->lcdc.h_active_low << 15);
/* DP_HSYNC_VSYNC_WIDTH_POLARITY */
writel_relaxed(data, ctrl_io->base + DP_HSYNC_VSYNC_WIDTH_POLARITY);
@@ -765,28 +806,15 @@ void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io,
writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID);
}
-void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
- struct mdss_panel_info *pinfo)
+void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc)
{
- u32 bpp = pinfo->bpp;
- u32 misc_val = 0x0;
-
- switch (bpp) {
- case 18:
- misc_val |= (0x0 << 5);
- break;
- case 30:
- misc_val |= (0x2 << 5);
- break;
- case 24:
- default:
- misc_val |= (0x1 << 5);
- }
+ u32 misc_val = cc;
+ misc_val |= (bd << 5);
misc_val |= BIT(0); /* Configure clock to synchronous mode */
pr_debug("Misc settings = 0x%x\n", misc_val);
- writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0);
+ writel_relaxed(misc_val, dp->ctrl_io.base + DP_MISC1_MISC0);
}
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
@@ -1113,7 +1141,8 @@ static u8 mdss_dp_calculate_parity_byte(u32 data)
return parityByte;
}
-static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
+static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io,
+ u32 num_of_channels)
{
u32 value = 0;
u32 new_value = 0;
@@ -1131,7 +1160,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
/* Config header and parity byte 2 */
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
- new_value = 0x0;
+ new_value = value;
parity_byte = mdss_dp_calculate_parity_byte(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
@@ -1141,7 +1170,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
/* Config header and parity byte 3 */
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
- new_value = 0x01;
+ new_value = num_of_channels - 1;
parity_byte = mdss_dp_calculate_parity_byte(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
@@ -1179,7 +1208,7 @@ static void mdss_dp_audio_setup_audio_timestamp_sdp(struct dss_io_data *ctrl_io)
/* Config header and parity byte 3 */
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1);
- new_value = (0x0 | (0x12 << 2));
+ new_value = (0x0 | (0x11 << 2));
parity_byte = mdss_dp_calculate_parity_byte(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
@@ -1216,7 +1245,7 @@ static void mdss_dp_audio_setup_audio_infoframe_sdp(struct dss_io_data *ctrl_io)
/* Config header and parity byte 3 */
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1);
- new_value = (0x0 | (0x12 << 2));
+ new_value = (0x0 | (0x11 << 2));
parity_byte = mdss_dp_calculate_parity_byte(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
@@ -1309,7 +1338,7 @@ static void mdss_dp_audio_setup_isrc_sdp(struct dss_io_data *ctrl_io)
writel_relaxed(0x0, ctrl_io->base + MMSS_DP_AUDIO_ISRC_4);
}
-void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io)
+void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io, u32 num_of_channels)
{
u32 sdp_cfg = 0;
u32 sdp_cfg2 = 0;
@@ -1335,7 +1364,7 @@ void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io)
writel_relaxed(sdp_cfg2, ctrl_io->base + MMSS_DP_SDP_CFG2);
- mdss_dp_audio_setup_audio_stream_sdp(ctrl_io);
+ mdss_dp_audio_setup_audio_stream_sdp(ctrl_io, num_of_channels);
mdss_dp_audio_setup_audio_timestamp_sdp(ctrl_io);
mdss_dp_audio_setup_audio_infoframe_sdp(ctrl_io);
mdss_dp_audio_setup_copy_management_sdp(ctrl_io);
@@ -1366,7 +1395,7 @@ void mdss_dp_set_safe_to_exit_level(struct dss_io_data *ctrl_io,
}
mainlink_levels = readl_relaxed(ctrl_io->base + DP_MAINLINK_LEVELS);
- mainlink_levels &= 0xFF0;
+ mainlink_levels &= 0xFE0;
mainlink_levels |= safe_to_exit_level;
pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
@@ -1406,28 +1435,17 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
return;
}
- /* Disable mainlink */
- writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
-
- /* Reset mainlink */
- mdss_dp_mainlink_reset(io);
-
- /* Enable mainlink */
- writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
-
/* Initialize DP state control */
- mdss_dp_state_ctrl(io, 0x00);
+ writel_relaxed(0x0, io->base + DP_STATE_CTRL);
pr_debug("phy_test_pattern_sel = %s\n",
mdss_dp_get_phy_test_pattern(phy_test_pattern_sel));
switch (phy_test_pattern_sel) {
case PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING:
- mdss_dp_state_ctrl(io, BIT(0));
+ writel_relaxed(0x1, io->base + DP_STATE_CTRL);
break;
case PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
- value = readl_relaxed(io->base +
- DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
value &= ~(1 << 16);
writel_relaxed(value, io->base +
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
@@ -1438,7 +1456,7 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
mdss_dp_state_ctrl(io, BIT(4));
break;
case PHY_TEST_PATTERN_PRBS7:
- mdss_dp_state_ctrl(io, BIT(5));
+ writel_relaxed(0x20, io->base + DP_STATE_CTRL);
break;
case PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN:
mdss_dp_state_ctrl(io, BIT(6));
@@ -1453,9 +1471,7 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
DP_TEST_80BIT_CUSTOM_PATTERN_REG2);
break;
case PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN:
- value = readl_relaxed(io->base +
- DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
- value |= BIT(16);
+ value = BIT(16);
writel_relaxed(value, io->base +
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
value |= 0xFC;
@@ -1469,4 +1485,8 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
phy_test_pattern_sel);
return;
}
+
+ value = 0x0;
+ value = readl_relaxed(io->base + DP_MAINLINK_READY);
+ pr_info("DP_MAINLINK_READY = 0x%x\n", value);
}
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index fcb9a77db67c..cb62d145960f 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -65,6 +65,7 @@
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000004C4)
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000004C8)
+#define MMSS_DP_MISC1_MISC0 (0x0000042C)
#define MMSS_DP_AUDIO_TIMING_GEN (0x00000480)
#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000484)
#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000488)
@@ -73,6 +74,9 @@
#define MMSS_DP_AUDIO_TIMING_RBR_48 (0x00000494)
#define MMSS_DP_AUDIO_TIMING_HBR_48 (0x00000498)
+#define MMSS_DP_PSR_CRC_RG (0x00000554)
+#define MMSS_DP_PSR_CRC_B (0x00000558)
+
#define MMSS_DP_AUDIO_CFG (0x00000600)
#define MMSS_DP_AUDIO_STATUS (0x00000604)
#define MMSS_DP_AUDIO_PKT_CTRL (0x00000608)
@@ -135,6 +139,8 @@
#define MMSS_DP_GENERIC1_8 (0x00000748)
#define MMSS_DP_GENERIC1_9 (0x0000074C)
+#define MMSS_DP_TIMING_ENGINE_EN (0x00000A10)
+
/*DP PHY Register offsets */
#define DP_PHY_REVISION_ID0 (0x00000000)
#define DP_PHY_REVISION_ID1 (0x00000004)
@@ -285,8 +291,7 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io);
void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert);
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
u8 ln_cnt, u32 res, struct mdss_panel_info *pinfo);
-void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
- struct mdss_panel_info *pinfo);
+void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc);
void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io);
void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
@@ -312,7 +317,7 @@ void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io,
u8 orientation, u8 ln_cnt);
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,
char link_rate);
-void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io);
+void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io, u32 num_of_channels);
void mdss_dp_audio_enable(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_audio_select_core(struct dss_io_data *ctrl_io);
void mdss_dp_audio_set_sample_rate(struct dss_io_data *ctrl_io,
@@ -321,5 +326,7 @@ void mdss_dp_set_safe_to_exit_level(struct dss_io_data *ctrl_io,
uint32_t lane_cnt);
int mdss_dp_aux_read_rx_status(struct mdss_dp_drv_pdata *dp, u8 *rx_status);
void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp);
+void mdss_dp_config_ctl_frame_crc(struct mdss_dp_drv_pdata *dp, bool enable);
+int mdss_dp_read_ctl_frame_crc(struct mdss_dp_drv_pdata *dp);
#endif /* __DP_UTIL_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 19e3eadfc1b2..51745a9a59ac 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2507,6 +2507,23 @@ static struct device_node *mdss_dsi_get_fb_node_cb(struct platform_device *pdev)
return fb_node;
}
+static void mdss_dsi_timing_db_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
+ int enable)
+{
+ if (!ctrl || !ctrl->timing_db_mode ||
+ (ctrl->shared_data->hw_rev < MDSS_DSI_HW_REV_201))
+ return;
+
+ mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
+ MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_ON);
+ MIPI_OUTP((ctrl->ctrl_base + 0x1e8), enable);
+ wmb(); /* ensure timing db is disabled */
+ MIPI_OUTP((ctrl->ctrl_base + 0x1e4), enable);
+ wmb(); /* ensure timing flush is disabled */
+ mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle,
+ MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_OFF);
+}
+
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -2680,6 +2697,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
&ctrl_pdata->dba_work, HZ);
}
break;
+ case MDSS_EVENT_DSI_TIMING_DB_CTRL:
+ mdss_dsi_timing_db_ctrl(ctrl_pdata, (int)(unsigned long)arg);
+ break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 0574410868bf..df24352ff87d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -58,6 +58,7 @@
#define MDSS_DSI_HW_REV_104_1 0x10040001 /* 8996 */
#define MDSS_DSI_HW_REV_104_2 0x10040002 /* 8937 */
#define MDSS_DSI_HW_REV_200 0x20000000 /* cobalt */
+#define MDSS_DSI_HW_REV_201 0x20010000 /* 660 */
#define MDSS_DSI_HW_REV_STEP_0 0x0
#define MDSS_DSI_HW_REV_STEP_1 0x1
@@ -487,6 +488,8 @@ struct mdss_dsi_ctrl_pdata {
struct dsi_panel_cmds post_dms_on_cmds;
struct dsi_panel_cmds post_panel_on_cmds;
struct dsi_panel_cmds off_cmds;
+ struct dsi_panel_cmds lp_on_cmds;
+ struct dsi_panel_cmds lp_off_cmds;
struct dsi_panel_cmds status_cmds;
u32 *status_valid_params;
u32 *status_cmds_rlen;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 7f6cad3de18e..7cc9ce6e034d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -160,6 +160,27 @@ int mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
}
+static void mdss_dsi_panel_apply_settings(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_panel_cmds *pcmds)
+{
+ struct dcs_cmd_req cmdreq;
+ struct mdss_panel_info *pinfo;
+
+ pinfo = &(ctrl->panel_data.panel_info);
+ if ((pinfo->dcs_cmd_by_left) && (ctrl->ndx != DSI_CTRL_LEFT))
+ return;
+
+ memset(&cmdreq, 0, sizeof(cmdreq));
+ cmdreq.cmds = pcmds->cmds;
+ cmdreq.cmds_cnt = pcmds->cmd_cnt;
+ cmdreq.flags = CMD_REQ_COMMIT;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+
static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_panel_cmds *pcmds, u32 flags)
{
@@ -660,6 +681,38 @@ end:
return 0;
}
+static int mdss_dsi_panel_apply_display_setting(struct mdss_panel_data *pdata,
+ u32 mode)
+{
+ struct mdss_dsi_ctrl_pdata *ctrl = NULL;
+ struct dsi_panel_cmds *lp_on_cmds;
+ struct dsi_panel_cmds *lp_off_cmds;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ lp_on_cmds = &ctrl->lp_on_cmds;
+ lp_off_cmds = &ctrl->lp_off_cmds;
+
+ /* Apply display settings for low-persistence mode */
+ if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_ON) &&
+ (lp_on_cmds->cmd_cnt))
+ mdss_dsi_panel_apply_settings(ctrl, lp_on_cmds);
+ else if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_OFF) &&
+ (lp_on_cmds->cmd_cnt))
+ mdss_dsi_panel_apply_settings(ctrl, lp_off_cmds);
+ else
+ return -EINVAL;
+
+ pr_debug("%s: Persistence mode %d applied\n", __func__, mode);
+ return 0;
+}
+
static void mdss_dsi_panel_switch_mode(struct mdss_panel_data *pdata,
int mode)
{
@@ -822,6 +875,10 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
if (ctrl->ds_registered)
mdss_dba_utils_video_on(pinfo->dba_data, pinfo);
+
+ /* Ensure low persistence mode is set as before */
+ mdss_dsi_panel_apply_display_setting(pdata, pinfo->persist_mode);
+
end:
pr_debug("%s:-\n", __func__);
return ret;
@@ -2046,6 +2103,12 @@ static int mdss_dsi_parse_panel_features(struct device_node *np,
__func__, __LINE__);
}
+ mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_on_cmds,
+ "qcom,mdss-dsi-lp-mode-on", NULL);
+
+ mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_off_cmds,
+ "qcom,mdss-dsi-lp-mode-off", NULL);
+
return 0;
}
@@ -2796,12 +2859,15 @@ int mdss_dsi_panel_init(struct device_node *node,
pinfo->dynamic_switch_pending = false;
pinfo->is_lpm_mode = false;
pinfo->esd_rdy = false;
+ pinfo->persist_mode = false;
ctrl_pdata->on = mdss_dsi_panel_on;
ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
ctrl_pdata->off = mdss_dsi_panel_off;
ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
+ ctrl_pdata->panel_data.apply_display_setting =
+ mdss_dsi_panel_apply_display_setting;
ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
return 0;
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index f20248e13cf8..a183fd7cd247 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1,8 +1,8 @@
/*
* Core MDSS framebuffer driver.
*
+ * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -589,8 +589,8 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
"primary_panel=%d\nis_pluggable=%d\ndisplay_id=%s\n"
"is_cec_supported=%d\nis_pingpong_split=%d\n"
"dfps_porch_mode=%d\npu_roi_cnt=%d\ndual_dsi=%d\n"
- "is_hdr_enabled=%d\n"
- "peak_brightness=%d\nblackness_level=%d\n"
+ "is_hdr_enabled=%d\npeak_brightness=%d\n"
+ "blackness_level=%d\naverage_brightness=%d\n"
"white_chromaticity_x=%d\nwhite_chromaticity_y=%d\n"
"red_chromaticity_x=%d\nred_chromaticity_y=%d\n"
"green_chromaticity_x=%d\ngreen_chromaticity_y=%d\n"
@@ -612,6 +612,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
is_panel_split(mfd), pinfo->hdr_properties.hdr_enabled,
pinfo->hdr_properties.peak_brightness,
pinfo->hdr_properties.blackness_level,
+ pinfo->hdr_properties.avg_brightness,
pinfo->hdr_properties.display_primaries[0],
pinfo->hdr_properties.display_primaries[1],
pinfo->hdr_properties.display_primaries[2],
@@ -823,6 +824,74 @@ static ssize_t mdss_fb_get_dfps_mode(struct device *dev,
return ret;
}
+static ssize_t mdss_fb_change_persist_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ struct mdss_panel_info *pinfo = NULL;
+ struct mdss_panel_data *pdata;
+ int ret = 0;
+ u32 persist_mode;
+
+ if (!mfd || !mfd->panel_info) {
+ pr_err("%s: Panel info is NULL!\n", __func__);
+ return len;
+ }
+
+ pinfo = mfd->panel_info;
+
+ if (kstrtouint(buf, 0, &persist_mode)) {
+ pr_err("kstrtouint buf error!\n");
+ return len;
+ }
+
+ mutex_lock(&mfd->mdss_sysfs_lock);
+ if (mdss_panel_is_power_off(mfd->panel_power_state)) {
+ pinfo->persist_mode = persist_mode;
+ goto end;
+ }
+
+ mutex_lock(&mfd->bl_lock);
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if ((pdata) && (pdata->apply_display_setting))
+ ret = pdata->apply_display_setting(pdata, persist_mode);
+
+ mutex_unlock(&mfd->bl_lock);
+
+ if (!ret) {
+ pr_debug("%s: Persist mode %d\n", __func__, persist_mode);
+ pinfo->persist_mode = persist_mode;
+ }
+
+end:
+ mutex_unlock(&mfd->mdss_sysfs_lock);
+
+ return len;
+}
+
+static ssize_t mdss_fb_get_persist_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ struct mdss_panel_data *pdata;
+ struct mdss_panel_info *pinfo;
+ int ret;
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected!\n");
+ return -EINVAL;
+ }
+ pinfo = &pdata->panel_info;
+
+ ret = scnprintf(buf, PAGE_SIZE, "%d\n", pinfo->persist_mode);
+
+ return ret;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split,
mdss_fb_store_split);
@@ -841,6 +910,8 @@ static DEVICE_ATTR(msm_fb_dfps_mode, S_IRUGO | S_IWUSR,
mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
static DEVICE_ATTR(measured_fps, S_IRUGO | S_IWUSR | S_IWGRP,
mdss_fb_get_fps_info, NULL);
+static DEVICE_ATTR(msm_fb_persist_mode, S_IRUGO | S_IWUSR,
+ mdss_fb_get_persist_mode, mdss_fb_change_persist_mode);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
&dev_attr_msm_fb_split.attr,
@@ -853,6 +924,7 @@ static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_panel_status.attr,
&dev_attr_msm_fb_dfps_mode.attr,
&dev_attr_measured_fps.attr,
+ &dev_attr_msm_fb_persist_mode.attr,
NULL,
};
@@ -1203,6 +1275,7 @@ static int mdss_fb_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mfd->file_list);
mutex_init(&mfd->bl_lock);
+ mutex_init(&mfd->mdss_sysfs_lock);
mutex_init(&mfd->switch_lock);
fbi_list[fbi_list_index++] = fbi;
@@ -1971,6 +2044,8 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
return ret;
}
+ mutex_lock(&mfd->mdss_sysfs_lock);
+
if (mfd->op_enable == 0) {
if (blank_mode == FB_BLANK_UNBLANK)
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
@@ -1980,7 +2055,9 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
else
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
- return 0;
+
+ ret = 0;
+ goto end;
}
pr_debug("mode: %d\n", blank_mode);
@@ -1997,7 +2074,12 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
if (pdata->panel_disable_mode)
mdss_mdp_enable_panel_disable_mode(mfd, false);
- return mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
+ ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
+
+end:
+ mutex_unlock(&mfd->mdss_sysfs_lock);
+
+ return ret;
}
static inline int mdss_fb_create_ion_client(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 1487c4e7f6e2..111d7cfc7c9a 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -310,6 +310,7 @@ struct msm_fb_data_type {
bool allow_bl_update;
u32 bl_level_scaled;
struct mutex bl_lock;
+ struct mutex mdss_sysfs_lock;
bool ipc_resume;
struct platform_device *pdev;
@@ -427,6 +428,12 @@ static inline bool mdss_fb_is_power_on_lp(struct msm_fb_data_type *mfd)
return mdss_panel_is_power_on_lp(mfd->panel_power_state);
}
+static inline bool mdss_fb_is_power_on_ulp(struct msm_fb_data_type *mfd)
+{
+ return mdss_panel_is_power_on_ulp(mfd->panel_power_state);
+}
+
+
static inline bool mdss_fb_is_hdmi_primary(struct msm_fb_data_type *mfd)
{
return (mfd && (mfd->index == 0) &&
diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
index 08307fe8eb16..834726e84bda 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c
+++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -643,7 +643,8 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
/* Wait for HDCP keys to be checked and validated */
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
((link0_status >> reg_set->keys_offset) & 0x7)
- == HDCP_KEYS_STATE_VALID,
+ == HDCP_KEYS_STATE_VALID ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("key not ready\n");
@@ -658,7 +659,8 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
/* Wait for An0 and An1 bit to be ready */
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
- (link0_status & (BIT(8) | BIT(9))),
+ (link0_status & (BIT(8) | BIT(9))) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("An not ready\n");
@@ -668,6 +670,9 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
/* As per hardware recommendations, wait before reading An */
msleep(20);
error:
+ if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+ rc = -EINVAL;
+
return rc;
}
@@ -820,7 +825,8 @@ static int hdcp_1x_verify_r0(struct hdcp_1x *hdcp)
/* Wait for HDCP R0 computation to be completed */
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
- link0_status & BIT(reg_set->r0_offset),
+ (link0_status & BIT(reg_set->r0_offset)) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("R0 not ready\n");
@@ -862,10 +868,14 @@ static int hdcp_1x_verify_r0(struct hdcp_1x *hdcp)
DSS_REG_W(io, reg_set->data2_0, (((u32)buf[1]) << 8) | buf[0]);
rc = readl_poll_timeout(io->base + reg_set->status,
- link0_status, link0_status & BIT(12),
+ link0_status, (link0_status & BIT(12)) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
r0_read_delay_us, r0_read_timeout_us);
} while (rc && --r0_retry);
error:
+ if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+ rc = -EINVAL;
+
return rc;
}
@@ -1092,9 +1102,9 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
*/
if (i && !((i + 1) % 64)) {
rc = readl_poll_timeout(io->base + reg_set->sha_status,
- sha_status, sha_status & BIT(0),
- HDCP_POLL_SLEEP_US,
- HDCP_POLL_TIMEOUT_US);
+ sha_status, (sha_status & BIT(0)) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("block not done\n");
goto error;
@@ -1108,7 +1118,8 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
/* Now wait for HDCP_SHA_COMP_DONE */
rc = readl_poll_timeout(io->base + reg_set->sha_status, sha_status,
- sha_status & BIT(4),
+ (sha_status & BIT(4)) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("V computation not done\n");
@@ -1117,13 +1128,17 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
/* Wait for V_MATCHES */
rc = readl_poll_timeout(io->base + reg_set->status, status,
- status & BIT(reg_set->v_offset),
+ (status & BIT(reg_set->v_offset)) ||
+ !hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
pr_err("V mismatch\n");
rc = -EINVAL;
}
error:
+ if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
+ rc = -EINVAL;
+
return rc;
}
@@ -1273,8 +1288,6 @@ static void hdcp_1x_update_auth_status(struct hdcp_1x *hdcp)
if (hdcp_1x_state(HDCP_STATE_AUTHENTICATED)) {
hdcp_1x_cache_topology(hdcp);
hdcp_1x_notify_topology(hdcp);
- } else {
- hdcp1_set_enc(false);
}
if (hdcp->init_data.notify_status &&
@@ -1459,9 +1472,6 @@ void hdcp_1x_off(void *input)
return;
}
- if (hdcp_1x_state(HDCP_STATE_AUTHENTICATED))
- hdcp1_set_enc(false);
-
/*
* Disable HDCP interrupts.
* Also, need to set the state to inactive here so that any ongoing
@@ -1482,11 +1492,13 @@ void hdcp_1x_off(void *input)
* No more reauthentiaction attempts will be scheduled since we
* set the currect state to inactive.
*/
- rc = cancel_delayed_work(&hdcp->hdcp_auth_work);
+ rc = cancel_delayed_work_sync(&hdcp->hdcp_auth_work);
if (rc)
pr_debug("%s: Deleted hdcp auth work\n",
HDCP_STATE_NAME);
+ hdcp1_set_enc(false);
+
reg = DSS_REG_R(io, reg_set->reset);
DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 3adf04214d87..3d8fe2ceebac 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -122,13 +122,6 @@ struct hdmi_edid_sink_caps {
bool ind_view_support;
};
-struct hdmi_edid_override_data {
- int scramble;
- int sink_mode;
- int format;
- int vic;
-};
-
struct hdmi_edid_ctrl {
u8 pt_scan_info;
u8 it_scan_info;
@@ -1607,9 +1600,14 @@ static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl,
(timing.refresh_rate % 100) / 10,
timing.refresh_rate % 10);
- rc = hdmi_get_video_id_code(&timing, NULL);
- if (rc < 0)
- rc = hdmi_set_resv_timing_info(&timing);
+ /*
+ * Always add resolutions parsed from DTD in the reserved
+ * timing info. This can avoid matching resolutions that have
+ * a non-integral fps denominators with corresponding
+ * resolutions that have an integral fps denominator.
+ * For example - 640x480p@59.94Hz --> 640x480p@60Hz
+ */
+ rc = hdmi_set_resv_timing_info(&timing);
} else {
rc = -EINVAL;
}
@@ -1983,7 +1981,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
{
u8 i = 0, offset = 0, std_blk = 0;
u32 video_format = HDMI_VFRMT_640x480p60_4_3;
- u32 has480p = false;
u8 len = 0;
u8 num_of_cea_blocks;
u8 *data_buf;
@@ -2046,9 +2043,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
video_format == HDMI_VFRMT_2880x576p50_16_9 ||
video_format == HDMI_VFRMT_1920x1250i50_16_9)
has50hz_mode = true;
-
- if (video_format == HDMI_VFRMT_640x480p60_4_3)
- has480p = true;
}
}
@@ -2067,9 +2061,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
hdmi_edid_add_sink_video_format(edid_ctrl,
video_format);
- if (video_format == HDMI_VFRMT_640x480p60_4_3)
- has480p = true;
-
/* Make a note of the preferred video format */
if (i == 0)
sink_data->preferred_video_format =
@@ -2091,7 +2082,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
desc_offset = edid_blk1[0x02];
if (desc_offset < (EDID_BLOCK_SIZE - EDID_DTD_LEN)) {
i = 0;
- while (!edid_blk1[desc_offset]) {
+ while ((i < 4) && edid_blk1[desc_offset]) {
hdmi_edid_detail_desc(edid_ctrl,
edid_blk1+desc_offset,
&video_format);
@@ -2103,8 +2094,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
hdmi_edid_add_sink_video_format(edid_ctrl,
video_format);
- if (video_format == HDMI_VFRMT_640x480p60_4_3)
- has480p = true;
/* Make a note of the preferred video format */
if (i == 0) {
@@ -2192,15 +2181,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
if (!rc)
pr_debug("%s: 3D formats in VSD\n", __func__);
}
-
- /*
- * Need to add default 640 by 480 timings, in case not described
- * in the EDID structure.
- * All DTV sink devices should support this mode
- */
- if (!has480p)
- hdmi_edid_add_sink_video_format(edid_ctrl,
- HDMI_VFRMT_640x480p60_4_3);
} /* hdmi_edid_get_display_mode */
u32 hdmi_edid_get_raw_data(void *input, u8 *buf, u32 size)
@@ -2498,6 +2478,11 @@ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode)
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
struct hdmi_edid_sink_data *sink_data;
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return false;
+ }
+
sink_data = &edid_ctrl->sink_data;
for (i = 0; i < sink_data->num_of_elements; ++i) {
if (sink_data->disp_mode_list[i].video_format != video_mode)
@@ -2610,6 +2595,31 @@ void hdmi_edid_set_video_resolution(void *input, u32 resolution, bool reset)
}
} /* hdmi_edid_set_video_resolution */
+void hdmi_edid_config_override(void *input, bool enable,
+ struct hdmi_edid_override_data *data)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+ struct hdmi_edid_override_data *ov_data = &edid_ctrl->override_data;
+
+ if ((!edid_ctrl) || (enable && !data)) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ edid_ctrl->edid_override = enable;
+ pr_debug("EDID override %s\n", enable ? "enabled" : "disabled");
+
+ if (enable) {
+ ov_data->scramble = data->scramble;
+ ov_data->sink_mode = data->sink_mode;
+ ov_data->format = data->format;
+ ov_data->vic = data->vic;
+ pr_debug("%s: Override data: scramble=%d sink_mode=%d format=%d vic=%d\n",
+ __func__, ov_data->scramble, ov_data->sink_mode,
+ ov_data->format, ov_data->vic);
+ }
+}
+
void hdmi_edid_deinit(void *input)
{
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index 5ee77fcf2066..16efb6ee4014 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -44,6 +44,20 @@ struct hdmi_edid_hdr_data {
u32 min_luminance;
};
+/*
+ * struct hdmi_override_data - Resolution Override Data
+ * @scramble - scrambler enable
+ * @sink_mode - 0 for DVI and 1 for HDMI
+ * @format - pixel format (refer to msm_hdmi_modes.h)
+ * @vic - resolution code
+ */
+struct hdmi_edid_override_data {
+ int scramble;
+ int sink_mode;
+ int format;
+ int vic;
+};
+
int hdmi_edid_parser(void *edid_ctrl);
u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size);
u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution);
@@ -63,5 +77,7 @@ u8 hdmi_edid_get_deep_color(void *edid_ctrl);
u32 hdmi_edid_get_max_pclk(void *edid_ctrl);
void hdmi_edid_get_hdr_data(void *edid_ctrl,
struct hdmi_edid_hdr_data **hdr_data);
+void hdmi_edid_config_override(void *input, bool enable,
+ struct hdmi_edid_override_data *data);
#endif /* __HDMI_EDID_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
index ce5c8c412c99..eadb90f3ce88 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
@@ -689,7 +689,6 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl)
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
pr_err("hdcp is off\n");
- rc = -EINVAL;
goto exit;
}
hdmi_ddc_config(ddc_ctrl);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 67813ca9cd37..abc56f5f352d 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -421,8 +421,10 @@ static inline void hdmi_tx_send_cable_notification(
if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd) {
u32 flags = 0;
- if (hdmi_tx_is_dvi_mode(hdmi_ctrl))
- flags |= MSM_EXT_DISP_HPD_NO_AUDIO;
+ flags |= MSM_EXT_DISP_HPD_VIDEO;
+
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
+ flags |= MSM_EXT_DISP_HPD_AUDIO;
hdmi_ctrl->ext_audio_data.intf_ops.hpd(hdmi_ctrl->ext_pdev,
hdmi_ctrl->ext_audio_data.type, val, flags);
@@ -1608,14 +1610,18 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work)
}
if (hdmi_tx_is_panel_on(hdmi_ctrl)) {
- DEV_DBG("%s: Reauthenticating\n", __func__);
- rc = hdmi_ctrl->hdcp_ops->reauthenticate(
- hdmi_ctrl->hdcp_data);
- if (rc)
- DEV_ERR("%s: HDCP reauth failed. rc=%d\n",
- __func__, rc);
+ pr_debug("%s: Reauthenticating\n", __func__);
+ if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_data) {
+ rc = hdmi_ctrl->hdcp_ops->reauthenticate(
+ hdmi_ctrl->hdcp_data);
+ if (rc)
+ pr_err("%s: HDCP reauth failed. rc=%d\n",
+ __func__, rc);
+ } else
+ pr_err("%s: NULL HDCP Ops and Data\n",
+ __func__);
} else {
- DEV_DBG("%s: Not reauthenticating. Cable not conn\n",
+ pr_debug("%s: Not reauthenticating. Cable not conn\n",
__func__);
}
@@ -2282,7 +2288,8 @@ static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
if (hdmi_ctrl->hdcp14_present) {
fd = hdmi_tx_get_fd(HDMI_TX_FEAT_HDCP);
- ops = hdcp_1x_start(fd);
+ if (fd)
+ ops = hdcp_1x_start(fd);
}
}
@@ -2325,6 +2332,31 @@ static void hdmi_tx_update_deep_color(struct hdmi_tx_ctrl *hdmi_ctrl)
}
}
+static void hdmi_tx_update_hdr_info(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info;
+ struct mdss_panel_hdr_properties *hdr_prop = &pinfo->hdr_properties;
+ struct hdmi_edid_hdr_data *hdr_data = NULL;
+
+ /* CEA-861.3 4.2 */
+ hdr_prop->hdr_enabled = hdmi_tx_is_hdr_supported(hdmi_ctrl);
+ /* no display primaries in EDID, so skip it */
+ memset(hdr_prop->display_primaries, 0,
+ sizeof(hdr_prop->display_primaries));
+
+ hdmi_edid_get_hdr_data(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), &hdr_data);
+
+ if (hdr_prop->hdr_enabled) {
+ hdr_prop->peak_brightness = hdr_data->max_luminance * 10000;
+ if (hdr_data->avg_luminance != 0)
+ hdr_prop->avg_brightness = 50 *
+ (BIT(0) << (int)(hdr_data->avg_luminance / 32));
+ hdr_prop->blackness_level = (hdr_data->min_luminance *
+ hdr_data->min_luminance *
+ hdr_data->max_luminance * 100) / 65025;
+ }
+}
+
static void hdmi_tx_hpd_int_work(struct work_struct *work)
{
struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
@@ -2353,6 +2385,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
if (!retry && rc)
pr_warn_ratelimited("%s: EDID read failed\n", __func__);
hdmi_tx_update_deep_color(hdmi_ctrl);
+ hdmi_tx_update_hdr_info(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, true);
} else {
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c
index 89890bcf68df..102c2f994646 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_util.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -555,6 +555,9 @@ int msm_hdmi_get_timing_info(
case HDMI_VFRMT_3840x2160p60_64_27:
MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p60_64_27);
break;
+ case HDMI_VFRMT_640x480p59_4_3:
+ MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_640x480p59_4_3);
+ break;
default:
ret = hdmi_get_resv_timing_info(mode, id);
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 7ed4b5404868..fbbcc16f48b5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1,7 +1,7 @@
/*
* MDSS MDP Interface (used by framebuffer core)
*
- * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2017, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -1794,11 +1794,13 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
return -EINVAL;
}
- mdata->venus = devm_regulator_get_optional(&mdata->pdev->dev,
- "gdsc-venus");
- if (IS_ERR_OR_NULL(mdata->venus)) {
- mdata->venus = NULL;
- pr_debug("unable to get venus gdsc regulator\n");
+ mdata->core_gdsc = devm_regulator_get_optional(&mdata->pdev->dev,
+ "gdsc-core");
+ if (IS_ERR_OR_NULL(mdata->core_gdsc)) {
+ mdata->core_gdsc = NULL;
+ pr_err("unable to get core gdsc regulator\n");
+ } else {
+ pr_debug("core gdsc regulator found\n");
}
mdata->fs_ena = false;
@@ -2370,10 +2372,10 @@ void mdss_mdp_footswitch_ctrl_splash(int on)
if (on) {
mdata->handoff_pending = true;
pr_debug("Enable MDP FS for splash.\n");
- if (mdata->venus) {
- ret = regulator_enable(mdata->venus);
+ if (mdata->core_gdsc) {
+ ret = regulator_enable(mdata->core_gdsc);
if (ret)
- pr_err("venus failed to enable\n");
+ pr_err("core_gdsc failed to enable\n");
}
ret = regulator_enable(mdata->fs);
@@ -2387,8 +2389,8 @@ void mdss_mdp_footswitch_ctrl_splash(int on)
mdss_bus_bandwidth_ctrl(false);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
regulator_disable(mdata->fs);
- if (mdata->venus)
- regulator_disable(mdata->venus);
+ if (mdata->core_gdsc)
+ regulator_disable(mdata->core_gdsc);
mdata->handoff_pending = false;
}
} else {
@@ -5059,6 +5061,7 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
{
int ret;
int active_cnt = 0;
+ bool footswitch_suspend = false;
if (!mdata->fs)
return;
@@ -5069,12 +5072,21 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
if (on) {
if (!mdata->fs_ena) {
pr_debug("Enable MDP FS\n");
- if (mdata->venus) {
- ret = regulator_enable(mdata->venus);
+ if (mdata->core_gdsc) {
+ ret = regulator_enable(mdata->core_gdsc);
if (ret)
- pr_err("venus failed to enable\n");
+ pr_err("core_gdsc failed to enable\n");
}
+ /*
+ * Advise RPM to not turn MMSS GDSC off, this will
+ * ensure that GDSC off is maintained during Active
+ * display and during Idle display
+ */
+ if (mdss_has_quirk(mdata,
+ MDSS_QUIRK_MMSS_GDSC_COLLAPSE))
+ mdss_rpm_set_msg_ram(true);
+
ret = regulator_enable(mdata->fs);
if (ret)
pr_warn("Footswitch failed to enable\n");
@@ -5092,13 +5104,6 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
active_cnt = atomic_read(&mdata->active_intf_cnt);
if (active_cnt != 0) {
/*
- * Advise RPM to not turn MMSS GDSC off during
- * idle case.
- */
- if (mdss_has_quirk(mdata,
- MDSS_QUIRK_MMSS_GDSC_COLLAPSE))
- mdss_rpm_set_msg_ram(true);
- /*
* Turning off GDSC while overlays are still
* active.
*/
@@ -5109,14 +5114,8 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
pr_debug("idle pc. active overlays=%d\n",
active_cnt);
} else {
- /*
- * Advise RPM to turn MMSS GDSC off during
- * suspend case
- */
- if (mdss_has_quirk(mdata,
- MDSS_QUIRK_MMSS_GDSC_COLLAPSE))
- mdss_rpm_set_msg_ram(false);
+ footswitch_suspend = true;
mdss_mdp_cx_ctrl(mdata, false);
mdss_mdp_batfet_ctrl(mdata, false);
mdss_mdp_memory_retention_ctrl(
@@ -5127,8 +5126,21 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
if (mdata->en_svs_high)
mdss_mdp_config_cx_voltage(mdata, false);
regulator_disable(mdata->fs);
- if (mdata->venus)
- regulator_disable(mdata->venus);
+ if (mdata->core_gdsc)
+ regulator_disable(mdata->core_gdsc);
+
+ if (footswitch_suspend) {
+ /*
+ * Advise RPM to turn MMSS GDSC off during
+ * suspend case, do this after the MDSS GDSC
+ * regulator OFF, so we can ensure that MMSS
+ * GDSC will go OFF after the MDSS GDSC
+ * regulator
+ */
+ if (mdss_has_quirk(mdata,
+ MDSS_QUIRK_MMSS_GDSC_COLLAPSE))
+ mdss_rpm_set_msg_ram(false);
+ }
}
mdata->fs_ena = false;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index d3d332d780d5..cb9cc08140f0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -124,6 +124,7 @@
#define DS_ENHANCER_UPDATE BIT(5)
#define DS_VALIDATE BIT(6)
#define DS_DIRTY_UPDATE BIT(7)
+#define DS_PU_ENABLE BIT(8)
/**
* Destination Scaler DUAL mode overfetch pixel count
@@ -386,6 +387,7 @@ struct mdss_mdp_destination_scaler {
u16 last_mixer_height;
u32 flags;
struct mdp_scale_data_v2 scaler;
+ struct mdss_rect panel_roi;
};
@@ -1169,6 +1171,14 @@ static inline int is_dest_scaling_enable(struct mdss_mdp_mixer *mixer)
mixer && mixer->ds && (mixer->ds->flags & DS_ENABLE));
}
+static inline int is_dest_scaling_pu_enable(struct mdss_mdp_mixer *mixer)
+{
+ if (is_dest_scaling_enable(mixer))
+ return (mixer->ds->flags & DS_PU_ENABLE);
+
+ return 0;
+}
+
static inline u32 get_ds_input_width(struct mdss_mdp_mixer *mixer)
{
struct mdss_mdp_destination_scaler *ds;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index f397aca8ad3a..ffbf156e9eed 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -4434,6 +4434,13 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
goto end;
}
+ /*
+ * reset the play_cnt, after the cmd_stop
+ * this will ensure pipes are reconfiged
+ * after every panel power state change
+ */
+ ctl->play_cnt = 0;
+
if (mdss_panel_is_power_on(power_state)) {
pr_debug("panel is not off, leaving ctl power on\n");
goto end;
@@ -4450,8 +4457,6 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
mdss_mdp_reset_mixercfg(ctl);
- ctl->play_cnt = 0;
-
end:
if (!ret) {
ctl->power_state = power_state;
@@ -4575,7 +4580,8 @@ int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery)
if (mixer) {
mdss_mdp_pipe_reset(mixer, is_recovery);
- if (is_dual_lm_single_display(ctl->mfd))
+ if (is_dual_lm_single_display(ctl->mfd) &&
+ ctl->mixer_right)
mdss_mdp_pipe_reset(ctl->mixer_right, is_recovery);
}
@@ -4652,7 +4658,15 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
previous_frame_pu_type = mdss_mdp_get_pu_type(ctl);
if (ctl->mixer_left) {
mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi);
- ctl->roi = ctl->mixer_left->roi;
+ if (is_dest_scaling_enable(ctl->mixer_left))
+ ctl->roi = ctl->mixer_left->ds->panel_roi;
+ else
+ ctl->roi = ctl->mixer_left->roi;
+
+ pr_debug("ctl->mixer_left: [%d %d %d %d] ds:%d\n",
+ ctl->roi.x, ctl->roi.y,
+ ctl->roi.w, ctl->roi.h,
+ is_dest_scaling_enable(ctl->mixer_left));
}
if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
@@ -4660,20 +4674,43 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
if (sctl && sctl->mixer_left) {
mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi);
- sctl->roi = sctl->mixer_left->roi;
+ if (is_dest_scaling_enable(sctl->mixer_left))
+ sctl->roi = sctl->mixer_left->ds->panel_roi;
+ else
+ sctl->roi = sctl->mixer_left->roi;
+
+ pr_debug("sctl->mixer_left: [%d %d %d %d] ds:%d\n",
+ sctl->roi.x, sctl->roi.y,
+ sctl->roi.w, sctl->roi.h,
+ is_dest_scaling_enable(sctl->mixer_left));
+
}
} else if (is_dual_lm_single_display(ctl->mfd) && ctl->mixer_right) {
mdss_mdp_set_mixer_roi(ctl->mixer_right, r_roi);
/* in this case, CTL_ROI is a union of left+right ROIs. */
- ctl->roi.w += ctl->mixer_right->roi.w;
+ if (is_dest_scaling_enable(ctl->mixer_right))
+ ctl->roi.w += ctl->mixer_right->ds->panel_roi.w;
+ else
+ ctl->roi.w += ctl->mixer_right->roi.w;
/* right_only, update roi.x as per CTL ROI guidelines */
if (ctl->mixer_left && !ctl->mixer_left->valid_roi) {
- ctl->roi = ctl->mixer_right->roi;
- ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
- ctl->mixer_right->roi.x;
+ if (is_dest_scaling_enable(ctl->mixer_right)) {
+ ctl->roi = ctl->mixer_right->ds->panel_roi;
+ ctl->roi.x =
+ get_ds_output_width(ctl->mixer_left) +
+ ctl->mixer_right->ds->panel_roi.x;
+ } else {
+ ctl->roi = ctl->mixer_right->roi;
+ ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
+ ctl->mixer_right->roi.x;
+ }
+ pr_debug("ctl->mixer_right_only : [%d %d %d %d] ds:%d\n",
+ ctl->roi.x, ctl->roi.y,
+ ctl->roi.w, ctl->roi.h,
+ is_dest_scaling_enable(ctl->mixer_right));
}
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index c249cac87b8a..b7f27b818eda 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -51,8 +51,10 @@ struct mdss_mdp_cmd_ctx {
u32 current_pp_num;
/*
* aux_pp_num will be set only when topology is using split-lm.
- * aux_pp_num will be used only when MDSS_QUIRK_DSC_RIGHT_ONLY_PU
- * quirk is set and on following partial updates.
+ * aux_pp_num will be used
+ * if right-only update on DUAL_LM_SINGLE_DISPLAY with 3D Mux
+ * or if MDSS_QUIRK_DSC_RIGHT_ONLY_PU quirk is set
+ * and on following partial updates.
*
* right-only update on DUAL_LM_SINGLE_DISPLAY with DSC_MERGE
* right-only update on DUAL_LM_DUAL_DISPLAY with DSC
@@ -119,14 +121,32 @@ static int mdss_mdp_setup_vsync(struct mdss_mdp_cmd_ctx *ctx, bool enable);
static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata,
struct mdss_mdp_ctl *mctl)
{
- return (mdata && mctl && mctl->is_master &&
- mdss_has_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU) &&
- is_dsc_compression(&mctl->panel_data->panel_info) &&
- ((mctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) ||
- ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
- (mctl->panel_data->panel_info.dsc_enc_total == 1))) &&
- !mctl->mixer_left->valid_roi &&
- mctl->mixer_right->valid_roi);
+ bool mux3d, merge, quirk, rightonly;
+
+ if (!mdata || !mctl || !mctl->is_master)
+ return false;
+
+ /*
+ * aux_pp_num will be used:
+ * if right-only update on DUAL_LM_SINGLE_DISPLAY with 3D Mux
+ * or if MDSS_QUIRK_DSC_RIGHT_ONLY_PU quirk is set
+ * and on following partial updates.
+ *
+ * right-only update on DUAL_LM_SINGLE_DISPLAY with DSC_MERGE
+ * right-only update on DUAL_LM_DUAL_DISPLAY with DSC
+ */
+ mux3d = ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
+ (mctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE));
+ merge = ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
+ (mctl->panel_data->panel_info.dsc_enc_total == 1));
+ quirk = (mdss_has_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU) &&
+ is_dsc_compression(&mctl->panel_data->panel_info) &&
+ ((mctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) ||
+ merge));
+ rightonly = !mctl->mixer_left->valid_roi &&
+ mctl->mixer_right->valid_roi;
+
+ return ((mux3d || quirk) && rightonly);
}
static bool __mdss_mdp_cmd_is_panel_power_off(struct mdss_mdp_cmd_ctx *ctx)
@@ -337,6 +357,87 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
return 0;
}
+/**
+ * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
+ * @arg: void pointer to the controller context.
+ *
+ * This function is the pp_done interrupt callback while disabling
+ * autorefresh. This function does not modify the kickoff count (koff_cnt).
+ */
+static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ if (!ctx) {
+ pr_err("%s: invalid ctx\n", __func__);
+ return;
+ }
+
+ mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num);
+ mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num, NULL, NULL);
+
+ MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
+ complete_all(&ctx->autorefresh_ppdone);
+
+ pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
+ ctl->num, ctl->intf_num, ctx->current_pp_num,
+ atomic_read(&ctx->koff_cnt));
+}
+
+static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
+{
+ int rc;
+ u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
+ char __iomem *pp_base = ctl->mixer_left->pingpong_base;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
+
+ MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
+ pr_debug("ctl:%d line_out:%d\n", ctl->num, line_out);
+
+ if (!ctx) {
+ pr_err("%s: invalid ctx\n", __func__);
+ return;
+ }
+
+ if (line_out < ctl->mixer_left->roi.h) {
+ reinit_completion(&ctx->autorefresh_ppdone);
+
+ /* enable ping pong done */
+ mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
+ mdss_mdp_cmd_autorefresh_pp_done, ctl);
+ mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);
+
+ /* wait for ping pong done */
+ rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
+ KOFF_TIMEOUT);
+ if (rc <= 0) {
+ val = mdss_mdp_pingpong_read(pp_base,
+ MDSS_MDP_REG_PP_LINE_COUNT);
+ if (val == ctl->mixer_left->roi.h) {
+ mdss_mdp_irq_clear(ctl->mdata,
+ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num);
+ mdss_mdp_irq_disable_nosync(intr_type,
+ ctx->current_pp_num);
+ mdss_mdp_set_intr_callback(intr_type,
+ ctx->current_pp_num, NULL, NULL);
+ } else {
+ pr_err("timedout waiting for ctl%d autorefresh pp done\n",
+ ctl->num);
+ MDSS_XLOG(0xbad3);
+ MDSS_XLOG_TOUT_HANDLER("mdp",
+ "vbif", "dbg_bus", "vbif_dbg_bus",
+ "panic");
+ }
+ }
+ }
+}
+
static bool __disable_rd_ptr_from_te(char __iomem *pingpong_base)
{
u32 cfg;
@@ -410,7 +511,10 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
rd_ptr_disabled =
__disable_rd_ptr_from_te(mixer->pingpong_base);
- /* 2. disable autorefresh */
+ /* 2. wait for previous transfer to finish */
+ mdss_mdp_cmd_wait4_autorefresh_pp(ctl);
+
+ /* 3. disable autorefresh */
if (is_pingpong_split(ctl->mfd))
__disable_autorefresh(
mdata->slave_pingpong_base);
@@ -427,7 +531,7 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
__disable_autorefresh(mixer->pingpong_base);
pr_debug("%s: disabling auto refresh\n", __func__);
- /* 2. re-enable rd pointer from te (if was enabled) */
+ /* 4. re-enable rd pointer from te (if was enabled) */
if (rd_ptr_disabled)
__enable_rd_ptr_from_te(mixer->pingpong_base);
@@ -1475,36 +1579,6 @@ static int mdss_mdp_cmd_update_lineptr(struct mdss_mdp_ctl *ctl, bool enable)
return 0;
}
-/**
- * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
- * @arg: void pointer to the controller context.
- *
- * This function is the pp_done interrupt callback while disabling
- * autorefresh. This function does not modify the kickoff count (koff_cnt).
- */
-static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
-{
- struct mdss_mdp_ctl *ctl = arg;
- struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
-
- if (!ctx) {
- pr_err("%s: invalid ctx\n", __func__);
- return;
- }
-
- mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num);
- mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num, NULL, NULL);
-
- MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
- complete_all(&ctx->autorefresh_ppdone);
-
- pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
- ctl->num, ctl->intf_num, ctx->current_pp_num,
- atomic_read(&ctx->koff_cnt));
-}
-
static void pingpong_done_work(struct work_struct *work)
{
u32 status;
@@ -2488,51 +2562,6 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl)
}
}
-static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
-{
- int rc;
- u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
- char __iomem *pp_base = ctl->mixer_left->pingpong_base;
- struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
-
- line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
-
- MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
-
- if (line_out < ctl->mixer_left->roi.h) {
- reinit_completion(&ctx->autorefresh_ppdone);
-
- /* enable ping pong done */
- mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
- mdss_mdp_cmd_autorefresh_pp_done, ctl);
- mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);
-
- /* wait for ping pong done */
- rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
- KOFF_TIMEOUT);
- if (rc <= 0) {
- val = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_LINE_COUNT);
- if (val == ctl->mixer_left->roi.h) {
- mdss_mdp_irq_clear(ctl->mdata,
- MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num);
- mdss_mdp_irq_disable_nosync(intr_type,
- ctx->current_pp_num);
- mdss_mdp_set_intr_callback(intr_type,
- ctx->current_pp_num, NULL, NULL);
- } else {
- pr_err("timedout waiting for ctl%d autorefresh pp done\n",
- ctl->num);
- MDSS_XLOG(0xbad3);
- MDSS_XLOG_TOUT_HANDLER("mdp",
- "vbif", "dbg_bus", "vbif_dbg_bus",
- "panic");
- }
- }
- }
-}
-
static void mdss_mdp_cmd_autorefresh_done(void *arg)
{
struct mdss_mdp_ctl *ctl = arg;
@@ -3236,6 +3265,8 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
(void *)&ctx->intf_mdp_callback,
CTL_INTF_EVENT_FLAG_DEFAULT);
+ mdss_mdp_tearcheck_enable(ctl, true);
+
ctx->intf_stopped = 0;
if (sctx)
sctx->intf_stopped = 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 5d5515a91572..4efa38093557 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1521,6 +1521,11 @@ exit_dfps:
pr_err("Error in dfps_wait: %d\n", rc);
}
+ /* Disable interface timing double buffer */
+ rc = mdss_mdp_ctl_intf_event(ctl,
+ MDSS_EVENT_DSI_TIMING_DB_CTRL,
+ (void *) (unsigned long) 0,
+ CTL_INTF_EVENT_FLAG_DEFAULT);
} else {
pr_err("intf %d panel, unknown FPS mode\n",
ctl->intf_num);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
index 9bebd72dce61..e1d2a947a77f 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -521,6 +521,10 @@ int mdss_mdp_writeback_prepare_cwb(struct mdss_mdp_ctl *ctl,
* updating img_width with buffer->planes[0].stride
*/
fmt = mdss_mdp_get_format_params(buffer->format);
+ if (!fmt) {
+ pr_err("invalid format for cwb\n");
+ return -EINVAL;
+ }
mdss_mdp_get_plane_sizes(fmt, ctx->img_width,
buffer->height, &ps, 0, 0);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 5a7f8e7e95b4..0eb82dd8371d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -67,6 +67,36 @@ static inline void *u64_to_ptr(uint64_t address)
return (void *)(uintptr_t)address;
}
+static inline struct mdp_destination_scaler_data *__dest_scaler_next(
+ struct mdp_destination_scaler_data *ds_data, int ds_count)
+{
+ struct mdp_destination_scaler_data *ds_data_r = ds_data;
+ size_t offset;
+
+ /*
+ * Advanced to next ds_data structure from commit if
+ * there is more than 1 for source split usecase.
+ */
+ if (ds_count > 1) {
+ ds_data_r = ds_data + 1;
+
+ /*
+ * To check for binary compatibility with old user mode
+ * driver which does not have ROI support in destination
+ * scalar.
+ */
+ if ((ds_data_r->dest_scaler_ndx != 1) &&
+ (ds_data_r->lm_height != ds_data->lm_height)) {
+ offset = offsetof(struct mdp_destination_scaler_data,
+ panel_roi);
+ ds_data_r = (struct mdp_destination_scaler_data *)(
+ (void *)ds_data + offset);
+ }
+ }
+
+ return ds_data_r;
+}
+
static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
{
struct mdss_data_type *mdata = ctl->mdata;
@@ -94,6 +124,9 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
ctl->mixer_right->roi = (struct mdss_rect) { 0, 0,
ctl->mixer_right->width,
ctl->mixer_right->height };
+ if (split_ctl)
+ split_ctl->mixer_left->roi =
+ ctl->mixer_right->roi;
/*
* Disable destination scaler by resetting the control
@@ -143,6 +176,46 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
}
}
+static int __dest_scaler_panel_roi_update(
+ struct mdp_destination_scaler_data *ds_data,
+ struct mdss_mdp_destination_scaler *ds)
+{
+ if (ds_data->flags & MDP_DESTSCALER_ROI_ENABLE) {
+ /*
+ * Updating PANEL ROI info, used in partial update
+ */
+ if ((ds_data->panel_roi.w > ds->scaler.dst_width) ||
+ (ds_data->panel_roi.h >
+ ds->scaler.dst_height) ||
+ (ds_data->panel_roi.w == 0) ||
+ (ds_data->panel_roi.h == 0)) {
+ pr_err("Invalid panel ROI parameter for dest-scaler-%d: [%d %d %d %d]\n",
+ ds_data->dest_scaler_ndx,
+ ds_data->panel_roi.x,
+ ds_data->panel_roi.y,
+ ds_data->panel_roi.w,
+ ds_data->panel_roi.h);
+ ds->flags &= ~DS_PU_ENABLE;
+ return -EINVAL;
+ }
+ ds->panel_roi.x = ds_data->panel_roi.x;
+ ds->panel_roi.y = ds_data->panel_roi.y;
+ ds->panel_roi.w = ds_data->panel_roi.w;
+ ds->panel_roi.h = ds_data->panel_roi.h;
+ ds->flags |= DS_PU_ENABLE;
+ pr_debug("dest-scaler[%d] panel_roi update: [%d,%d,%d,%d]\n",
+ ds->num,
+ ds_data->panel_roi.x, ds_data->panel_roi.y,
+ ds_data->panel_roi.w, ds_data->panel_roi.h);
+ MDSS_XLOG(ds->num, ds_data->panel_roi.x, ds_data->panel_roi.y,
+ ds_data->panel_roi.w, ds_data->panel_roi.h);
+ } else {
+ ds->flags &= ~DS_PU_ENABLE;
+ }
+
+ return 0;
+}
+
static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
struct mdss_mdp_destination_scaler *ds,
u32 max_input_width, u32 max_output_width)
@@ -188,6 +261,9 @@ static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
ds->src_height = ds_data->lm_height;
}
+ if (__dest_scaler_panel_roi_update(ds_data, ds))
+ return -EINVAL;
+
if (ds_data->flags == 0) {
pr_debug("Disabling destination scaler-%d\n",
ds_data->dest_scaler_ndx);
@@ -235,13 +311,7 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
}
if (ctl->mixer_right && ctl->mixer_right->ds) {
- /*
- * Advanced to next ds_data structure from commit if
- * there is more than 1 for split display usecase.
- */
- if (ds_count > 1)
- ds_data++;
-
+ ds_data = __dest_scaler_next(ds_data, ds_count);
pinfo = &ctl->panel_data->panel_info;
if ((ds_data->lm_width > get_panel_xres(pinfo)) ||
(ds_data->lm_height > get_panel_yres(pinfo)) ||
@@ -317,14 +387,17 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
int ret = 0;
struct mdss_data_type *mdata;
struct mdss_mdp_ctl *ctl;
+ struct mdss_mdp_ctl *sctl;
struct mdss_mdp_destination_scaler *ds_left = NULL;
struct mdss_mdp_destination_scaler *ds_right = NULL;
struct mdss_panel_info *pinfo;
u32 scaler_width, scaler_height;
+ struct mdp_destination_scaler_data *ds_data_r = NULL;
if (ds_data) {
mdata = mfd_to_mdata(mfd);
ctl = mfd_to_ctl(mfd);
+ sctl = mdss_mdp_get_split_ctl(ctl);
if (ctl->mixer_left)
ds_left = ctl->mixer_left->ds;
@@ -332,6 +405,9 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ctl->mixer_right)
ds_right = ctl->mixer_right->ds;
+ if (sctl && sctl->mixer_left && ds_right)
+ sctl->mixer_left->ds = ds_right;
+
switch (ds_mode) {
case DS_DUAL_MODE:
if (!ds_left || !ds_right) {
@@ -346,13 +422,28 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
- ret = __dest_scaler_data_setup(&ds_data[1], ds_right,
+ ds_data_r = __dest_scaler_next(ds_data, 2);
+ ret = __dest_scaler_data_setup(ds_data_r, ds_right,
mdata->max_dest_scaler_input_width -
MDSS_MDP_DS_OVERFETCH_SIZE,
mdata->max_dest_scaler_output_width);
if (ret)
goto reset_mixer;
+ if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
+ pinfo = &ctl->panel_data->panel_info;
+ if (ds_right->panel_roi.x >=
+ get_panel_xres(pinfo)) {
+ ds_right->panel_roi.x -=
+ get_panel_xres(pinfo);
+ } else {
+ pr_err("SCTL DS right roi.x:%d < left panel width:%d\n",
+ ds_right->panel_roi.x,
+ get_panel_xres(pinfo));
+ goto reset_mixer;
+ }
+ }
+
ds_left->flags &= ~(DS_LEFT|DS_RIGHT);
ds_left->flags |= DS_DUAL_MODE;
ds_right->flags &= ~(DS_LEFT|DS_RIGHT);
@@ -377,6 +468,17 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
+ /*
+ * For Partial update usecase, it is possible switching
+ * from Left+Right mode to Left only mode. So make sure
+ * cleanup the DS_RIGHT flags.
+ */
+ if (ds_right) {
+ ds_right->flags &=
+ ~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
+ ds_right->flags |= DS_VALIDATE;
+ }
+
MDSS_XLOG(ds_left->num, ds_left->src_width,
ds_left->src_height, ds_left->flags);
break;
@@ -396,6 +498,26 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
+ if (ds_left) {
+ ds_left->flags &=
+ ~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
+ ds_left->flags |= DS_VALIDATE;
+ }
+
+ if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
+ pinfo = &ctl->panel_data->panel_info;
+ if (ds_right->panel_roi.x >=
+ get_panel_xres(pinfo)) {
+ ds_right->panel_roi.x -=
+ get_panel_xres(pinfo);
+ } else {
+ pr_err("SCTL DS-right-only roi.x:%d < Left panel width:%d\n",
+ ds_right->panel_roi.x,
+ get_panel_xres(pinfo));
+ goto reset_mixer;
+ }
+ }
+
MDSS_XLOG(ds_right->num, ds_right->src_width,
ds_right->src_height, ds_right->flags);
break;
@@ -418,11 +540,11 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
pinfo = &ctl->panel_data->panel_info;
scaler_width = 0;
scaler_height = 0;
- if (ds_left && ds_left->flags) {
+ if (ds_left && (ds_left->flags & DS_ENABLE)) {
scaler_width += ds_left->scaler.dst_width;
scaler_height = ds_left->scaler.dst_height;
}
- if (ds_right && ds_right->flags) {
+ if (ds_right && (ds_right->flags & DS_ENABLE)) {
scaler_width += ds_right->scaler.dst_width;
scaler_height = ds_right->scaler.dst_height;
}
@@ -1674,7 +1796,12 @@ static int __validate_secure_session(struct mdss_overlay_private *mdp5_data)
pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n",
sd_pipes, nonsd_pipes, secure_vid_pipes, secure_cam_pipes);
- if ((sd_pipes || mdss_get_sd_client_cnt()) &&
+ if (mdss_get_sd_client_cnt() && !mdp5_data->sd_enabled) {
+ pr_err("Secure session already enabled for other client\n");
+ return -EINVAL;
+ }
+
+ if ((sd_pipes) &&
(nonsd_pipes || secure_vid_pipes ||
secure_cam_pipes)) {
pr_err("non-secure layer validation request during secure display session\n");
@@ -2726,7 +2853,8 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
return -ENODEV;
}
- if (mdss_fb_is_power_off(mfd)) {
+ if (mdss_fb_is_power_off(mfd) ||
+ mdss_fb_is_power_on_ulp(mfd)) {
pr_err("display interface is in off state fb:%d\n",
mfd->index);
return -EPERM;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index c6fc10833d7f..9864d611e8e4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1930,6 +1930,39 @@ static void __restore_pipe(struct mdss_mdp_pipe *pipe)
pipe->restore_roi = false;
}
+static void __restore_dest_scaler_roi(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+
+ if (is_dest_scaling_pu_enable(ctl->mixer_left)) {
+ ctl->mixer_left->ds->panel_roi.x = 0;
+ ctl->mixer_left->ds->panel_roi.y = 0;
+ ctl->mixer_left->ds->panel_roi.w = get_panel_xres(pinfo);
+ ctl->mixer_left->ds->panel_roi.h = get_panel_yres(pinfo);
+
+ if ((ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) &&
+ sctl) {
+ if (ctl->panel_data->next)
+ pinfo = &ctl->panel_data->next->panel_info;
+ sctl->mixer_left->ds->panel_roi.x = 0;
+ sctl->mixer_left->ds->panel_roi.y = 0;
+ sctl->mixer_left->ds->panel_roi.w =
+ get_panel_xres(pinfo);
+ sctl->mixer_left->ds->panel_roi.h =
+ get_panel_yres(pinfo);
+ } else if (ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) {
+ ctl->mixer_right->ds->panel_roi.x =
+ get_panel_xres(pinfo);
+ ctl->mixer_right->ds->panel_roi.y = 0;
+ ctl->mixer_right->ds->panel_roi.w =
+ get_panel_xres(pinfo);
+ ctl->mixer_right->ds->panel_roi.h =
+ get_panel_yres(pinfo);
+ }
+ }
+}
+
/**
* __adjust_pipe_rect() - Adjust pipe roi for dual partial update feature.
* @pipe: pipe to check against.
@@ -2145,6 +2178,9 @@ set_roi:
}
dual_roi->enabled = false;
}
+
+ if (pinfo->partial_update_enabled)
+ __restore_dest_scaler_roi(ctl);
}
pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n",
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 6870193166f2..563cb8be1a04 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2406,8 +2406,16 @@ bool mdss_mdp_is_amortizable_pipe(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_mixer *mixer, struct mdss_data_type *mdata)
{
/* do not apply for rotator or WB */
- return ((pipe->dst.y > mdata->prefill_data.ts_threshold) &&
- (mixer->type == MDSS_MDP_MIXER_TYPE_INTF));
+ if (!((pipe->dst.y > mdata->prefill_data.ts_threshold) &&
+ (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)))
+ return false;
+
+ /* do not apply for sdm660 in command mode */
+ if ((IS_MDSS_MAJOR_MINOR_SAME(mdata->mdp_rev,
+ MDSS_MDP_HW_REV_320)) && !mixer->ctl->is_video_mode)
+ return false;
+
+ return true;
}
static inline void __get_ordered_rects(struct mdss_mdp_pipe *pipe,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index 30dd3c856c7f..d83bedacec28 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3980,8 +3980,7 @@ int mdss_mdp_igc_lut_config(struct msm_fb_data_type *mfd,
disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
if (config->ops & MDP_PP_OPS_READ) {
- if (config->len != IGC_LUT_ENTRIES &&
- !pp_ops[IGC].pp_get_config) {
+ if (config->len != IGC_LUT_ENTRIES) {
pr_err("invalid len for IGC table for read %d\n",
config->len);
return -EINVAL;
@@ -4827,6 +4826,11 @@ gamut_clk_off:
goto gamut_set_dirty;
}
}
+ if (pp_gm_has_invalid_lut_size(config)) {
+ pr_debug("invalid lut size for gamut\n");
+ ret = -EINVAL;
+ goto gamut_config_exit;
+ }
local_cfg = *config;
tbl_off = mdss_pp_res->gamut_tbl[disp_num];
for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
@@ -5279,7 +5283,7 @@ static int pp_hist_collect(struct mdp_histogram_data *hist,
u32 block)
{
int ret = 0;
- u32 sum;
+ int sum = 0;
char __iomem *v_base = NULL;
unsigned long flag;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 4698d441f365..3fc5b2226b3e 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -118,6 +118,11 @@ enum {
};
enum {
+ MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0,
+ MDSS_PANEL_LOW_PERSIST_MODE_ON,
+};
+
+enum {
MODE_GPIO_NOT_VALID = 0,
MODE_SEL_DUAL_PORT,
MODE_SEL_SINGLE_PORT,
@@ -293,6 +298,7 @@ enum mdss_intf_events {
MDSS_EVENT_DEEP_COLOR,
MDSS_EVENT_DISABLE_PANEL,
MDSS_EVENT_UPDATE_PANEL_PPM,
+ MDSS_EVENT_DSI_TIMING_DB_CTRL,
MDSS_EVENT_MAX,
};
@@ -372,9 +378,11 @@ struct lcd_panel_info {
u32 h_back_porch;
u32 h_front_porch;
u32 h_pulse_width;
+ u32 h_active_low;
u32 v_back_porch;
u32 v_front_porch;
u32 v_pulse_width;
+ u32 v_active_low;
u32 border_clr;
u32 underflow_clr;
u32 hsync_skew;
@@ -746,6 +754,8 @@ struct mdss_panel_hdr_properties {
/* peak brightness supported by panel */
u32 peak_brightness;
+ /* average brightness supported by panel */
+ u32 avg_brightness;
/* Blackness level supported by panel */
u32 blackness_level;
};
@@ -892,6 +902,9 @@ struct mdss_panel_info {
/* debugfs structure for the panel */
struct mdss_panel_debugfs_info *debugfs_info;
+ /* persistence mode on/off */
+ bool persist_mode;
+
/* stores initial adaptive variable refresh vtotal value */
u32 saved_avr_vtotal;
@@ -936,6 +949,7 @@ struct mdss_panel_timing {
struct mdss_panel_data {
struct mdss_panel_info panel_info;
void (*set_backlight) (struct mdss_panel_data *pdata, u32 bl_level);
+ int (*apply_display_setting)(struct mdss_panel_data *pdata, u32 mode);
unsigned char *mmss_cc_base;
/**
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index 4fccf1178dac..30f8ca0487a7 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@ struct msm_ext_disp {
struct list_head display_list;
struct mutex lock;
struct completion hpd_comp;
+ u32 flags;
};
static int msm_ext_disp_get_intf_data(struct msm_ext_disp *ext_disp,
@@ -365,7 +366,7 @@ static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
{
int ret = 0;
- if (flags & MSM_EXT_DISP_HPD_NO_VIDEO) {
+ if (!(flags & MSM_EXT_DISP_HPD_VIDEO)) {
pr_debug("skipping video setup for display (%s)\n",
msm_ext_disp_name(type));
goto end;
@@ -398,7 +399,7 @@ static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
{
int ret = 0;
- if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
+ if (!(flags & MSM_EXT_DISP_HPD_AUDIO)) {
pr_debug("skipping audio setup for display (%s)\n",
msm_ext_disp_name(type));
goto end;
@@ -425,6 +426,47 @@ end:
return ret;
}
+static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_type type, u32 flags)
+{
+ /* allow new connections */
+ if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX)
+ goto end;
+
+ /* if already connected, block a new connection */
+ if (ext_disp->current_disp != type)
+ return false;
+
+ /* if same display connected, block same connection type */
+ if (ext_disp->flags & flags)
+ return false;
+
+end:
+ ext_disp->flags |= flags;
+ ext_disp->current_disp = type;
+ return true;
+}
+
+static bool msm_ext_disp_validate_disconnect(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_type type, u32 flags)
+{
+ /* check if nothing connected */
+ if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX)
+ return false;
+
+ /* check if a different display's request */
+ if (ext_disp->current_disp != type)
+ return false;
+
+ /* allow only an already connected type */
+ if (ext_disp->flags & flags) {
+ ext_disp->flags &= ~flags;
+ return true;
+ }
+
+ return false;
+}
+
static int msm_ext_disp_hpd(struct platform_device *pdev,
enum msm_ext_disp_type type,
enum msm_ext_disp_cable_state state,
@@ -446,8 +488,8 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
mutex_lock(&ext_disp->lock);
- pr_debug("HPD for display (%s), NEW STATE = %d\n",
- msm_ext_disp_name(type), state);
+ pr_debug("HPD for display (%s), NEW STATE = %d, flags = %d\n",
+ msm_ext_disp_name(type), state, flags);
if (state < EXT_DISPLAY_CABLE_DISCONNECT ||
state >= EXT_DISPLAY_CABLE_STATE_MAX) {
@@ -456,24 +498,13 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
goto end;
}
- if ((state == EXT_DISPLAY_CABLE_CONNECT) &&
- (ext_disp->current_disp != EXT_DISPLAY_TYPE_MAX)) {
- pr_err("Display interface (%s) already connected\n",
- msm_ext_disp_name(ext_disp->current_disp));
- ret = -EINVAL;
- goto end;
- }
-
- if ((state == EXT_DISPLAY_CABLE_DISCONNECT) &&
- (ext_disp->current_disp != type)) {
- pr_err("Display interface (%s) is not connected\n",
- msm_ext_disp_name(type));
- ret = -EINVAL;
- goto end;
- }
-
if (state == EXT_DISPLAY_CABLE_CONNECT) {
- ext_disp->current_disp = type;
+ if (!msm_ext_disp_validate_connect(ext_disp, type, flags)) {
+ pr_err("Display interface (%s) already connected\n",
+ msm_ext_disp_name(ext_disp->current_disp));
+ ret = -EINVAL;
+ goto end;
+ }
ret = msm_ext_disp_process_display(ext_disp, type, state,
flags);
@@ -490,11 +521,19 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
if (ret)
goto end;
} else {
+ if (!msm_ext_disp_validate_disconnect(ext_disp, type, flags)) {
+ pr_err("Display interface (%s) not connected\n",
+ msm_ext_disp_name(type));
+ ret = -EINVAL;
+ goto end;
+ }
+
msm_ext_disp_process_audio(ext_disp, type, state, flags);
msm_ext_disp_update_audio_ops(ext_disp, type, state, flags);
msm_ext_disp_process_display(ext_disp, type, state, flags);
- ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
+ if (!ext_disp->flags)
+ ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
pr_debug("Hpd (%d) for display (%s)\n", state,
@@ -653,7 +692,7 @@ static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
int ret = 0;
struct msm_ext_disp_audio_codec_ops *ops = ext_disp->ops;
- if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
+ if (!(flags & MSM_EXT_DISP_HPD_AUDIO)) {
pr_debug("skipping audio ops setup for display (%s)\n",
msm_ext_disp_name(type));
goto end;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 5071d1039c26..025f11b9cffa 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -928,6 +928,8 @@ static int fuse_readpages_fill(void *_data, struct page *page)
lock_page(newpage);
put_page(newpage);
+ lru_cache_add_file(newpage);
+
/* finally release the old page and swap pointers */
unlock_page(oldpage);
page_cache_release(oldpage);
diff --git a/include/dt-bindings/clock/mdss-pll-clk.h b/include/dt-bindings/clock/mdss-pll-clk.h
index 8cd0b2a9bc98..9015b4c0e1c9 100644
--- a/include/dt-bindings/clock/mdss-pll-clk.h
+++ b/include/dt-bindings/clock/mdss-pll-clk.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,4 +39,11 @@
#define SHADOW_POST_N1_DIV_1_CLK 22
#define SHADOW_VCO_CLK_1_CLK 23
+/* DP PLL clocks */
+#define DP_VCO_CLK 0
+#define DP_LINK_2X_CLK_DIVSEL_FIVE 1
+#define DP_VCO_DIVSEL_FOUR_CLK_SRC 2
+#define DP_VCO_DIVSEL_TWO_CLK_SRC 3
+#define DP_VCO_DIVIDED_CLK_SRC_MUX 4
+
#endif
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index da8ca5a7da58..6d73a04d0150 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -39,6 +39,15 @@ struct bvec_iter {
current bvec */
};
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+/* Double declaration from ktime.h so as to not break the include dependency
+ * chain. Should be kept up to date.
+ */
+union blk_ktime {
+ s64 tv64;
+};
+#endif
+
/*
* main unit of I/O for the block layer and lower layers (ie drivers and
* stacking drivers)
@@ -54,6 +63,10 @@ struct bio {
struct bvec_iter bi_iter;
+#ifdef CONFIG_BLOCK_PERF_FRAMEWORK
+ union blk_ktime submit_time;
+ unsigned int blk_sector_count;
+#endif
/* Number of segments in this BIO after
* physical address coalescing is performed.
*/
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 0eab4811ee92..d81d6a2db342 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -113,7 +113,7 @@ extern const struct cpumask *const cpu_isolated_mask;
#define cpu_possible(cpu) ((cpu) == 0)
#define cpu_present(cpu) ((cpu) == 0)
#define cpu_active(cpu) ((cpu) == 0)
-#define cpu_isolated(cpu) ((cpu) == 0)
+#define cpu_isolated(cpu) ((cpu) != 0)
#endif
/* verify cpu argument to cpumask_* operators */
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index d545604cc22d..c11a5c4afece 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -901,6 +901,7 @@ struct IpaHwRingStats_t {
* injected due to vdev_id change
* @num_ic_inj_fw_desc_change : Number of times the Imm Cmd is
* injected due to fw_desc change
+ * @num_qmb_int_handled : Number of QMB interrupts handled
*/
struct IpaHwStatsWDIRxInfoData_t {
u32 max_outstanding_pkts;
@@ -914,6 +915,7 @@ struct IpaHwStatsWDIRxInfoData_t {
u32 num_pkts_in_dis_uninit_state;
u32 num_ic_inj_vdev_change;
u32 num_ic_inj_fw_desc_change;
+ u32 num_qmb_int_handled;
u32 reserved1;
u32 reserved2;
} __packed;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3c1c96786248..b0bcc1561d3d 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -73,6 +73,7 @@ enum irqchip_irq_state;
* it from the spurious interrupt detection
* mechanism and from core side polling.
* IRQ_DISABLE_UNLAZY - Disable lazy irq disable
+ * IRQ_AFFINITY_MANAGED - Affinity is auto-managed by the kernel
*/
enum {
IRQ_TYPE_NONE = 0x00000000,
@@ -99,13 +100,14 @@ enum {
IRQ_PER_CPU_DEVID = (1 << 17),
IRQ_IS_POLLED = (1 << 18),
IRQ_DISABLE_UNLAZY = (1 << 19),
+ IRQ_AFFINITY_MANAGED = (1 << 21),
};
#define IRQF_MODIFY_MASK \
(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
- IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY)
+ IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_AFFINITY_MANAGED)
#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
@@ -191,6 +193,7 @@ struct irq_data {
* IRQD_IRQ_INPROGRESS - In progress state of the interrupt
* IRQD_WAKEUP_ARMED - Wakeup mode armed
* IRQD_FORWARDED_TO_VCPU - The interrupt is forwarded to a VCPU
+ * IRQD_AFFINITY_MANAGED - Affinity is auto-managed by the kernel
*/
enum {
IRQD_TRIGGER_MASK = 0xf,
@@ -206,6 +209,7 @@ enum {
IRQD_IRQ_INPROGRESS = (1 << 18),
IRQD_WAKEUP_ARMED = (1 << 19),
IRQD_FORWARDED_TO_VCPU = (1 << 20),
+ IRQD_AFFINITY_MANAGED = (1 << 21),
};
#define __irqd_to_state(d) ((d)->common->state_use_accessors)
@@ -299,6 +303,11 @@ static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)
__irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
}
+static inline bool irqd_affinity_is_managed(struct irq_data *d)
+{
+ return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
+}
+
static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
{
return d->hwirq;
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 11e8d89c337b..6eb8c1893a53 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -334,6 +334,7 @@ struct wcd9xxx {
struct slim_device *slim_slave;
struct mutex io_lock;
struct mutex xfer_lock;
+ struct mutex reset_lock;
u8 version;
int reset_gpio;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 276dbf19805b..804d89a825fc 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -22,6 +22,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <linux/mmc/pm.h>
+#include <linux/mmc/ring_buffer.h>
#define MMC_AUTOSUSPEND_DELAY_MS 3000
@@ -571,6 +572,7 @@ struct mmc_host {
} perf;
bool perf_enable;
#endif
+ struct mmc_trace_buffer trace_buf;
enum dev_state dev_status;
bool wakeup_on_idle;
struct mmc_cmdq_context_info cmdq_ctx;
diff --git a/include/linux/mmc/ring_buffer.h b/include/linux/mmc/ring_buffer.h
new file mode 100644
index 000000000000..e6bf163ffcfe
--- /dev/null
+++ b/include/linux/mmc/ring_buffer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MMC_RING_BUFFER__
+#define __MMC_RING_BUFFER__
+
+#include <linux/mmc/card.h>
+#include <linux/smp.h>
+
+#include "core.h"
+
+#define MMC_TRACE_RBUF_SZ_ORDER 2 /* 2^2 pages */
+#define MMC_TRACE_RBUF_SZ (PAGE_SIZE * (1 << MMC_TRACE_RBUF_SZ_ORDER))
+#define MMC_TRACE_EVENT_SZ 256
+#define MMC_TRACE_RBUF_NUM_EVENTS (MMC_TRACE_RBUF_SZ / MMC_TRACE_EVENT_SZ)
+
+struct mmc_host;
+struct mmc_trace_buffer {
+ int wr_idx;
+ bool stop_tracing;
+ spinlock_t trace_lock;
+ char *data;
+};
+
+#ifdef CONFIG_MMC_RING_BUFFER
+void mmc_stop_tracing(struct mmc_host *mmc);
+void mmc_trace_write(struct mmc_host *mmc, const char *fmt, ...);
+void mmc_trace_init(struct mmc_host *mmc);
+void mmc_trace_free(struct mmc_host *mmc);
+void mmc_dump_trace_buffer(struct mmc_host *mmc, struct seq_file *s);
+#else
+static inline void mmc_stop_tracing(struct mmc_host *mmc) {}
+static inline void mmc_trace_write(struct mmc_host *mmc,
+ const char *fmt, ...) {}
+static inline void mmc_trace_init(struct mmc_host *mmc) {}
+static inline void mmc_trace_free(struct mmc_host *mmc) {}
+static inline void mmc_dump_trace_buffer(struct mmc_host *mmc,
+ struct seq_file *s) {}
+#endif
+
+#define MMC_TRACE(mmc, fmt, ...) \
+ mmc_trace_write(mmc, fmt, ##__VA_ARGS__)
+
+#endif /* __MMC_RING_BUFFER__ */
diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h
index b3a7e4ad722a..44a04b5c2fcd 100644
--- a/include/linux/msm_ext_display.h
+++ b/include/linux/msm_ext_display.h
@@ -1,6 +1,6 @@
/* include/linux/msm_ext_display.h
*
- * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,11 +24,11 @@
/**
* Flags to be used with the HPD operation of the external display
* interface:
- * MSM_EXT_DISP_HPD_NO_AUDIO: audio will not be routed to external display
- * MSM_EXT_DISP_HPD_NO_VIDEO: video will not be routed to external display
+ * MSM_EXT_DISP_HPD_AUDIO: audio will be routed to external display
+ * MSM_EXT_DISP_HPD_VIDEO: video will be routed to external display
*/
-#define MSM_EXT_DISP_HPD_NO_AUDIO BIT(0)
-#define MSM_EXT_DISP_HPD_NO_VIDEO BIT(1)
+#define MSM_EXT_DISP_HPD_AUDIO BIT(0)
+#define MSM_EXT_DISP_HPD_VIDEO BIT(1)
/**
* struct ext_disp_cable_notify - cable notify handler structure
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index bc5637ab01df..4cde40dac778 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -55,7 +55,7 @@
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
/* big enough to hold our biggest descriptor */
-#define USB_COMP_EP0_BUFSIZ 1024
+#define USB_COMP_EP0_BUFSIZ 4096
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1)
struct usb_configuration;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 94ace231b3bd..e5930177c96a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -69,6 +69,8 @@ struct wiphy;
#define CFG80211_ABORT_SCAN 1
#define CFG80211_UPDATE_CONNECT_PARAMS 1
#define CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT 1
+#define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1
+#define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1
/*
* wireless hardware capability structures
@@ -1568,6 +1570,17 @@ struct cfg80211_sched_scan_plan {
};
/**
+ * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
+ *
+ * @band: band of BSS which should match for RSSI level adjustment.
+ * @delta: value of RSSI level adjustment.
+ */
+struct cfg80211_bss_select_adjust {
+ enum nl80211_band band;
+ s8 delta;
+};
+
+/**
* struct cfg80211_sched_scan_request - scheduled scan request description
*
* @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
@@ -1602,6 +1615,16 @@ struct cfg80211_sched_scan_plan {
* cycle. The driver may ignore this parameter and start
* immediately (or at any other time), if this feature is not
* supported.
+ * @relative_rssi_set: Indicates whether @relative_rssi is set or not.
+ * @relative_rssi: Relative RSSI threshold in dB to restrict scan result
+ * reporting in connected state to cases where a matching BSS is determined
+ * to have better or slightly worse RSSI than the current connected BSS.
+ * The relative RSSI threshold values are ignored in disconnected state.
+ * @rssi_adjust: delta dB of RSSI preference to be given to the BSSs that belong
+ * to the specified band while deciding whether a better BSS is reported
+ * using @relative_rssi. If delta is a negative number, the BSSs that
+ * belong to the specified band will be penalized by delta dB in relative
+ * comparisions.
*/
struct cfg80211_sched_scan_request {
struct cfg80211_ssid *ssids;
@@ -1621,6 +1644,10 @@ struct cfg80211_sched_scan_request {
u8 mac_addr[ETH_ALEN] __aligned(2);
u8 mac_addr_mask[ETH_ALEN] __aligned(2);
+ bool relative_rssi_set;
+ s8 relative_rssi;
+ struct cfg80211_bss_select_adjust rssi_adjust;
+
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
@@ -1906,6 +1933,22 @@ struct cfg80211_ibss_params {
};
/**
+ * struct cfg80211_bss_selection - connection parameters for BSS selection.
+ *
+ * @behaviour: requested BSS selection behaviour.
+ * @param: parameters for requestion behaviour.
+ * @band_pref: preferred band for %NL80211_BSS_SELECT_ATTR_BAND_PREF.
+ * @adjust: parameters for %NL80211_BSS_SELECT_ATTR_RSSI_ADJUST.
+ */
+struct cfg80211_bss_selection {
+ enum nl80211_bss_select_attr behaviour;
+ union {
+ enum ieee80211_band band_pref;
+ struct cfg80211_bss_select_adjust adjust;
+ } param;
+};
+
+/**
* struct cfg80211_connect_params - Connection parameters
*
* This structure provides information needed to complete IEEE 802.11
@@ -1942,6 +1985,7 @@ struct cfg80211_ibss_params {
* @vht_capa_mask: The bits of vht_capa which are to be used.
* @pbss: if set, connect to a PCP instead of AP. Valid for DMG
* networks.
+ * @bss_select: criteria to be used for BSS selection.
* @prev_bssid: previous BSSID, if not %NULL use reassociate frame
*/
struct cfg80211_connect_params {
@@ -1966,6 +2010,7 @@ struct cfg80211_connect_params {
struct ieee80211_vht_cap vht_capa;
struct ieee80211_vht_cap vht_capa_mask;
bool pbss;
+ struct cfg80211_bss_selection bss_select;
const u8 *prev_bssid;
};
@@ -3283,6 +3328,9 @@ struct wiphy_iftype_ext_capab {
* low rssi when a frame is heard on different channel, then it should set
* this variable to the maximal offset for which it can compensate.
* This value should be set in MHz.
+ * @bss_select_support: bitmask indicating the BSS selection criteria supported
+ * by the driver in the .connect() callback. The bit position maps to the
+ * attribute indices defined in &enum nl80211_bss_select_attr.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -3410,6 +3458,8 @@ struct wiphy {
u8 max_num_csa_counters;
u8 max_adj_channel_rssi_comp;
+ u32 bss_select_support;
+
char priv[0] __aligned(NETDEV_ALIGN);
};
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ee5270f984ba..e4a54cd23211 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2685,6 +2685,33 @@ enum ieee80211_ampdu_mlme_action {
};
/**
+ * struct ieee80211_ampdu_params - AMPDU action parameters
+ *
+ * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action.
+ * @sta: peer of this AMPDU session
+ * @tid: tid of the BA session
+ * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When
+ * action is set to %IEEE80211_AMPDU_RX_START the driver passes back the
+ * actual ssn value used to start the session and writes the value here.
+ * @buf_size: reorder buffer size (number of subframes). Valid only when the
+ * action is set to %IEEE80211_AMPDU_RX_START or
+ * %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU.
+ * valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @timeout: BA session timeout. Valid only when the action is set to
+ * %IEEE80211_AMPDU_RX_START
+ */
+struct ieee80211_ampdu_params {
+ enum ieee80211_ampdu_mlme_action action;
+ struct ieee80211_sta *sta;
+ u16 tid;
+ u16 ssn;
+ u8 buf_size;
+ bool amsdu;
+ u16 timeout;
+};
+
+/**
* enum ieee80211_frame_release_type - frame release reason
* @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
* @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
@@ -3028,13 +3055,9 @@ enum ieee80211_reconfig_type {
* @ampdu_action: Perform a certain A-MPDU action
* The RA/TID combination determines the destination and TID we want
* the ampdu action to be performed for. The action is defined through
- * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
- * is the first frame we expect to perform the action on. Notice
- * that TX/RX_STOP can pass NULL for this parameter.
- * The @buf_size parameter is only valid when the action is set to
- * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
- * buffer size (number of subframes) for this session -- the driver
- * may neither send aggregates containing more subframes than this
+ * ieee80211_ampdu_mlme_action.
+ * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver
+ * may neither send aggregates containing more subframes than @buf_size
* nor send aggregates in a way that lost frames would exceed the
* buffer size. If just limiting the aggregate size, this would be
* possible with a buf_size of 8:
@@ -3045,9 +3068,6 @@ enum ieee80211_reconfig_type {
* buffer size of 8. Correct ways to retransmit #1 would be:
* - TX: 1 or 18 or 81
* Even "189" would be wrong since 1 could be lost again.
- * The @amsdu parameter is valid when the action is set to
- * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability
- * to receive A-MSDU within A-MPDU.
*
* Returns a negative error code on failure.
* The callback can sleep.
@@ -3389,9 +3409,7 @@ struct ieee80211_ops {
int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size, bool amsdu);
+ struct ieee80211_ampdu_params *params);
int (*get_survey)(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void (*rfkill_poll)(struct ieee80211_hw *hw);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 38d49a2af8be..a047a33334d2 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1349,6 +1349,8 @@ struct afe_mod_enable_param {
* #AFE_MODULE_SIDETONE_IIR_FILTER module.
*/
#define AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG 0x00010204
+#define MAX_SIDETONE_IIR_DATA_SIZE 224
+#define MAX_NO_IIR_FILTER_STAGE 10
struct afe_sidetone_iir_filter_config_params {
u16 num_biquad_stages;
@@ -1360,6 +1362,7 @@ struct afe_sidetone_iir_filter_config_params {
/* Pregain for the compensating filter response.
* Supported values: Any number in Q13 format
*/
+ uint8_t iir_config[MAX_SIDETONE_IIR_DATA_SIZE];
} __packed;
#define AFE_MODULE_LOOPBACK 0x00010205
@@ -1511,6 +1514,55 @@ struct afe_loopback_cfg_v1 {
} __packed;
+struct afe_loopback_sidetone_gain {
+ u16 rx_port_id;
+ u16 gain;
+} __packed;
+
+struct loopback_cfg_data {
+ u32 loopback_cfg_minor_version;
+/* Minor version used for tracking the version of the RMC module
+ * configuration interface.
+ * Supported values: #AFE_API_VERSION_LOOPBACK_CONFIG
+ */
+ u16 dst_port_id;
+ /* Destination Port Id. */
+ u16 routing_mode;
+/* Specifies data path type from src to dest port.
+ * Supported values:
+ * #LB_MODE_DEFAULT
+ * #LB_MODE_SIDETONE
+ * #LB_MODE_EC_REF_VOICE_AUDIO
+ * #LB_MODE_EC_REF_VOICE_A
+ * #LB_MODE_EC_REF_VOICE
+ */
+
+ u16 enable;
+/* Specifies whether to enable (1) or
+ * disable (0) an AFE loopback.
+ */
+ u16 reserved;
+/* Reserved for 32-bit alignment. This field must be set to 0.
+ */
+} __packed;
+
+struct afe_st_loopback_cfg_v1 {
+ struct apr_hdr hdr;
+ struct afe_port_cmd_set_param_v2 param;
+ struct afe_port_param_data_v2 gain_pdata;
+ struct afe_loopback_sidetone_gain gain_data;
+ struct afe_port_param_data_v2 cfg_pdata;
+ struct loopback_cfg_data cfg_data;
+} __packed;
+
+struct afe_loopback_iir_cfg_v2 {
+ struct apr_hdr hdr;
+ struct afe_port_cmd_set_param_v2 param;
+ struct afe_port_param_data_v2 st_iir_enable_pdata;
+ struct afe_mod_enable_param st_iir_mode_enable_data;
+ struct afe_port_param_data_v2 st_iir_filter_config_pdata;
+ struct afe_sidetone_iir_filter_config_params st_iir_filter_config_data;
+} __packed;
#define AFE_MODULE_SPEAKER_PROTECTION 0x00010209
#define AFE_PARAM_ID_SPKR_PROT_CONFIG 0x0001020a
#define AFE_API_VERSION_SPKR_PROT_CONFIG 0x1
@@ -4924,8 +4976,8 @@ struct asm_amrwbplus_fmt_blk_v2 {
} __packed;
-#define ASM_MEDIA_FMT_AC3 0x00010DEE
-#define ASM_MEDIA_FMT_EAC3 0x00010DEF
+#define ASM_MEDIA_FMT_AC3 0x00010DEE
+#define ASM_MEDIA_FMT_EAC3 0x00010DEF
#define ASM_MEDIA_FMT_DTS 0x00010D88
#define ASM_MEDIA_FMT_MP2 0x00010DE9
#define ASM_MEDIA_FMT_FLAC 0x00010C16
@@ -4934,7 +4986,6 @@ struct asm_amrwbplus_fmt_blk_v2 {
#define ASM_MEDIA_FMT_APE 0x00012F32
#define ASM_MEDIA_FMT_DSD 0x00012F3E
-
/* Media format ID for adaptive transform acoustic coding. This
* ID is used by the #ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED command
* only.
@@ -8941,6 +8992,31 @@ struct asm_dts_eagle_param_get {
struct asm_stream_cmd_get_pp_params_v2 param;
} __packed;
+/* Opcode to set BT address and license for aptx decoder */
+#define APTX_DECODER_BT_ADDRESS 0x00013201
+#define APTX_CLASSIC_DEC_LICENSE_ID 0x00013202
+
+struct aptx_dec_bt_addr_cfg {
+ uint32_t lap;
+ uint32_t uap;
+ uint32_t nap;
+} __packed;
+
+struct aptx_dec_bt_dev_addr {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param encdec;
+ struct aptx_dec_bt_addr_cfg bt_addr_cfg;
+} __packed;
+
+struct asm_aptx_dec_fmt_blk_v2 {
+ struct apr_hdr hdr;
+ struct asm_data_cmd_media_fmt_update_v2 fmtblk;
+ u32 sample_rate;
+/* Number of samples per second.
+ * Supported values: 44100 and 48000 Hz
+ */
+} __packed;
+
/* LSM Specific */
#define VW_FEAT_DIM (39)
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index e0da428fa52f..a47d2805b9c5 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -265,7 +265,7 @@ struct aanc_data {
int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
int afe_close(int port_id);
int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
-int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain);
+int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable);
int afe_loopback_gain(u16 port_id, u16 volume);
int afe_validate_port(u16 port_id);
int afe_get_port_index(u16 port_id);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index efa5af8e661c..9a3db9aaa25e 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -53,6 +53,7 @@
#define FORMAT_G711_MLAW_FS 0x001b
#define FORMAT_DTS 0x001c
#define FORMAT_DSD 0x001d
+#define FORMAT_APTX 0x001e
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -270,7 +271,7 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample);
int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample);
+ uint16_t bits_per_sample, bool ts_mode);
int q6asm_open_write(struct audio_client *ac, uint32_t format
/*, uint16_t bits_per_sample*/);
@@ -552,6 +553,9 @@ int q6asm_media_format_block_ape(struct audio_client *ac,
int q6asm_media_format_block_dsd(struct audio_client *ac,
struct asm_dsd_cfg *cfg, int stream_id);
+int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
+ uint32_t sr, int stream_id);
+
int q6asm_ds1_set_endp_params(struct audio_client *ac,
int param_id, int param_value);
@@ -574,6 +578,10 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size,
int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size,
void *data, struct param_outband *po, int m_id);
+/* Send aptx decoder BT address */
+int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
+ struct aptx_dec_bt_addr_cfg *cfg);
+
/* Set SoftPause Params */
int q6asm_set_softpause(struct audio_client *ac,
struct asm_softpause_params *param);
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 3c6ab13ca470..f05f9aaddb70 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -98,12 +98,15 @@ enum {
ULP_LSM_TOPOLOGY_ID_CAL_TYPE,
AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
+ AFE_SIDETONE_IIR_CAL_TYPE,
MAX_CAL_TYPES,
};
#define AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE
#define AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE
+#define AFE_SIDETONE_IIR_CAL_TYPE AFE_SIDETONE_IIR_CAL_TYPE
+
enum {
VERSION_0_0,
};
@@ -346,6 +349,19 @@ struct audio_cal_info_sidetone {
int32_t pid;
};
+#define MAX_SIDETONE_IIR_DATA_SIZE 224
+#define MAX_NO_IIR_FILTER_STAGE 10
+
+struct audio_cal_info_sidetone_iir {
+ uint16_t iir_enable;
+ uint16_t num_biquad_stages;
+ uint16_t pregain;
+ int32_t tx_acdb_id;
+ int32_t rx_acdb_id;
+ int32_t mid;
+ int32_t pid;
+ uint8_t iir_config[MAX_SIDETONE_IIR_DATA_SIZE];
+};
struct audio_cal_info_lsm_top {
int32_t topology;
int32_t acdb_id;
@@ -580,6 +596,17 @@ struct audio_cal_sidetone {
struct audio_cal_type_sidetone cal_type;
};
+struct audio_cal_type_sidetone_iir {
+ struct audio_cal_type_header cal_hdr;
+ struct audio_cal_data cal_data;
+ struct audio_cal_info_sidetone_iir cal_info;
+};
+
+struct audio_cal_sidetone_iir {
+ struct audio_cal_header hdr;
+ struct audio_cal_type_sidetone_iir cal_type;
+};
+
struct audio_cal_type_lsm_top {
struct audio_cal_type_header cal_hdr;
struct audio_cal_data cal_data;
diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 24f1e7c7b742..3bd8bea8ae0d 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -125,6 +125,12 @@ DESTINATION SCALER FLAG CONFIGURATION
*/
#define MDP_DESTSCALER_ENHANCER_UPDATE 0x4
+/*
+ * Indicating a partial update to panel ROI. ROI can be
+ * applied anytime when Destination scaler is enabled.
+ */
+#define MDP_DESTSCALER_ROI_ENABLE 0x8
+
/**********************************************************************
VALIDATE/COMMIT FLAG CONFIGURATION
**********************************************************************/
@@ -405,6 +411,12 @@ struct mdp_destination_scaler_data {
* A userspace pointer points to struct mdp_scale_data_v2.
*/
uint64_t __user scale;
+
+ /*
+ * Panel ROI is used when partial update is required in
+ * current commit call.
+ */
+ struct mdp_rect panel_roi;
};
/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index cc8ece36e0e3..0505b1f9872b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1934,6 +1934,20 @@ enum nl80211_commands {
* @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
* used in various commands/events for specifying the BSSID.
*
+ * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which
+ * other BSSs has to be better or slightly worse than the current
+ * connected BSS so that they get reported to user space.
+ * This will give an opportunity to userspace to consider connecting to
+ * other matching BSSs which have better or slightly worse RSSI than
+ * the current connected BSS by using an offloaded operation to avoid
+ * unnecessary wakeups.
+ *
+ * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for BSSs in
+ * the specified band is to be adjusted before doing
+ * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparision to figure out
+ * better BSSs. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2340,6 +2354,9 @@ enum nl80211_attrs {
NL80211_ATTR_BSSID,
+ NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+ NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3008,6 +3025,13 @@ enum nl80211_reg_rule_attr {
* how this API was implemented in the past. Also, due to the same problem,
* the only way to create a matchset with only an RSSI filter (with this
* attribute) is if there's only a single matchset with the RSSI attribute.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI: Flag indicating whether
+ * %NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to be used as absolute RSSI or
+ * relative to current bss's RSSI.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST: When present the RSSI level for
+ * BSS-es in the specified band is to be adjusted before doing
+ * RSSI-based BSS selection. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3017,6 +3041,8 @@ enum nl80211_sched_scan_match_attr {
NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
/* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -4603,6 +4629,15 @@ enum nl80211_feature_flags {
* configuration (AP/mesh) with HT rates.
* @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
* configuration (AP/mesh) with VHT rates.
+ * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup
+ * with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
+ * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA: This driver supports randomized TA
+ * in @NL80211_CMD_FRAME while not associated.
+ * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED: This driver supports
+ * randomized TA in @NL80211_CMD_FRAME while associated.
+ * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan
+ * for reporting BSSs with better RSSI than the current connected BSS
+ * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4617,6 +4652,10 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
NL80211_EXT_FEATURE_BEACON_RATE_HT,
NL80211_EXT_FEATURE_BEACON_RATE_VHT,
+ NL80211_EXT_FEATURE_FILS_STA,
+ NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA,
+ NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED,
+ NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
@@ -4866,4 +4905,48 @@ enum nl80211_sched_scan_plan {
__NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1
};
+/**
+ * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters.
+ *
+ * @band: band of BSS that must match for RSSI value adjustment.
+ * @delta: value used to adjust the RSSI value of matching BSS.
+ */
+struct nl80211_bss_select_rssi_adjust {
+ __u8 band;
+ __s8 delta;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_bss_select_attr - attributes for bss selection.
+ *
+ * @__NL80211_BSS_SELECT_ATTR_INVALID: reserved.
+ * @NL80211_BSS_SELECT_ATTR_RSSI: Flag indicating only RSSI-based BSS selection
+ * is requested.
+ * @NL80211_BSS_SELECT_ATTR_BAND_PREF: attribute indicating BSS
+ * selection should be done such that the specified band is preferred.
+ * When there are multiple BSS-es in the preferred band, the driver
+ * shall use RSSI-based BSS selection as a second step. The value of
+ * this attribute is according to &enum nl80211_band (u32).
+ * @NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: When present the RSSI level for
+ * BSS-es in the specified band is to be adjusted before doing
+ * RSSI-based BSS selection. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ * @NL80211_BSS_SELECT_ATTR_MAX: highest bss select attribute number.
+ * @__NL80211_BSS_SELECT_ATTR_AFTER_LAST: internal use.
+ *
+ * One and only one of these attributes are found within %NL80211_ATTR_BSS_SELECT
+ * for %NL80211_CMD_CONNECT. It specifies the required BSS selection behaviour
+ * which the driver shall use.
+ */
+enum nl80211_bss_select_attr {
+ __NL80211_BSS_SELECT_ATTR_INVALID,
+ NL80211_BSS_SELECT_ATTR_RSSI,
+ NL80211_BSS_SELECT_ATTR_BAND_PREF,
+ NL80211_BSS_SELECT_ATTR_RSSI_ADJUST,
+
+ /* keep last */
+ __NL80211_BSS_SELECT_ATTR_AFTER_LAST,
+ NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index ef96966b2bbe..6a297ad6d380 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -103,7 +103,8 @@
#define SND_AUDIOCODEC_ALAC ((__u32) 0x00000019)
#define SND_AUDIOCODEC_APE ((__u32) 0x00000020)
#define SND_AUDIOCODEC_DSD ((__u32) 0x00000021)
-#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_DSD
+#define SND_AUDIOCODEC_APTX ((__u32) 0x00000022)
+#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APTX
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
@@ -396,6 +397,12 @@ struct snd_dec_ape {
__u32 seek_table_present;
};
+struct snd_dec_aptx {
+ __u32 lap;
+ __u32 uap;
+ __u32 nap;
+};
+
union snd_codec_options {
struct snd_enc_wma wma;
struct snd_enc_vorbis vorbis;
@@ -407,6 +414,7 @@ union snd_codec_options {
struct snd_dec_vorbis vorbis_dec;
struct snd_dec_alac alac;
struct snd_dec_ape ape;
+ struct snd_dec_aptx aptx_dec;
};
/** struct snd_codec_desc - description of codec capabilities
diff --git a/include/uapi/video/msm_hdmi_modes.h b/include/uapi/video/msm_hdmi_modes.h
index 2200485daa6c..43ca6bab4c62 100644
--- a/include/uapi/video/msm_hdmi_modes.h
+++ b/include/uapi/video/msm_hdmi_modes.h
@@ -234,7 +234,11 @@ struct msm_hdmi_mode_timing_info {
#define HDMI_VFRMT_1920x1200p60_16_10 ETIII_OFF(8)
#define ETIII_VFRMT_END HDMI_VFRMT_1920x1200p60_16_10
-#define RESERVE_OFF(x) (ETIII_VFRMT_END + x)
+#define MISC_VFRMT_OFF(x) (ETIII_VFRMT_END + x)
+#define HDMI_VFRMT_640x480p59_4_3 MISC_VFRMT_OFF(1)
+#define MISC_VFRMT_END HDMI_VFRMT_640x480p59_4_3
+
+#define RESERVE_OFF(x) (MISC_VFRMT_END + x)
#define HDMI_VFRMT_RESERVE1 RESERVE_OFF(1)
#define HDMI_VFRMT_RESERVE2 RESERVE_OFF(2)
@@ -425,6 +429,11 @@ struct msm_hdmi_mode_timing_info {
{HDMI_VFRMT_3840x2160p60_64_27, 3840, 176, 88, 296, false, \
2160, 8, 10, 72, false, 594000, 60000, false, true, \
HDMI_RES_AR_64_27, 0}
+#define HDMI_VFRMT_640x480p59_4_3_TIMING \
+ {HDMI_VFRMT_640x480p59_4_3, 640, 16, 96, 48, true, \
+ 480, 10, 2, 33, true, 25170, 59928, false, true, \
+ HDMI_RES_AR_4_3, 1}
+
#define MSM_HDMI_MODES_SET_TIMING(LUT, MODE) do { \
struct msm_hdmi_mode_timing_info mode = MODE##_TIMING; \
@@ -508,6 +517,8 @@ do { \
HDMI_VFRMT_3840x2160p50_64_27); \
MSM_HDMI_MODES_SET_TIMING(__lut, \
HDMI_VFRMT_3840x2160p60_64_27); \
+ MSM_HDMI_MODES_SET_TIMING(__lut, \
+ HDMI_VFRMT_640x480p59_4_3); \
} \
if (__type & MSM_HDMI_MODES_XTND) { \
MSM_HDMI_MODES_SET_TIMING(__lut, \
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 15206453b12a..9812d9c0d483 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -836,7 +836,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
irq_settings_clr_and_set(desc, clr, set);
irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU |
- IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT);
+ IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT |
+ IRQD_AFFINITY_MANAGED);
if (irq_settings_has_no_balance_set(desc))
irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
if (irq_settings_is_per_cpu(desc))
@@ -845,6 +846,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT);
if (irq_settings_is_level(desc))
irqd_set(&desc->irq_data, IRQD_LEVEL);
+ if (irq_settings_has_affinity_managed_set(desc))
+ irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED);
irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc));
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index fcab63c66905..56afc0be6289 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -105,6 +105,8 @@ static inline void unregister_handler_proc(unsigned int irq,
struct irqaction *action) { }
#endif
+extern bool irq_can_set_affinity_usr(unsigned int irq);
+
extern int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask);
extern void irq_set_thread_affinity(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5cb153a8474a..e5c70dcb7f8e 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -115,12 +115,12 @@ EXPORT_SYMBOL(synchronize_irq);
#ifdef CONFIG_SMP
cpumask_var_t irq_default_affinity;
-static int __irq_can_set_affinity(struct irq_desc *desc)
+static bool __irq_can_set_affinity(struct irq_desc *desc)
{
if (!desc || !irqd_can_balance(&desc->irq_data) ||
!desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)
- return 0;
- return 1;
+ return false;
+ return true;
}
/**
@@ -134,6 +134,21 @@ int irq_can_set_affinity(unsigned int irq)
}
/**
+ * irq_can_set_affinity_usr - Check if affinity of a irq can be set from user space
+ * @irq: Interrupt to check
+ *
+ * Like irq_can_set_affinity() above, but additionally checks for the
+ * AFFINITY_MANAGED flag.
+ */
+bool irq_can_set_affinity_usr(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ return __irq_can_set_affinity(desc) &&
+ !irqd_affinity_is_managed(&desc->irq_data);
+}
+
+/**
* irq_set_thread_affinity - Notify irq threads to adjust affinity
* @desc: irq descriptor which has affitnity changed
*
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index a2c02fd5d6d0..a24c5b909047 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -96,7 +96,7 @@ static ssize_t write_irq_affinity(int type, struct file *file,
cpumask_var_t new_value;
int err;
- if (!irq_can_set_affinity(irq) || no_irq_affinity)
+ if (!irq_can_set_affinity_usr(irq) || no_irq_affinity)
return -EIO;
if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index 320579d89091..f0964f058521 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -17,6 +17,7 @@ enum {
_IRQ_IS_POLLED = IRQ_IS_POLLED,
_IRQ_DISABLE_UNLAZY = IRQ_DISABLE_UNLAZY,
_IRQF_MODIFY_MASK = IRQF_MODIFY_MASK,
+ _IRQ_AFFINITY_MANAGED = IRQ_AFFINITY_MANAGED,
};
#define IRQ_PER_CPU GOT_YOU_MORON
@@ -32,6 +33,7 @@ enum {
#define IRQ_DISABLE_UNLAZY GOT_YOU_MORON
#undef IRQF_MODIFY_MASK
#define IRQF_MODIFY_MASK GOT_YOU_MORON
+#define IRQ_AFFINITY_MANAGED GOT_YOU_MORON
static inline void
irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set)
@@ -65,6 +67,16 @@ static inline bool irq_settings_has_no_balance_set(struct irq_desc *desc)
return desc->status_use_accessors & _IRQ_NO_BALANCING;
}
+static inline void irq_settings_set_affinity_managed(struct irq_desc *desc)
+{
+ desc->status_use_accessors |= _IRQ_AFFINITY_MANAGED;
+}
+
+static inline bool irq_settings_has_affinity_managed_set(struct irq_desc *desc)
+{
+ return desc->status_use_accessors & _IRQ_AFFINITY_MANAGED;
+}
+
static inline u32 irq_settings_get_trigger_mask(struct irq_desc *desc)
{
return desc->status_use_accessors & IRQ_TYPE_SENSE_MASK;
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 40df4f8f1de0..95125c5518e2 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -590,6 +590,7 @@ void update_cluster_topology(void)
* cluster_head visible.
*/
move_list(&cluster_head, &new_head, false);
+ update_all_clusters_stats();
}
void init_clusters(void)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d3873333c766..a2a87c3ad44e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -178,7 +178,7 @@ extern int no_unaligned_warning;
#define SYSCTL_WRITES_WARN 0
#define SYSCTL_WRITES_STRICT 1
-static int sysctl_writes_strict = SYSCTL_WRITES_WARN;
+static int sysctl_writes_strict = SYSCTL_WRITES_STRICT;
static int proc_do_cad_pid(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d41925306d75..c42587d02190 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1754,13 +1754,25 @@ static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
struct page, lru);
/*
- * It should never happen but changes to locking could
- * inadvertently allow a per-cpu drain to add pages
- * to MIGRATE_HIGHATOMIC while unreserving so be safe
- * and watch for underflows.
+ * In page freeing path, migratetype change is racy so
+ * we can counter several free pages in a pageblock
+ * in this loop althoug we changed the pageblock type
+ * from highatomic to ac->migratetype. So we should
+ * adjust the count once.
*/
- zone->nr_reserved_highatomic -= min(pageblock_nr_pages,
- zone->nr_reserved_highatomic);
+ if (get_pageblock_migratetype(page) ==
+ MIGRATE_HIGHATOMIC) {
+ /*
+ * It should never happen but changes to
+ * locking could inadvertently allow a per-cpu
+ * drain to add pages to MIGRATE_HIGHATOMIC
+ * while unreserving so be safe and watch for
+ * underflows.
+ */
+ zone->nr_reserved_highatomic -= min(
+ pageblock_nr_pages,
+ zone->nr_reserved_highatomic);
+ }
/*
* Convert to ac->migratetype and avoid the normal
@@ -1802,7 +1814,8 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
page = list_entry(area->free_list[fallback_mt].next,
struct page, lru);
- if (can_steal)
+ if (can_steal &&
+ get_pageblock_migratetype(page) != MIGRATE_HIGHATOMIC)
steal_suitable_fallback(zone, page, start_migratetype);
/* Remove the page from the freelists */
@@ -2240,7 +2253,8 @@ int __isolate_free_page(struct page *page, unsigned int order)
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
int mt = get_pageblock_migratetype(page);
- if (!is_migrate_isolate(mt) && !is_migrate_cma(mt))
+ if (!is_migrate_isolate(mt) && !is_migrate_cma(mt)
+ && mt != MIGRATE_HIGHATOMIC)
set_pageblock_migratetype(page,
MIGRATE_MOVABLE);
}
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 367784be5df2..f598ff80b30e 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -7,6 +7,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -61,6 +62,14 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
{
struct ieee80211_local *local = sta->local;
struct tid_ampdu_rx *tid_rx;
+ struct ieee80211_ampdu_params params = {
+ .sta = &sta->sta,
+ .action = IEEE80211_AMPDU_RX_STOP,
+ .tid = tid,
+ .amsdu = false,
+ .timeout = 0,
+ .ssn = 0,
+ };
lockdep_assert_held(&sta->ampdu_mlme.mtx);
@@ -78,8 +87,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
(int)reason);
- if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
- &sta->sta, tid, NULL, 0, false))
+ if (drv_ampdu_action(local, sta->sdata, &params))
sdata_info(sta->sdata,
"HW problem - can not stop rx aggregation for %pM tid %d\n",
sta->sta.addr, tid);
@@ -237,6 +245,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
{
struct ieee80211_local *local = sta->sdata->local;
struct tid_ampdu_rx *tid_agg_rx;
+ struct ieee80211_ampdu_params params = {
+ .sta = &sta->sta,
+ .action = IEEE80211_AMPDU_RX_START,
+ .tid = tid,
+ .amsdu = false,
+ .timeout = timeout,
+ .ssn = start_seq_num,
+ };
+
int i, ret = -EOPNOTSUPP;
u16 status = WLAN_STATUS_REQUEST_DECLINED;
@@ -275,6 +292,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
/* make sure the size doesn't exceed the maximum supported by the hw */
if (buf_size > local->hw.max_rx_aggregation_subframes)
buf_size = local->hw.max_rx_aggregation_subframes;
+ params.buf_size = buf_size;
/* examine state machine */
mutex_lock(&sta->ampdu_mlme.mtx);
@@ -322,8 +340,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
for (i = 0; i < buf_size; i++)
__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
- ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
- &sta->sta, tid, &start_seq_num, 0, false);
+ ret = drv_ampdu_action(local, sta->sdata, &params);
ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
sta->sta.addr, tid, ret);
if (ret) {
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index ff757181b0a8..4932e9f243a2 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -7,6 +7,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
{
struct ieee80211_local *local = sta->local;
struct tid_ampdu_tx *tid_tx;
- enum ieee80211_ampdu_mlme_action action;
+ struct ieee80211_ampdu_params params = {
+ .sta = &sta->sta,
+ .tid = tid,
+ .buf_size = 0,
+ .amsdu = false,
+ .timeout = 0,
+ .ssn = 0,
+ };
int ret;
lockdep_assert_held(&sta->ampdu_mlme.mtx);
@@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
case AGG_STOP_DECLINED:
case AGG_STOP_LOCAL_REQUEST:
case AGG_STOP_PEER_REQUEST:
- action = IEEE80211_AMPDU_TX_STOP_CONT;
+ params.action = IEEE80211_AMPDU_TX_STOP_CONT;
break;
case AGG_STOP_DESTROY_STA:
- action = IEEE80211_AMPDU_TX_STOP_FLUSH;
+ params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
break;
default:
WARN_ON_ONCE(1);
@@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
spin_unlock_bh(&sta->lock);
if (reason != AGG_STOP_DESTROY_STA)
return -EALREADY;
- ret = drv_ampdu_action(local, sta->sdata,
- IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
- &sta->sta, tid, NULL, 0, false);
+ params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
+ ret = drv_ampdu_action(local, sta->sdata, &params);
WARN_ON_ONCE(ret);
return 0;
}
@@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
WLAN_BACK_INITIATOR;
tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
- ret = drv_ampdu_action(local, sta->sdata, action,
- &sta->sta, tid, NULL, 0, false);
+ ret = drv_ampdu_action(local, sta->sdata, &params);
/* HW shall not deny going back to legacy */
if (WARN_ON(ret)) {
@@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
struct tid_ampdu_tx *tid_tx;
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
- u16 start_seq_num;
+ struct ieee80211_ampdu_params params = {
+ .sta = &sta->sta,
+ .action = IEEE80211_AMPDU_TX_START,
+ .tid = tid,
+ .buf_size = 0,
+ .amsdu = false,
+ .timeout = 0,
+ };
int ret;
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
@@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
*/
synchronize_net();
- start_seq_num = sta->tid_seq[tid] >> 4;
-
- ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
- &sta->sta, tid, &start_seq_num, 0, false);
+ params.ssn = sta->tid_seq[tid] >> 4;
+ ret = drv_ampdu_action(local, sdata, &params);
if (ret) {
ht_dbg(sdata,
"BA request denied - HW unavailable for %pM tid %d\n",
@@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
/* send AddBA request */
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
- tid_tx->dialog_token, start_seq_num,
+ tid_tx->dialog_token, params.ssn,
IEEE80211_MAX_AMPDU_BUF,
tid_tx->timeout);
}
@@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
struct sta_info *sta, u16 tid)
{
struct tid_ampdu_tx *tid_tx;
+ struct ieee80211_ampdu_params params = {
+ .sta = &sta->sta,
+ .action = IEEE80211_AMPDU_TX_OPERATIONAL,
+ .tid = tid,
+ .timeout = 0,
+ .ssn = 0,
+ };
lockdep_assert_held(&sta->ampdu_mlme.mtx);
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+ params.buf_size = tid_tx->buf_size;
+ params.amsdu = tid_tx->amsdu;
ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
sta->sta.addr, tid);
- drv_ampdu_action(local, sta->sdata,
- IEEE80211_AMPDU_TX_OPERATIONAL,
- &sta->sta, tid, NULL, tid_tx->buf_size,
- tid_tx->amsdu);
+ drv_ampdu_action(local, sta->sdata, &params);
/*
* synchronize with TX path, while splicing the TX path
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index ca1fe5576103..c258f1041d33 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local,
int drv_ampdu_action(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid,
- u16 *ssn, u8 buf_size, bool amsdu)
+ struct ieee80211_ampdu_params *params)
{
int ret = -EOPNOTSUPP;
@@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_local *local,
if (!check_sdata_in_driver(sdata))
return -EIO;
- trace_drv_ampdu_action(local, sdata, action, sta, tid,
- ssn, buf_size, amsdu);
+ trace_drv_ampdu_action(local, sdata, params);
if (local->ops->ampdu_action)
- ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
- sta, tid, ssn, buf_size, amsdu);
+ ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params);
trace_drv_return_int(local, ret);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 154ce4b13406..18b0d65baff0 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local)
int drv_ampdu_action(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid,
- u16 *ssn, u8 buf_size, bool amsdu);
+ struct ieee80211_ampdu_params *params);
static inline int drv_get_survey(struct ieee80211_local *local, int idx,
struct survey_info *survey)
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 56c6d6cfa5a1..913e959b03cf 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -80,7 +80,23 @@
#define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d"
#define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx
-
+#define AMPDU_ACTION_ENTRY __field(enum ieee80211_ampdu_mlme_action, \
+ ieee80211_ampdu_mlme_action) \
+ STA_ENTRY \
+ __field(u16, tid) \
+ __field(u16, ssn) \
+ __field(u8, buf_size) \
+ __field(bool, amsdu) \
+ __field(u16, timeout)
+#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \
+ __entry->tid = params->tid; \
+ __entry->ssn = params->ssn; \
+ __entry->buf_size = params->buf_size; \
+ __entry->amsdu = params->amsdu; \
+ __entry->timeout = params->timeout;
+#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
+#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \
+ __entry->buf_size, __entry->amsdu, __entry->timeout
/*
* Tracing for driver callbacks.
@@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon,
TRACE_EVENT(drv_ampdu_action,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid,
- u16 *ssn, u8 buf_size, bool amsdu),
+ struct ieee80211_ampdu_params *params),
- TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu),
+ TP_ARGS(local, sdata, params),
TP_STRUCT__entry(
LOCAL_ENTRY
- STA_ENTRY
- __field(u32, action)
- __field(u16, tid)
- __field(u16, ssn)
- __field(u8, buf_size)
- __field(bool, amsdu)
VIF_ENTRY
+ AMPDU_ACTION_ENTRY
),
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
- STA_ASSIGN;
- __entry->action = action;
- __entry->tid = tid;
- __entry->ssn = ssn ? *ssn : 0;
- __entry->buf_size = buf_size;
- __entry->amsdu = amsdu;
+ AMPDU_ACTION_ASSIGN;
),
TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
- __entry->tid, __entry->buf_size, __entry->amsdu
+ LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG
)
);
diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c
index 2999e2c15fdb..2819da9ae3f2 100644
--- a/net/rmnet_data/rmnet_data_vnd.c
+++ b/net/rmnet_data/rmnet_data_vnd.c
@@ -504,6 +504,18 @@ static void rmnet_vnd_setup(struct net_device *dev)
INIT_LIST_HEAD(&dev_conf->flow_head);
}
+/**
+ * rmnet_vnd_setup() - net_device initialization helper function
+ * @dev: Virtual network device
+ *
+ * Called during device initialization. Disables GRO.
+ */
+static void rmnet_vnd_disable_offload(struct net_device *dev)
+{
+ dev->wanted_features &= ~NETIF_F_GRO;
+ __netdev_update_features(dev);
+}
+
/* ***************** Exposed API ******************************************** */
/**
@@ -616,6 +628,8 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device,
*new_device = dev;
}
+ rmnet_vnd_disable_offload(dev);
+
LOGM("Registered device %s", dev->name);
return rc;
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 16043faba52c..14868e42f3ca 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -619,6 +619,13 @@ int wiphy_register(struct wiphy *wiphy)
!rdev->ops->set_mac_acl)))
return -EINVAL;
+ /* assure only valid behaviours are flagged by driver
+ * hence subtract 2 as bit 0 is invalid.
+ */
+ if (WARN_ON(wiphy->bss_select_support &&
+ (wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
+ return -EINVAL;
+
if (wiphy->addresses)
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index fb44fa3bf4ef..594eeea9533b 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -644,8 +644,25 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
return err;
}
- if (!ether_addr_equal(mgmt->sa, wdev_address(wdev)))
- return -EINVAL;
+ if (!ether_addr_equal(mgmt->sa, wdev_address(wdev))) {
+ /* Allow random TA to be used with Public Action frames if the
+ * driver has indicated support for this. Otherwise, only allow
+ * the local address to be used.
+ */
+ if (!ieee80211_is_action(mgmt->frame_control) ||
+ mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
+ return -EINVAL;
+ if (!wdev->current_bss &&
+ !wiphy_ext_feature_isset(
+ &rdev->wiphy,
+ NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
+ return -EINVAL;
+ if (wdev->current_bss &&
+ !wiphy_ext_feature_isset(
+ &rdev->wiphy,
+ NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
+ return -EINVAL;
+ }
/* Transmit the Action frame as requested by user space */
return rdev_mgmt_tx(rdev, wdev, params, cookie);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2d71cafde513..5ec8e5cf8a8e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -402,7 +402,12 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
[NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
+ [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
[NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
+ [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
+ [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
+ .len = sizeof(struct nl80211_bss_select_rssi_adjust)
+ },
};
/* policy for the key attributes */
@@ -487,6 +492,15 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
[NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
};
+static const struct nla_policy
+nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
+ [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
+ [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
+ [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
+ .len = sizeof(struct nl80211_bss_select_rssi_adjust)
+ },
+};
+
static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct cfg80211_registered_device **rdev,
@@ -1778,6 +1792,25 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
}
}
+ if (rdev->wiphy.bss_select_support) {
+ struct nlattr *nested;
+ u32 bss_select_support = rdev->wiphy.bss_select_support;
+
+ nested = nla_nest_start(msg, NL80211_ATTR_BSS_SELECT);
+ if (!nested)
+ goto nla_put_failure;
+
+ i = 0;
+ while (bss_select_support) {
+ if ((bss_select_support & 1) &&
+ nla_put_flag(msg, i))
+ goto nla_put_failure;
+ i++;
+ bss_select_support >>= 1;
+ }
+ nla_nest_end(msg, nested);
+ }
+
/* done */
state->split_start = 0;
break;
@@ -6087,6 +6120,73 @@ static int validate_scan_freqs(struct nlattr *freqs)
return n_channels;
}
+static bool is_band_valid(struct wiphy *wiphy, enum ieee80211_band b)
+{
+ return b < IEEE80211_NUM_BANDS && wiphy->bands[b];
+}
+
+static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
+ struct cfg80211_bss_selection *bss_select)
+{
+ struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
+ struct nlattr *nest;
+ int err;
+ bool found = false;
+ int i;
+
+ /* only process one nested attribute */
+ nest = nla_data(nla);
+ if (!nla_ok(nest, nla_len(nest)))
+ return -EINVAL;
+
+ err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest),
+ nla_len(nest), nl80211_bss_select_policy);
+ if (err)
+ return err;
+
+ /* only one attribute may be given */
+ for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
+ if (attr[i]) {
+ if (found)
+ return -EINVAL;
+ found = true;
+ }
+ }
+
+ bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
+
+ if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
+
+ if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
+ bss_select->param.band_pref =
+ nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
+ if (!is_band_valid(wiphy, bss_select->param.band_pref))
+ return -EINVAL;
+ }
+
+ if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
+ struct nl80211_bss_select_rssi_adjust *adj_param;
+
+ adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
+ bss_select->param.adjust.band = adj_param->band;
+ bss_select->param.adjust.delta = adj_param->delta;
+ if (!is_band_valid(wiphy, bss_select->param.adjust.band))
+ return -EINVAL;
+ }
+
+ /* user-space did not provide behaviour attribute */
+ if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
+ return -EINVAL;
+
+ if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
+ return -EINVAL;
+
+ return 0;
+}
+
static int nl80211_parse_random_mac(struct nlattr **attrs,
u8 *mac_addr, u8 *mac_addr_mask)
{
@@ -6557,6 +6657,12 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
return ERR_PTR(-EINVAL);
+ if (!wiphy_ext_feature_isset(
+ wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
+ (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
+ return ERR_PTR(-EINVAL);
+
request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->match_sets) * n_match_sets
@@ -6762,6 +6868,26 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
request->delay =
nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
+ if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
+ request->relative_rssi = nla_get_s8(
+ attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
+ request->relative_rssi_set = true;
+ }
+
+ if (request->relative_rssi_set &&
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
+ struct nl80211_bss_select_rssi_adjust *rssi_adjust;
+
+ rssi_adjust = nla_data(
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
+ request->rssi_adjust.band = rssi_adjust->band;
+ request->rssi_adjust.delta = rssi_adjust->delta;
+ if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
+ err = -EINVAL;
+ goto out_free;
+ }
+ }
+
err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
if (err)
goto out_free;
@@ -8349,6 +8475,21 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
}
+ if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
+ /* bss selection makes no sense if bssid is set */
+ if (connect.bssid) {
+ kzfree(connkeys);
+ return -EINVAL;
+ }
+
+ err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
+ wiphy, &connect.bss_select);
+ if (err) {
+ kzfree(connkeys);
+ return err;
+ }
+ }
+
wdev_lock(dev->ieee80211_ptr);
err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
@@ -9245,6 +9386,20 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
return -ENOBUFS;
+ if (req->relative_rssi_set) {
+ struct nl80211_bss_select_rssi_adjust rssi_adjust;
+
+ if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+ req->relative_rssi))
+ return -ENOBUFS;
+
+ rssi_adjust.band = req->rssi_adjust.band;
+ rssi_adjust.delta = req->rssi_adjust.delta;
+ if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+ sizeof(rssi_adjust), &rssi_adjust))
+ return -ENOBUFS;
+ }
+
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
if (!freqs)
return -ENOBUFS;
diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c
index 0869a862f521..cd3f08b3959d 100644
--- a/security/pfe/pfk_kc.c
+++ b/security/pfe/pfk_kc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -100,6 +100,9 @@ struct kc_entry {
struct task_struct *thread_pending;
enum pfk_kc_entry_state state;
+
+ /* ref count for the number of requests in the HW queue for this key */
+ int loaded_ref_cnt;
int scm_error;
};
@@ -520,6 +523,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
if (entry_exists) {
kc_update_timestamp(entry);
entry->state = ACTIVE_ICE_LOADED;
+
+ if (async)
+ entry->loaded_ref_cnt++;
+
break;
}
case (FREE):
@@ -529,8 +536,17 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
entry->scm_error = ret;
pr_err("%s: key load error (%d)\n", __func__, ret);
} else {
- entry->state = ACTIVE_ICE_LOADED;
kc_update_timestamp(entry);
+ entry->state = ACTIVE_ICE_LOADED;
+
+ /*
+ * only increase ref cnt for async calls,
+ * sync calls from within work thread do not pass
+ * requests further to HW
+ */
+ if (async)
+ entry->loaded_ref_cnt++;
+
}
break;
case (ACTIVE_ICE_PRELOAD):
@@ -539,6 +555,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
break;
case (ACTIVE_ICE_LOADED):
kc_update_timestamp(entry);
+
+ if (async)
+ entry->loaded_ref_cnt++;
+
break;
case(SCM_ERROR):
ret = entry->scm_error;
@@ -572,6 +592,8 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size,
const unsigned char *salt, size_t salt_size)
{
struct kc_entry *entry = NULL;
+ struct task_struct *tmp_pending = NULL;
+ int ref_cnt = 0;
if (!kc_is_ready())
return;
@@ -591,14 +613,28 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size,
if (!entry) {
kc_spin_unlock();
pr_err("internal error, there should an entry to unlock\n");
+
return;
}
- entry->state = INACTIVE;
+ ref_cnt = --entry->loaded_ref_cnt;
+
+ if (ref_cnt < 0)
+ pr_err("internal error, ref count should never be negative\n");
- /* wake-up invalidation if it's waiting for the entry to be released */
- if (entry->thread_pending) {
- wake_up_process(entry->thread_pending);
- entry->thread_pending = NULL;
+ if (!ref_cnt) {
+ entry->state = INACTIVE;
+ /*
+ * wake-up invalidation if it's waiting
+ * for the entry to be released
+ */
+ if (entry->thread_pending) {
+ tmp_pending = entry->thread_pending;
+ entry->thread_pending = NULL;
+
+ kc_spin_unlock();
+ wake_up_process(tmp_pending);
+ return;
+ }
}
kc_spin_unlock();
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
index b94001d8a6eb..85cf0eb48ee0 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -94,6 +94,7 @@ static struct snd_soc_dai_driver msm_anlg_cdc_i2s_dai[];
/* By default enable the internal speaker boost */
static bool spkr_boost_en = true;
static bool initial_boot = true;
+static bool is_ssr_en;
static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
"cdc-vdd-mic-bias",
@@ -4052,15 +4053,17 @@ int msm_anlg_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
return -ENOMEM;
}
sdm660_cdc_priv->version_entry = version_entry;
- sdm660_cdc_priv->audio_ssr_nb.notifier_call =
- sdm660_cdc_notifier_service_cb;
- ret = audio_notifier_register("pmic_analog_cdc",
- AUDIO_NOTIFIER_ADSP_DOMAIN,
- &sdm660_cdc_priv->audio_ssr_nb);
- if (ret < 0) {
- pr_err("%s: Audio notifier register failed ret = %d\n",
- __func__, ret);
- return ret;
+ if (is_ssr_en) {
+ sdm660_cdc_priv->audio_ssr_nb.notifier_call =
+ sdm660_cdc_notifier_service_cb;
+ ret = audio_notifier_register("pmic_analog_cdc",
+ AUDIO_NOTIFIER_ADSP_DOMAIN,
+ &sdm660_cdc_priv->audio_ssr_nb);
+ if (ret < 0) {
+ pr_err("%s: Audio notifier register failed ret = %d\n",
+ __func__, ret);
+ return ret;
+ }
}
return 0;
}
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
index c39b6d57f908..5c210dc2176e 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -333,21 +333,6 @@ static int msm_dig_cdc_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
return 0;
}
-static int msm_dig_cdc_codec_enable_rx_chain(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
-{
- struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
- switch (event) {
- case SND_SOC_DAPM_POST_PMD:
- snd_soc_update_bits(codec, w->reg,
- 1 << w->shift, 0x00);
- break;
- }
- return 0;
-}
-
static int msm_dig_cdc_get_iir_enable_audio_mixer(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -809,13 +794,18 @@ static int msm_dig_cdc_codec_enable_dmic(struct snd_soc_dapm_widget *w,
(*dmic_clk_cnt)++;
if (*dmic_clk_cnt == 1) {
snd_soc_update_bits(codec, dmic_clk_reg,
- 0x0E, 0x02);
+ 0x0E, 0x04);
snd_soc_update_bits(codec, dmic_clk_reg,
dmic_clk_en, dmic_clk_en);
}
snd_soc_update_bits(codec,
- MSM89XX_CDC_CORE_TX1_DMIC_CTL + (dmic - 1) * 0x20,
- 0x07, 0x02);
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x07, 0x02);
+ snd_soc_update_bits(codec,
+ MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x07, 0x02);
+ snd_soc_update_bits(codec,
+ MSM89XX_CDC_CORE_TX3_DMIC_CTL, 0x07, 0x02);
+ snd_soc_update_bits(codec,
+ MSM89XX_CDC_CORE_TX4_DMIC_CTL, 0x07, 0x02);
break;
case SND_SOC_DAPM_POST_PMD:
(*dmic_clk_cnt)--;
@@ -1556,18 +1546,9 @@ static const struct snd_soc_dapm_widget msm_dig_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_MIXER_E("RX1 CHAIN", SND_SOC_NOPM,
- 0, 0, NULL, 0,
- msm_dig_cdc_codec_enable_rx_chain,
- SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER_E("RX2 CHAIN", SND_SOC_NOPM,
- 0, 0, NULL, 0,
- msm_dig_cdc_codec_enable_rx_chain,
- SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER_E("RX3 CHAIN", SND_SOC_NOPM,
- 0, 0, NULL, 0,
- msm_dig_cdc_codec_enable_rx_chain,
- SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX3 CHAIN", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp1_mux),
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index 3228be362bab..cb201899b4b8 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -1554,6 +1554,7 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
if (mbhc->mbhc_cb->enable_mb_source)
mbhc->mbhc_cb->enable_mb_source(mbhc, true);
mbhc->btn_press_intr = false;
+ mbhc->is_btn_press = false;
wcd_mbhc_detect_plug_type(mbhc);
} else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
&& !detection_type) {
@@ -1571,6 +1572,7 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false);
mbhc->btn_press_intr = false;
+ mbhc->is_btn_press = false;
if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM,
false);
@@ -1759,6 +1761,7 @@ determine_plug:
mic_trigerred = 0;
mbhc->is_extn_cable = true;
mbhc->btn_press_intr = false;
+ mbhc->is_btn_press = false;
wcd_mbhc_detect_plug_type(mbhc);
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);
@@ -1935,15 +1938,13 @@ static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
pr_debug("%s: enter\n", __func__);
complete(&mbhc->btn_press_compl);
WCD_MBHC_RSC_LOCK(mbhc);
- /* send event to sw intr handler*/
- mbhc->is_btn_press = true;
wcd_cancel_btn_work(mbhc);
if (wcd_swch_level_remove(mbhc)) {
pr_debug("%s: Switch level is low ", __func__);
goto done;
}
- mbhc->btn_press_intr = true;
+ mbhc->is_btn_press = true;
msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
pr_debug("%s: msec_val = %ld\n", __func__, msec_val);
if (msec_val < MBHC_BUTTON_PRESS_THRESHOLD_MIN) {
@@ -1957,12 +1958,15 @@ static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
__func__);
goto done;
}
+ mask = wcd_mbhc_get_button_mask(mbhc);
+ if (mask == SND_JACK_BTN_0)
+ mbhc->btn_press_intr = true;
+
if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) {
pr_debug("%s: Plug isn't headset, ignore button press\n",
__func__);
goto done;
}
- mask = wcd_mbhc_get_button_mask(mbhc);
mbhc->buttons_pressed |= mask;
mbhc->mbhc_cb->lock_sleep(mbhc, true);
if (schedule_delayed_work(&mbhc->mbhc_btn_dwork,
@@ -1988,8 +1992,8 @@ static irqreturn_t wcd_mbhc_release_handler(int irq, void *data)
goto exit;
}
- if (mbhc->btn_press_intr) {
- mbhc->btn_press_intr = false;
+ if (mbhc->is_btn_press) {
+ mbhc->is_btn_press = false;
} else {
pr_debug("%s: This release is for fake btn press\n", __func__);
goto exit;
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 86ad8752b6ff..0030b1fcf773 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -8821,13 +8821,8 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
WCD9XXX_DIG_CORE_REGION_1);
mutex_lock(&tavil->codec_mutex);
- /*
- * Codec hardware by default comes up in SVS mode.
- * Initialize the svs_ref_cnt to 1 to reflect the hardware
- * state in the driver.
- */
- tavil->svs_ref_cnt = 1;
+ tavil_vote_svs(tavil, true);
tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
control->slim_slave->laddr;
tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
@@ -8835,17 +8830,9 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
tavil_init_slim_slave_cfg(codec);
snd_soc_card_change_online_state(codec->component.card, 1);
- /* Class-H Init */
- wcd_clsh_init(&tavil->clsh_d);
- /* Default HPH Mode to Class-H LOHiFi */
- tavil->hph_mode = CLS_H_LOHIFI;
-
for (i = 0; i < TAVIL_MAX_MICBIAS; i++)
tavil->micb_ref[i] = 0;
- for (i = 0; i < COMPANDER_MAX; i++)
- tavil->comp_enabled[i] = 0;
-
dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
__func__, control->mclk_rate);
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.h b/sound/soc/codecs/wcd9xxx-common-v2.h
index ee7e587b3f24..53c9a84b51ad 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.h
+++ b/sound/soc/codecs/wcd9xxx-common-v2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,7 +34,12 @@
#define WCD_CLSH_STATE_HPHL (0x01 << 1)
#define WCD_CLSH_STATE_HPHR (0x01 << 2)
#define WCD_CLSH_STATE_LO (0x01 << 3)
-#define WCD_CLSH_STATE_MAX 4
+
+/*
+ * Though number of CLSH states are 4, max state shoulbe be 5
+ * because state array index starts from 1.
+ */
+#define WCD_CLSH_STATE_MAX 5
#define NUM_CLSH_STATES_V2 (0x01 << WCD_CLSH_STATE_MAX)
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index bab4da4758ac..6c1897340e74 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -610,6 +610,49 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
},
{
.playback = {
+ .stream_name = "USBAUDIO_HOSTLESS Playback",
+ .aif_name = "USBAUDIO_DL_HL",
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+ SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_352800 |
+ SNDRV_PCM_RATE_384000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 384000,
+ },
+ .capture = {
+ .stream_name = "USBAUDIO_HOSTLESS Capture",
+ .aif_name = "USBAUDIO_UL_HL",
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+ SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_352800 |
+ SNDRV_PCM_RATE_384000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 384000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "USBAUDIO_HOSTLESS",
+ .probe = fe_dai_probe,
+ },
+ {
+ .playback = {
.stream_name = "AFE Playback",
.aif_name = "PCM_RX",
.rates = (SNDRV_PCM_RATE_8000 |
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 4af737680118..557c7946506a 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -3329,10 +3329,11 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
* TX14, TX15, TX16
*/
unsigned int rx_ch_tavil[WCD934X_RX_MAX] = {144, 145, 146, 147, 148,
- 149, 150, 151};
+ 149, 150, 151};
unsigned int tx_ch_tavil[WCD934X_TX_MAX] = {128, 129, 130, 131, 132,
- 134, 135, 136, 137, 138, 139,
- 133, 140, 141, 142, 143};
+ 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142,
+ 143};
pr_info("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
@@ -4983,6 +4984,22 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
.ignore_pmdown_time = 1,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
},
+ {
+ .name = "USB Audio Hostless",
+ .stream_name = "USB Audio Hostless",
+ .cpu_dai_name = "USBAUDIO_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
};
static struct snd_soc_dai_link msm_common_be_dai_links[] = {
diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
index 9b76b4892eb1..75af648baef3 100644
--- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c
+++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -119,6 +119,9 @@ size_t get_cal_info_size(int32_t cal_type)
case AFE_SIDETONE_CAL_TYPE:
size = sizeof(struct audio_cal_info_sidetone);
break;
+ case AFE_SIDETONE_IIR_CAL_TYPE:
+ size = sizeof(struct audio_cal_info_sidetone_iir);
+ break;
case LSM_CUST_TOPOLOGY_CAL_TYPE:
size = 0;
break;
@@ -265,6 +268,9 @@ size_t get_user_cal_type_size(int32_t cal_type)
case AFE_SIDETONE_CAL_TYPE:
size = sizeof(struct audio_cal_type_sidetone);
break;
+ case AFE_SIDETONE_IIR_CAL_TYPE:
+ size = sizeof(struct audio_cal_type_sidetone_iir);
+ break;
case LSM_CUST_TOPOLOGY_CAL_TYPE:
size = sizeof(struct audio_cal_type_basic);
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 9421d03f6a8d..2ba41ac1877f 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -754,7 +754,7 @@ static void populate_codec_list(struct msm_compr_audio *prtd)
COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
prtd->compr_cap.max_fragments =
COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
- prtd->compr_cap.num_codecs = 14;
+ prtd->compr_cap.num_codecs = 15;
prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
@@ -769,6 +769,7 @@ static void populate_codec_list(struct msm_compr_audio *prtd)
prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
+ prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
}
static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
@@ -788,6 +789,7 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
struct asm_alac_cfg alac_cfg;
struct asm_ape_cfg ape_cfg;
struct asm_dsd_cfg dsd_cfg;
+ struct aptx_dec_bt_addr_cfg aptx_cfg;
union snd_codec_options *codec_options;
int ret = 0;
@@ -1022,6 +1024,24 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
pr_err("%s: CMD DSD Format block failed ret %d\n",
__func__, ret);
break;
+ case FORMAT_APTX:
+ pr_debug("SND_AUDIOCODEC_APTX\n");
+ memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
+ ret = q6asm_stream_media_format_block_aptx_dec(
+ prtd->audio_client,
+ prtd->sample_rate,
+ stream_id);
+ if (ret >= 0) {
+ aptx_cfg.nap = codec_options->aptx_dec.nap;
+ aptx_cfg.uap = codec_options->aptx_dec.uap;
+ aptx_cfg.lap = codec_options->aptx_dec.lap;
+ q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
+ &aptx_cfg);
+ } else {
+ pr_err("%s: CMD Format block failed ret %d\n",
+ __func__, ret);
+ }
+ break;
default:
pr_debug("%s, unsupported format, skip", __func__);
break;
@@ -1245,8 +1265,13 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
pr_debug("%s: stream_id %d bits_per_sample %d\n",
__func__, ac->stream_id, bits_per_sample);
- ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
- bits_per_sample);
+ if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) {
+ ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
+ bits_per_sample, true);
+ } else {
+ ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
+ bits_per_sample, false);
+ }
if (ret < 0) {
pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
return ret;
@@ -1789,6 +1814,12 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
break;
}
+ case SND_AUDIOCODEC_APTX: {
+ pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
+ prtd->codec = FORMAT_APTX;
+ break;
+ }
+
default:
pr_err("codec not supported, id =%d\n", params->codec.id);
return -EINVAL;
@@ -2659,6 +2690,7 @@ static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
case SND_AUDIOCODEC_DTS:
break;
case SND_AUDIOCODEC_DSD:
+ case SND_AUDIOCODEC_APTX:
break;
default:
pr_err("%s: Unsupported audio codec %d\n",
@@ -3071,6 +3103,7 @@ static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
switch (prtd->codec) {
case FORMAT_MP3:
case FORMAT_MPEG4_AAC:
+ case FORMAT_APTX:
pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
prtd->codec);
break;
@@ -3137,6 +3170,7 @@ static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
case FORMAT_APE:
case FORMAT_DTS:
case FORMAT_DSD:
+ case FORMAT_APTX:
pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
prtd->codec);
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index df32ede49ed0..8da75d74776b 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -681,7 +681,7 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int rc = 0, port_id, copp_idx;
- uint32_t idx, j;
+ uint32_t idx, j, current_offset;
uint32_t device = ucontrol->value.integer.value[0];
uint32_t param_id = ucontrol->value.integer.value[1];
uint32_t offset = ucontrol->value.integer.value[2];
@@ -758,6 +758,19 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol,
default: {
/* cache the parameters */
dolby_dap_params_modified[idx] += 1;
+ current_offset = dolby_dap_params_offset[idx] + offset;
+ if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) {
+ pr_err("%s: invalid offset %d at idx %d\n",
+ __func__, offset, idx);
+ return -EINVAL;
+ }
+ if ((length == 0) || (current_offset + length - 1
+ < current_offset) || (current_offset + length
+ > TOTAL_LENGTH_DOLBY_PARAM)) {
+ pr_err("%s: invalid length %d at idx %d\n",
+ __func__, length, idx);
+ return -EINVAL;
+ }
dolby_dap_params_length[idx] = length;
pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
__func__, device, param_id, offset, length);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 920e7324f14a..9b672d803d31 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -423,7 +423,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
prtd->audio_client->perf_mode);
ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
- bits_per_sample);
+ bits_per_sample, false);
if (ret < 0) {
pr_err("%s: q6asm_open_read failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 485ffa06f5bd..a62420a23789 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -69,6 +69,7 @@ static int sec_mi2s_switch_enable;
static int tert_mi2s_switch_enable;
static int quat_mi2s_switch_enable;
static int fm_pcmrx_switch_enable;
+static int usb_switch_enable;
static int lsm_mux_slim_port;
static int slim0_rx_aanc_fb_port;
static int msm_route_ec_ref_rx;
@@ -721,8 +722,7 @@ static struct cal_block_data *msm_routing_find_topology_by_path(int path)
static struct cal_block_data *msm_routing_find_topology(int path,
int app_type,
- int acdb_id,
- int sample_rate)
+ int acdb_id)
{
struct list_head *ptr, *next;
struct cal_block_data *cal_block = NULL;
@@ -739,13 +739,12 @@ static struct cal_block_data *msm_routing_find_topology(int path,
cal_block->cal_info;
if ((cal_info->path == path) &&
(cal_info->app_type == app_type) &&
- (cal_info->acdb_id == acdb_id) &&
- (cal_info->sample_rate == sample_rate)) {
+ (cal_info->acdb_id == acdb_id)) {
return cal_block;
}
}
- pr_debug("%s: Can't find topology for path %d, app %d, acdb_id %d sample_rate %d defaulting to search by path\n",
- __func__, path, app_type, acdb_id, sample_rate);
+ pr_debug("%s: Can't find topology for path %d, app %d, acdb_id %d defaulting to search by path\n",
+ __func__, path, app_type, acdb_id);
return msm_routing_find_topology_by_path(path);
}
@@ -754,7 +753,7 @@ static int msm_routing_get_adm_topology(int path, int fedai_id,
{
int topology = NULL_COPP_TOPOLOGY;
struct cal_block_data *cal_block = NULL;
- int app_type = 0, acdb_dev_id = 0, sample_rate = 0;
+ int app_type = 0, acdb_dev_id = 0;
pr_debug("%s\n", __func__);
path = get_cal_path(path);
@@ -765,10 +764,8 @@ static int msm_routing_get_adm_topology(int path, int fedai_id,
app_type = fe_dai_app_type_cfg[fedai_id][session_type].app_type;
acdb_dev_id = fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id;
- sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate;
- cal_block = msm_routing_find_topology(path, app_type,
- acdb_dev_id, sample_rate);
+ cal_block = msm_routing_find_topology(path, app_type, acdb_dev_id);
if (cal_block == NULL)
goto unlock;
@@ -1695,6 +1692,35 @@ static int msm_routing_put_hfp_switch_mixer(struct snd_kcontrol *kcontrol,
return 1;
}
+static int msm_routing_get_usb_switch_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = usb_switch_enable;
+ pr_debug("%s: HFP Switch enable %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_routing_put_usb_switch_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist =
+ dapm_kcontrol_get_wlist(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_dapm_update *update = NULL;
+
+ pr_debug("%s: USB Switch enable %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ if (ucontrol->value.integer.value[0])
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol,
+ 1, update);
+ else
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol,
+ 0, update);
+ usb_switch_enable = ucontrol->value.integer.value[0];
+ return 1;
+}
+
static int msm_routing_get_pri_mi2s_switch_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -4871,6 +4897,12 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -7024,6 +7056,12 @@ static const struct snd_kcontrol_new primary_mi2s_rx_port_mixer_controls[] = {
msm_routing_put_port_mixer),
};
+static const struct snd_kcontrol_new usb_rx_port_mixer_controls[] = {
+ SOC_SINGLE_EXT("USB_AUDIO_TX", MSM_BACKEND_DAI_USB_RX,
+ MSM_BACKEND_DAI_USB_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+};
+
static const struct snd_kcontrol_new quat_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
@@ -7693,6 +7731,11 @@ static const struct snd_kcontrol_new hfp_slim7_switch_mixer_controls =
0, 1, 0, msm_routing_get_hfp_switch_mixer,
msm_routing_put_hfp_switch_mixer);
+static const struct snd_kcontrol_new usb_switch_mixer_controls =
+ SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
+ 0, 1, 0, msm_routing_get_usb_switch_mixer,
+ msm_routing_put_usb_switch_mixer);
+
static const struct soc_enum lsm_mux_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_audio_mux_text), mad_audio_mux_text);
@@ -7806,7 +7849,8 @@ static int msm_routing_put_stereo_to_custom_stereo_control(
continue;
if ((port_id != SLIMBUS_0_RX) &&
(port_id != RT_PROXY_PORT_001_RX) &&
- (port_id != AFE_PORT_ID_PRIMARY_MI2S_RX))
+ (port_id != AFE_PORT_ID_PRIMARY_MI2S_RX) &&
+ (port_id != AFE_PORT_ID_INT4_MI2S_RX))
continue;
for_each_set_bit(i, &msm_bedais[be_index].fe_sessions,
@@ -8628,6 +8672,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_AIF_IN("INTHFP_DL_HL", "INT_HFP_BT_HOSTLESS Playback",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("INTHFP_UL_HL", "INT_HFP_BT_HOSTLESS Capture",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("USBAUDIO_DL_HL", "USBAUDIO_HOSTLESS Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("USBAUDIO_UL_HL", "USBAUDIO_HOSTLESS Capture",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_I2S_DL_HL", "SEC_I2S_RX_HOSTLESS Playback",
@@ -9173,6 +9221,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
&hfp_int_switch_mixer_controls),
SND_SOC_DAPM_SWITCH("HFP_SLIM7_UL_HL", SND_SOC_NOPM, 0, 0,
&hfp_slim7_switch_mixer_controls),
+ SND_SOC_DAPM_SWITCH("USB_DL_HL", SND_SOC_NOPM, 0, 0,
+ &usb_switch_mixer_controls),
/* Mux Definitions */
SND_SOC_DAPM_MUX("LSM1 MUX", SND_SOC_NOPM, 0, 0, &lsm1_mux),
@@ -9538,6 +9588,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_MIXER("USB_AUDIO_RX_Voice Mixer",
SND_SOC_NOPM, 0, 0, usb_audio_rx_voice_mixer_controls,
ARRAY_SIZE(usb_audio_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("USB_AUDIO_RX Port Mixer",
+ SND_SOC_NOPM, 0, 0, usb_rx_port_mixer_controls,
+ ARRAY_SIZE(usb_rx_port_mixer_controls)),
/* Virtual Pins to force backends ON atm */
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_INPUT("BE_IN"),
@@ -10246,6 +10299,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia3 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
{"MultiMedia5 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia2 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
+ {"MultiMedia2 Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
{"MultiMedia2 Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
{"MultiMedia1 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -11327,6 +11382,12 @@ static const struct snd_soc_dapm_route intercon[] = {
{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"AFE_PCM_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
{"PCM_RX", NULL, "AFE_PCM_RX Port Mixer"},
+ {"USB_AUDIO_RX Port Mixer", "USB_AUDIO_TX", "USB_AUDIO_TX"},
+ {"USB_AUDIO_RX", NULL, "USB_AUDIO_RX Port Mixer"},
+ {"USB_DL_HL", "Switch", "USBAUDIO_DL_HL"},
+ {"USB_AUDIO_RX", NULL, "USB_DL_HL"},
+ {"USBAUDIO_UL_HL", NULL, "USB_AUDIO_TX"},
+
{"AUX_PCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"AUX_PCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
@@ -12050,6 +12111,33 @@ static const struct snd_kcontrol_new device_pp_params_mixer_controls[] = {
msm_routing_put_device_pp_params_mixer),
};
+static int msm_aptx_dec_license_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ core_get_license_status(ASM_MEDIA_FMT_APTX);
+ pr_debug("%s: status %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_aptx_dec_license_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int32_t status = 0;
+
+ status = core_set_license(ucontrol->value.integer.value[0],
+ APTX_CLASSIC_DEC_LICENSE_ID);
+ pr_debug("%s: status %d\n", __func__, status);
+ return status;
+}
+
+static const struct snd_kcontrol_new aptx_dec_license_controls[] = {
+ SOC_SINGLE_EXT("APTX Dec License", SND_SOC_NOPM, 0,
+ 0xFFFF, 0, msm_aptx_dec_license_control_get,
+ msm_aptx_dec_license_control_put),
+};
+
static struct snd_pcm_ops msm_routing_pcm_ops = {
.hw_params = msm_pcm_routing_hw_params,
.close = msm_pcm_routing_close,
@@ -12102,6 +12190,9 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
ARRAY_SIZE(msm_source_tracking_controls));
snd_soc_add_platform_controls(platform, adm_channel_config_controls,
ARRAY_SIZE(adm_channel_config_controls));
+
+ snd_soc_add_platform_controls(platform, aptx_dec_license_controls,
+ ARRAY_SIZE(aptx_dec_license_controls));
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 286fff1eb4a8..f3ec45b8f9b1 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -390,6 +390,33 @@ static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
return ret;
}
+static int msm_voice_sidetone_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret;
+ bool sidetone_enable = ucontrol->value.integer.value[0];
+ uint32_t session_id = ALL_SESSION_VSID;
+
+ if (sidetone_enable < 0) {
+ pr_err("%s: Invalid arguments sidetone enable %d\n",
+ __func__, sidetone_enable);
+ ret = -EINVAL;
+ return ret;
+ }
+ ret = voc_set_afe_sidetone(session_id, sidetone_enable);
+ pr_debug("%s: AFE Sidetone enable=%d session_id=0x%x ret=%d\n",
+ __func__, sidetone_enable, session_id, ret);
+ return ret;
+}
+
+static int msm_voice_sidetone_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ ucontrol->value.integer.value[0] = voc_get_afe_sidetone();
+ return 0;
+}
+
static int msm_voice_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -632,6 +659,9 @@ static struct snd_kcontrol_new msm_voice_controls[] = {
.info = msm_voice_cvd_version_info,
.get = msm_voice_cvd_version_get,
},
+ SOC_SINGLE_MULTI_EXT("Voice Sidetone Enable", SND_SOC_NOPM, 0, 1, 0, 1,
+ msm_voice_sidetone_get, msm_voice_sidetone_put),
+
};
static struct snd_pcm_ops msm_pcm_ops = {
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 4ceaa452f14b..f1607b8e5d66 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -36,6 +36,7 @@ enum {
AFE_FB_SPKR_PROT_CAL,
AFE_HW_DELAY_CAL,
AFE_SIDETONE_CAL,
+ AFE_SIDETONE_IIR_CAL,
AFE_TOPOLOGY_CAL,
AFE_CUST_TOPOLOGY_CAL,
AFE_FB_SPKR_PROT_TH_VI_CAL,
@@ -4849,58 +4850,249 @@ fail_cmd:
return ret;
}
-int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
+static int afe_sidetone_iir(u16 tx_port_id)
{
- struct afe_loopback_cfg_v1 cmd_sidetone;
- int ret = 0;
+ struct afe_loopback_iir_cfg_v2 iir_sidetone;
+ int ret;
int index = 0;
+ uint16_t size = 0;
+ int cal_index = AFE_SIDETONE_IIR_CAL;
+ int iir_pregain = 0;
+ int iir_num_biquad_stages = 0;
+ int iir_enable;
+ struct cal_block_data *cal_block;
+ int mid;
+
+ memset(&iir_sidetone, 0, sizeof(iir_sidetone));
+ index = q6audio_get_port_index(tx_port_id);
+ iir_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ iir_sidetone.hdr.pkt_size = sizeof(iir_sidetone);
+ iir_sidetone.hdr.src_port = 0;
+ iir_sidetone.hdr.dest_port = 0;
+ iir_sidetone.hdr.token = index;
+ iir_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ iir_sidetone.param.port_id = tx_port_id;
+ iir_sidetone.param.payload_address_lsw = 0x00;
+ iir_sidetone.param.payload_address_msw = 0x00;
+ iir_sidetone.param.mem_map_handle = 0x00;
- pr_info("%s: tx_port_id: 0x%x rx_port_id: 0x%x enable:%d gain:%d\n",
- __func__, tx_port_id, rx_port_id, enable, gain);
- index = q6audio_get_port_index(rx_port_id);
- if (index < 0 || index > AFE_MAX_PORTS) {
- pr_err("%s: AFE port index[%d] invalid!\n",
- __func__, index);
- return -EINVAL;
+ if (this_afe.cal_data[cal_index] == NULL) {
+ pr_err("%s: cal data is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
}
- ret = q6audio_validate_port(rx_port_id);
- if (ret < 0) {
- pr_err("%s: Invalid port 0x%x %d", __func__, rx_port_id, ret);
- return -EINVAL;
+ mutex_lock(&this_afe.cal_data[cal_index]->lock);
+ cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
+ if (cal_block == NULL) {
+ pr_err("%s: cal_block not found\n ", __func__);
+ mutex_unlock(&this_afe.cal_data[cal_index]->lock);
+ ret = -EINVAL;
+ goto done;
}
+ iir_pregain = ((struct audio_cal_info_sidetone_iir *)
+ cal_block->cal_info)->pregain;
+ iir_enable = ((struct audio_cal_info_sidetone_iir *)
+ cal_block->cal_info)->iir_enable;
+ iir_num_biquad_stages = ((struct audio_cal_info_sidetone_iir *)
+ cal_block->cal_info)->num_biquad_stages;
+ mid = ((struct audio_cal_info_sidetone_iir *)
+ cal_block->cal_info)->mid;
+
+ /*
+ * calculate the actual size of payload based on no of stages
+ * enabled in calibration
+ */
+ size = (MAX_SIDETONE_IIR_DATA_SIZE / MAX_NO_IIR_FILTER_STAGE) *
+ iir_num_biquad_stages;
+ /*
+ * For an odd number of stages, 2 bytes of padding are
+ * required at the end of the payload.
+ */
+ if (iir_num_biquad_stages % 2) {
+ pr_debug("%s: adding 2 to size:%d\n", __func__, size);
+ size = size + 2;
+ }
+ memcpy(&iir_sidetone.st_iir_filter_config_data.iir_config,
+ &((struct audio_cal_info_sidetone_iir *)
+ cal_block->cal_info)->iir_config,
+ sizeof(iir_sidetone.st_iir_filter_config_data.iir_config));
+ mutex_unlock(&this_afe.cal_data[cal_index]->lock);
+
+ /*
+ * Calculate the payload size for setparams command
+ */
+ iir_sidetone.param.payload_size = (sizeof(iir_sidetone) -
+ sizeof(struct apr_hdr) -
+ sizeof(struct afe_port_cmd_set_param_v2) -
+ (MAX_SIDETONE_IIR_DATA_SIZE - size));
+
+ pr_debug("%s: payload size :%d\n", __func__,
+ iir_sidetone.param.payload_size);
+
+ /*
+ * Set IIR enable params
+ */
+ iir_sidetone.st_iir_enable_pdata.module_id = mid;
+ iir_sidetone.st_iir_enable_pdata.param_id =
+ AFE_PARAM_ID_ENABLE;
+ iir_sidetone.st_iir_enable_pdata.param_size =
+ sizeof(iir_sidetone.st_iir_mode_enable_data);
+ iir_sidetone.st_iir_mode_enable_data.enable = iir_enable;
+
+ /*
+ * Set IIR filter config params
+ */
+ iir_sidetone.st_iir_filter_config_pdata.module_id = mid;
+ iir_sidetone.st_iir_filter_config_pdata.param_id =
+ AFE_PARAM_ID_SIDETONE_IIR_FILTER_CONFIG;
+ iir_sidetone.st_iir_filter_config_pdata.param_size =
+ sizeof(iir_sidetone.st_iir_filter_config_data.num_biquad_stages)
+ +
+ sizeof(iir_sidetone.st_iir_filter_config_data.pregain) + size;
+ iir_sidetone.st_iir_filter_config_pdata.reserved = 0;
+ iir_sidetone.st_iir_filter_config_data.num_biquad_stages =
+ iir_num_biquad_stages;
+ iir_sidetone.st_iir_filter_config_data.pregain = iir_pregain;
+ pr_debug("%s: tx(0x%x)mid(0x%x)iir_en(%d)stg(%d)gain(0x%x)size(%d)\n",
+ __func__, tx_port_id, mid,
+ iir_sidetone.st_iir_mode_enable_data.enable,
+ iir_sidetone.st_iir_filter_config_data.num_biquad_stages,
+ iir_sidetone.st_iir_filter_config_data.pregain,
+ iir_sidetone.st_iir_filter_config_pdata.param_size);
+ ret = afe_apr_send_pkt(&iir_sidetone, &this_afe.wait[index]);
+ if (ret)
+ pr_err("%s: AFE sidetone failed for tx_port(0x%x)\n",
+ __func__, tx_port_id);
+
+done:
+ return ret;
+
+}
+
+static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
+{
+ struct afe_st_loopback_cfg_v1 cmd_sidetone;
+ int ret;
+ int index;
+ int cal_index = AFE_SIDETONE_CAL;
+ int sidetone_gain;
+ int sidetone_enable;
+ struct cal_block_data *cal_block;
+ int mid = 0;
+
+ memset(&cmd_sidetone, 0, sizeof(cmd_sidetone));
+ if (this_afe.cal_data[cal_index] == NULL) {
+ pr_err("%s: cal data is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ mutex_lock(&this_afe.cal_data[cal_index]->lock);
+ cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]);
+ if (cal_block == NULL) {
+ pr_err("%s: cal_block not found\n", __func__);
+ mutex_unlock(&this_afe.cal_data[cal_index]->lock);
+ ret = -EINVAL;
+ goto done;
+ }
+ sidetone_gain = ((struct audio_cal_info_sidetone *)
+ cal_block->cal_info)->gain;
+ sidetone_enable = ((struct audio_cal_info_sidetone *)
+ cal_block->cal_info)->enable;
+ mid = ((struct audio_cal_info_sidetone *)
+ cal_block->cal_info)->mid;
+ mutex_unlock(&this_afe.cal_data[cal_index]->lock);
+
+ index = q6audio_get_port_index(tx_port_id);
cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
cmd_sidetone.hdr.src_port = 0;
cmd_sidetone.hdr.dest_port = 0;
- cmd_sidetone.hdr.token = 0;
+ cmd_sidetone.hdr.token = index;
cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
- /* should it be rx or tx port id ?? , bharath*/
cmd_sidetone.param.port_id = tx_port_id;
- /* size of data param & payload */
cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
sizeof(struct apr_hdr) -
sizeof(struct afe_port_cmd_set_param_v2));
cmd_sidetone.param.payload_address_lsw = 0x00;
cmd_sidetone.param.payload_address_msw = 0x00;
cmd_sidetone.param.mem_map_handle = 0x00;
- cmd_sidetone.pdata.module_id = AFE_MODULE_LOOPBACK;
- cmd_sidetone.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
- /* size of actual payload only */
- cmd_sidetone.pdata.param_size = cmd_sidetone.param.payload_size -
- sizeof(struct afe_port_param_data_v2);
+ cmd_sidetone.gain_pdata.module_id = AFE_MODULE_LOOPBACK;
+ cmd_sidetone.gain_pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
+ /*
+ * size of actual payload only
+ */
+ cmd_sidetone.gain_pdata.param_size = sizeof(
+ struct afe_loopback_sidetone_gain);
+ cmd_sidetone.gain_data.rx_port_id = rx_port_id;
+ cmd_sidetone.gain_data.gain = sidetone_gain;
- cmd_sidetone.loopback_cfg_minor_version =
+ cmd_sidetone.cfg_pdata.module_id = AFE_MODULE_LOOPBACK;
+ cmd_sidetone.cfg_pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
+ /*
+ * size of actual payload only
+ */
+ cmd_sidetone.cfg_pdata.param_size = sizeof(struct loopback_cfg_data);
+ cmd_sidetone.cfg_data.loopback_cfg_minor_version =
AFE_API_VERSION_LOOPBACK_CONFIG;
- cmd_sidetone.dst_port_id = rx_port_id;
- cmd_sidetone.routing_mode = LB_MODE_SIDETONE;
- cmd_sidetone.enable = enable;
+ cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
+ cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
+ cmd_sidetone.cfg_data.enable = ((enable == 1) ? sidetone_enable : 0);
+
+ pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
+ __func__, rx_port_id, tx_port_id,
+ enable, mid, sidetone_gain, sidetone_enable);
ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
if (ret)
- pr_err("%s: sidetone failed tx_port:0x%x rx_port:0x%x ret%d\n",
- __func__, tx_port_id, rx_port_id, ret);
+ pr_err("%s: AFE sidetone send failed for tx_port:%d rx_port:%d ret:%d\n",
+ __func__, tx_port_id, rx_port_id, ret);
+done:
+ return ret;
+}
+
+int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable)
+{
+ int ret;
+ int index;
+
+ index = q6audio_get_port_index(rx_port_id);
+ if (index < 0 || index > AFE_MAX_PORTS) {
+ pr_err("%s: AFE port index[%d] invalid!\n",
+ __func__, index);
+ ret = -EINVAL;
+ goto done;
+ }
+ if (q6audio_validate_port(rx_port_id) < 0) {
+ pr_err("%s: Invalid port 0x%x\n",
+ __func__, rx_port_id);
+ ret = -EINVAL;
+ goto done;
+ }
+ index = q6audio_get_port_index(tx_port_id);
+ if (index < 0 || index > AFE_MAX_PORTS) {
+ pr_err("%s: AFE port index[%d] invalid!\n",
+ __func__, index);
+ ret = -EINVAL;
+ goto done;
+ }
+ if (q6audio_validate_port(tx_port_id) < 0) {
+ pr_err("%s: Invalid port 0x%x\n",
+ __func__, tx_port_id);
+ ret = -EINVAL;
+ goto done;
+ }
+ if (enable) {
+ ret = afe_sidetone_iir(tx_port_id);
+ if (ret)
+ goto done;
+ }
+
+ ret = afe_sidetone(tx_port_id, rx_port_id, enable);
+
+done:
return ret;
}
@@ -5033,6 +5225,20 @@ int afe_validate_port(u16 port_id)
case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ case AFE_PORT_ID_INT6_MI2S_RX:
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ case AFE_PORT_ID_INT6_MI2S_TX:
{
ret = 0;
break;
@@ -6007,6 +6213,9 @@ static int get_cal_type_index(int32_t cal_type)
case AFE_SIDETONE_CAL_TYPE:
ret = AFE_SIDETONE_CAL;
break;
+ case AFE_SIDETONE_IIR_CAL_TYPE:
+ ret = AFE_SIDETONE_IIR_CAL;
+ break;
case AFE_TOPOLOGY_CAL_TYPE:
ret = AFE_TOPOLOGY_CAL;
break;
@@ -6532,6 +6741,11 @@ static int afe_init_cal_data(void)
afe_set_cal, NULL, NULL} },
{NULL, NULL, cal_utils_match_buf_num} },
+ {{AFE_SIDETONE_IIR_CAL_TYPE,
+ {NULL, NULL, NULL,
+ afe_set_cal, NULL, NULL} },
+ {NULL, NULL, cal_utils_match_buf_num} },
+
{{AFE_TOPOLOGY_CAL_TYPE,
{NULL, NULL, NULL,
afe_set_cal, NULL, NULL} },
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index cfaa562fdaba..9353b2132e15 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2442,13 +2442,14 @@ EXPORT_SYMBOL(q6asm_open_read_v3);
* @ac: Client session handle
* @format: encoder format
* @bits_per_sample: bit width of capture session
+ * @ts_mode: timestamp mode
*/
int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample)
+ uint16_t bits_per_sample, bool ts_mode)
{
return __q6asm_open_read(ac, format, bits_per_sample,
PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/,
- true/*ts_mode*/);
+ ts_mode);
}
EXPORT_SYMBOL(q6asm_open_read_v4);
@@ -2661,6 +2662,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
case FORMAT_DSD:
open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
break;
+ case FORMAT_APTX:
+ open.dec_fmt_id = ASM_MEDIA_FMT_APTX;
+ break;
default:
pr_err("%s: Invalid format 0x%x\n", __func__, format);
rc = -EINVAL;
@@ -5773,6 +5777,57 @@ done:
}
EXPORT_SYMBOL(q6asm_media_format_block_dsd);
+int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
+ uint32_t srate, int stream_id)
+{
+ struct asm_aptx_dec_fmt_blk_v2 aptx_fmt;
+ int rc = 0;
+
+ if (!ac->session) {
+ pr_err("%s: ac session invalid\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ pr_debug("%s :session[%d] rate[%d] stream_id[%d]\n",
+ __func__, ac->session, srate, stream_id);
+
+ q6asm_stream_add_hdr(ac, &aptx_fmt.hdr, sizeof(aptx_fmt), TRUE,
+ stream_id);
+ atomic_set(&ac->cmd_state, -1);
+
+ aptx_fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ aptx_fmt.fmtblk.fmt_blk_size = sizeof(aptx_fmt) - sizeof(aptx_fmt.hdr) -
+ sizeof(aptx_fmt.fmtblk);
+
+ aptx_fmt.sample_rate = srate;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &aptx_fmt);
+ if (rc < 0) {
+ pr_err("%s :Comamnd media format update failed %d\n",
+ __func__, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s :timeout. waited for FORMAT_UPDATE\n", __func__);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
static int __q6asm_ds1_set_endp_params(struct audio_client *ac, int param_id,
int param_value, int stream_id)
{
@@ -6802,6 +6857,69 @@ int q6asm_set_volume_v2(struct audio_client *ac, int volume, int instance)
return __q6asm_set_volume(ac, volume, instance);
}
+int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
+ struct aptx_dec_bt_addr_cfg *cfg)
+{
+ struct aptx_dec_bt_dev_addr paylod;
+ int sz = 0;
+ int rc = 0;
+
+ pr_debug("%s: BT addr nap %d, uap %d, lap %d\n", __func__, cfg->nap,
+ cfg->uap, cfg->lap);
+
+ if (ac == NULL) {
+ pr_err("%s: AC handle NULL\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ if (ac->apr == NULL) {
+ pr_err("%s: AC APR handle NULL\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ sz = sizeof(struct aptx_dec_bt_dev_addr);
+ q6asm_add_hdr_async(ac, &paylod.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ paylod.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ paylod.encdec.param_id = APTX_DECODER_BT_ADDRESS;
+ paylod.encdec.param_size = sz - sizeof(paylod.hdr)
+ - sizeof(paylod.encdec);
+ paylod.bt_addr_cfg.lap = cfg->lap;
+ paylod.bt_addr_cfg.uap = cfg->uap;
+ paylod.bt_addr_cfg.nap = cfg->nap;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &paylod);
+ if (rc < 0) {
+ pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
+ __func__, paylod.encdec.param_id, rc);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
+ paylod.encdec.param_id);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)),
+ paylod.encdec.param_id);
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ pr_debug("%s: set BT addr is success\n", __func__);
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_set_softpause(struct audio_client *ac,
struct asm_softpause_params *pause_param)
{
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 5cff3dd1ed4f..e7619c0ca0dd 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -5847,6 +5847,48 @@ int voc_set_hd_enable(uint32_t session_id, uint32_t enable)
return ret;
}
+int voc_set_afe_sidetone(uint32_t session_id, bool sidetone_enable)
+{
+ struct voice_data *v = NULL;
+ int ret = -EINVAL;
+ struct voice_session_itr itr;
+ u16 rx_port, tx_port;
+
+ common.sidetone_enable = sidetone_enable;
+ voice_itr_init(&itr, session_id);
+ while (voice_itr_get_next_session(&itr, &v)) {
+ if (v == NULL) {
+ pr_err("%s: invalid session_id 0x%x\n", __func__,
+ session_id);
+ ret = -EINVAL;
+ break;
+ }
+ mutex_lock(&v->lock);
+ if (v->voc_state != VOC_RUN) {
+ mutex_unlock(&v->lock);
+ continue;
+ }
+ rx_port = v->dev_rx.port_id;
+ tx_port = v->dev_tx.port_id;
+ ret = afe_sidetone_enable(tx_port, rx_port,
+ sidetone_enable);
+ if (!ret) {
+ mutex_unlock(&v->lock);
+ break;
+ }
+ mutex_unlock(&v->lock);
+ }
+ return ret;
+}
+
+bool voc_get_afe_sidetone(void)
+{
+ bool ret;
+
+ ret = common.sidetone_enable;
+ return ret;
+}
+
int voc_get_pp_enable(uint32_t session_id, uint32_t module_id)
{
struct voice_data *v = voice_get_session(session_id);
@@ -8559,6 +8601,9 @@ static int __init voice_init(void)
memset(&common.ec_media_fmt_info.channel_mapping, 0,
VSS_CHANNEL_MAPPING_SIZE);
+ /* Initialize AFE Sidetone Enable */
+ common.sidetone_enable = false;
+
/* Initialize MVS info. */
common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 9c3ec62a980d..f7ea650dfda9 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1766,6 +1766,7 @@ struct common_data {
struct vss_isoundfocus_rsp_get_sectors_t soundFocusResponse;
struct shared_mem_info source_tracking_sh_mem;
struct vss_isourcetrack_activity_data_t sourceTrackingResponse;
+ bool sidetone_enable;
};
struct voice_session_itr {
@@ -1899,4 +1900,6 @@ uint32_t voice_get_topology(uint32_t topology_idx);
int voc_set_sound_focus(struct sound_focus_param sound_focus_param);
int voc_get_sound_focus(struct sound_focus_param *soundFocusData);
int voc_get_source_tracking(struct source_tracking_param *sourceTrackingData);
+int voc_set_afe_sidetone(uint32_t session_id, bool sidetone_enable);
+bool voc_get_afe_sidetone(void);
#endif
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index 63d8598d0b92..58eb30c39764 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -2909,7 +2909,7 @@ err:
}
devm_kfree(&pdev->dev, pdata);
if (pdata->snd_card_val != INT_SND_CARD)
- msm_ext_cdc_deinit();
+ msm_ext_cdc_deinit(pdata);
return ret;
}
@@ -2921,7 +2921,7 @@ static int msm_asoc_machine_remove(struct platform_device *pdev)
if (pdata->snd_card_val == INT_SND_CARD)
mutex_destroy(&pdata->cdc_int_mclk0_mutex);
else
- msm_ext_cdc_deinit();
+ msm_ext_cdc_deinit(pdata);
msm_free_auxdev_mem(pdev);
gpio_free(pdata->us_euro_gpio);
diff --git a/sound/soc/msm/sdm660-common.h b/sound/soc/msm/sdm660-common.h
index 36c2d9b7ca4e..5742c8545b86 100644
--- a/sound/soc/msm/sdm660-common.h
+++ b/sound/soc/msm/sdm660-common.h
@@ -78,6 +78,14 @@ enum {
EXT_SND_CARD_TAVIL,
};
+struct msm_snd_interrupt {
+ void __iomem *mpm_wakeup;
+ void __iomem *intr1_cfg_apps;
+ void __iomem *lpi_gpio_intr_cfg;
+ void __iomem *lpi_gpio_cfg;
+ void __iomem *lpi_gpio_inout;
+};
+
struct msm_asoc_mach_data {
int us_euro_gpio; /* used by gpio driver API */
int hph_en1_gpio;
@@ -105,6 +113,7 @@ struct msm_asoc_mach_data {
struct mutex cdc_int_mclk0_mutex;
struct delayed_work disable_int_mclk0_work;
struct afe_clk_set digital_cdc_core_clk;
+ struct msm_snd_interrupt msm_snd_intr_lpi;
};
int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
diff --git a/sound/soc/msm/sdm660-external.c b/sound/soc/msm/sdm660-external.c
index c900ce1a0fe9..0460d7f9fc68 100644
--- a/sound/soc/msm/sdm660-external.c
+++ b/sound/soc/msm/sdm660-external.c
@@ -67,16 +67,6 @@ struct msm_asoc_wcd93xx_codec {
static struct msm_asoc_wcd93xx_codec msm_codec_fn;
static struct platform_device *spdev;
-struct msm_snd_interrupt {
- void __iomem *mpm_wakeup;
- void __iomem *intr1_cfg_apps;
- void __iomem *lpi_gpio_intr_cfg;
- void __iomem *lpi_gpio_cfg;
- void __iomem *lpi_gpio_inout;
-};
-
-static struct msm_snd_interrupt msm_snd_intr_lpi;
-
static bool is_initial_boot;
static void *def_ext_mbhc_cal(void);
@@ -1220,25 +1210,25 @@ static void msm_afe_clear_config(void)
afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
}
-static void msm_snd_interrupt_config(void)
+static void msm_snd_interrupt_config(struct msm_asoc_mach_data *pdata)
{
int val;
- val = ioread32(msm_snd_intr_lpi.mpm_wakeup);
+ val = ioread32(pdata->msm_snd_intr_lpi.mpm_wakeup);
val |= LPI_GPIO_22_WAKEUP_VAL;
- iowrite32(val, msm_snd_intr_lpi.mpm_wakeup);
+ iowrite32(val, pdata->msm_snd_intr_lpi.mpm_wakeup);
- val = ioread32(msm_snd_intr_lpi.intr1_cfg_apps);
+ val = ioread32(pdata->msm_snd_intr_lpi.intr1_cfg_apps);
val &= ~(LPI_GPIO_22_INTR1_CFG_MASK);
val |= LPI_GPIO_22_INTR1_CFG_VAL;
- iowrite32(val, msm_snd_intr_lpi.intr1_cfg_apps);
+ iowrite32(val, pdata->msm_snd_intr_lpi.intr1_cfg_apps);
iowrite32(LPI_GPIO_INTR_CFG1_VAL,
- msm_snd_intr_lpi.lpi_gpio_intr_cfg);
+ pdata->msm_snd_intr_lpi.lpi_gpio_intr_cfg);
iowrite32(LPI_GPIO22_CFG_VAL,
- msm_snd_intr_lpi.lpi_gpio_cfg);
+ pdata->msm_snd_intr_lpi.lpi_gpio_cfg);
iowrite32(LPI_GPIO22_INOUT_VAL,
- msm_snd_intr_lpi.lpi_gpio_inout);
+ pdata->msm_snd_intr_lpi.lpi_gpio_inout);
}
static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
@@ -1246,7 +1236,10 @@ static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
int ret = 0;
unsigned long timeout;
int adsp_ready = 0;
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata;
+ pdata = snd_soc_card_get_drvdata(card);
timeout = jiffies +
msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
@@ -1269,7 +1262,7 @@ static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
ret = -ETIMEDOUT;
goto err_fail;
}
- msm_snd_interrupt_config();
+ msm_snd_interrupt_config(pdata);
ret = msm_afe_set_config(codec);
if (ret)
@@ -1817,15 +1810,15 @@ int msm_ext_cdc_init(struct platform_device *pdev,
ret);
ret = 0;
}
- msm_snd_intr_lpi.mpm_wakeup =
+ pdata->msm_snd_intr_lpi.mpm_wakeup =
ioremap(TLMM_CENTER_MPM_WAKEUP_INT_EN_0, 4);
- msm_snd_intr_lpi.intr1_cfg_apps =
+ pdata->msm_snd_intr_lpi.intr1_cfg_apps =
ioremap(TLMM_LPI_DIR_CONN_INTR1_CFG_APPS, 4);
- msm_snd_intr_lpi.lpi_gpio_intr_cfg =
+ pdata->msm_snd_intr_lpi.lpi_gpio_intr_cfg =
ioremap(TLMM_LPI_GPIO_INTR_CFG1, 4);
- msm_snd_intr_lpi.lpi_gpio_cfg =
+ pdata->msm_snd_intr_lpi.lpi_gpio_cfg =
ioremap(TLMM_LPI_GPIO22_CFG, 4);
- msm_snd_intr_lpi.lpi_gpio_inout =
+ pdata->msm_snd_intr_lpi.lpi_gpio_inout =
ioremap(TLMM_LPI_GPIO22_INOUT, 4);
err:
return ret;
@@ -1835,17 +1828,18 @@ EXPORT_SYMBOL(msm_ext_cdc_init);
/**
* msm_ext_cdc_deinit - external codec machine specific deinit.
*/
-void msm_ext_cdc_deinit(void)
+void msm_ext_cdc_deinit(struct msm_asoc_mach_data *pdata)
{
- if (msm_snd_intr_lpi.mpm_wakeup)
- iounmap(msm_snd_intr_lpi.mpm_wakeup);
- if (msm_snd_intr_lpi.intr1_cfg_apps)
- iounmap(msm_snd_intr_lpi.intr1_cfg_apps);
- if (msm_snd_intr_lpi.lpi_gpio_intr_cfg)
- iounmap(msm_snd_intr_lpi.lpi_gpio_intr_cfg);
- if (msm_snd_intr_lpi.lpi_gpio_cfg)
- iounmap(msm_snd_intr_lpi.lpi_gpio_cfg);
- if (msm_snd_intr_lpi.lpi_gpio_inout)
- iounmap(msm_snd_intr_lpi.lpi_gpio_inout);
+ if (pdata->msm_snd_intr_lpi.mpm_wakeup)
+ iounmap(pdata->msm_snd_intr_lpi.mpm_wakeup);
+ if (pdata->msm_snd_intr_lpi.intr1_cfg_apps)
+ iounmap(pdata->msm_snd_intr_lpi.intr1_cfg_apps);
+ if (pdata->msm_snd_intr_lpi.lpi_gpio_intr_cfg)
+ iounmap(pdata->msm_snd_intr_lpi.lpi_gpio_intr_cfg);
+ if (pdata->msm_snd_intr_lpi.lpi_gpio_cfg)
+ iounmap(pdata->msm_snd_intr_lpi.lpi_gpio_cfg);
+ if (pdata->msm_snd_intr_lpi.lpi_gpio_inout)
+ iounmap(pdata->msm_snd_intr_lpi.lpi_gpio_inout);
+
}
EXPORT_SYMBOL(msm_ext_cdc_deinit);
diff --git a/sound/soc/msm/sdm660-external.h b/sound/soc/msm/sdm660-external.h
index 7625a24e8fae..acf5735c2502 100644
--- a/sound/soc/msm/sdm660-external.h
+++ b/sound/soc/msm/sdm660-external.h
@@ -34,7 +34,7 @@ int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
struct snd_soc_card **, struct wcd_mbhc_config *);
void msm_ext_register_audio_notifier(struct platform_device *pdev);
-void msm_ext_cdc_deinit(void);
+void msm_ext_cdc_deinit(struct msm_asoc_mach_data *pdata);
#else
inline int msm_ext_cdc_init(struct platform_device *pdev,
struct msm_asoc_mach_data *pdata,
diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c
index 4ca579694a05..c002399beb6b 100644
--- a/sound/soc/msm/sdm660-internal.c
+++ b/sound/soc/msm/sdm660-internal.c
@@ -730,6 +730,12 @@ static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec,
mutex_lock(&pdata->cdc_int_mclk0_mutex);
if (atomic_read(&pdata->int_mclk0_enabled) == false ||
int_mclk0_freq_chg) {
+ if (atomic_read(&pdata->int_mclk0_enabled)) {
+ pdata->digital_cdc_core_clk.enable = 0;
+ afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ }
pdata->digital_cdc_core_clk.clk_freq_in_hz =
clk_freq_in_hz;
pdata->digital_cdc_core_clk.enable = 1;
@@ -1089,8 +1095,7 @@ static void update_int_mi2s_clk_val(int idx, int stream)
bit_per_sample =
get_int_mi2s_bits_per_sample(int_mi2s_cfg[idx].bit_format);
int_mi2s_clk[idx].clk_freq_in_hz =
- (int_mi2s_cfg[idx].sample_rate * int_mi2s_cfg[idx].channels
- * bit_per_sample);
+ (int_mi2s_cfg[idx].sample_rate * 2 * bit_per_sample);
}
static int int_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)