List of patches for DP drivers on SnapDragon
Subsystems (5)
v2 cover List of patches for DP drivers on SnapDragon
These patches are to enable DisplayPort driver on SanpDragon.
These patches have dependency on clock driver changes that provide DP clock support.
Changes in V2:
Core Dp driver:
-- Update copyright markings on all relevant files.
-- Change pr_err() to DRM_ERROR()
-- Use APIs directly instead of function pointers.
-- Use drm_display_mode structure to store link parameters in the driver. -- Use macros for register definitions instead of hardcoded values in dp_catalog.c file. -- Replace writel_relaxed/readl_relaxed with writel/readl and remove memory barriers. -- Remove unnecessary NULL checks.
-- Use drm helper functions for dpcd read/write.
-- Use DRM_DEBUG_DP for debug msgs.
DP PLL driver:
-- Update copyright markings on all relevant files.
-- Use DRM_DEBUG_DP for debug msgs.
Chandan Uddaraju (3):
dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon
845
drm/msm/dp: add displayPort driver support
drm/msm/dp: add support for DP PLL driver
.../devicetree/bindings/display/msm/dp.txt | 249 +++ .../devicetree/bindings/display/msm/dpu.txt | 16 +- drivers/gpu/drm/msm/Kconfig | 24 + drivers/gpu/drm/msm/Makefile | 18 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 26 + drivers/gpu/drm/msm/dp/dp_aux.c | 548 +++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 37 + drivers/gpu/drm/msm/dp/dp_catalog.c | 996 ++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 108 ++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1611 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 36 + drivers/gpu/drm/msm/dp/dp_display.c | 991 ++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 31 + drivers/gpu/drm/msm/dp/dp_drm.c | 189 +++ drivers/gpu/drm/msm/dp/dp_drm.h | 20 + drivers/gpu/drm/msm/dp/dp_extcon.c | 228 +++ drivers/gpu/drm/msm/dp/dp_extcon.h | 85 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1216 +++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 132 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 504 ++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 91 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 621 ++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 199 +++ drivers/gpu/drm/msm/dp/dp_power.c | 733 +++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 52 + drivers/gpu/drm/msm/dp/dp_reg.h | 475 ++++++ drivers/gpu/drm/msm/dp/pll/dp_pll.c | 145 ++ drivers/gpu/drm/msm/dp/pll/dp_pll.h | 56 + drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c | 393 +++++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h | 86 ++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c | 522 +++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 41 + 35 files changed, 10499 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/msm/dp.txt create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h create mode 100644 drivers/gpu/drm/msm/dp/dp_display.c create mode 100644 drivers/gpu/drm/msm/dp/dp_display.h create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.c create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.h create mode 100644 drivers/gpu/drm/msm/dp/dp_link.c create mode 100644 drivers/gpu/drm/msm/dp/dp_link.h create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h create mode 100644 drivers/gpu/drm/msm/dp/dp_power.c create mode 100644 drivers/gpu/drm/msm/dp/dp_power.h create mode 100644 drivers/gpu/drm/msm/dp/dp_reg.h create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll.c create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll.h create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH v2 1/3 dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon 845
Add bindings for Snapdragon 845 DisplayPort and
display-port PLL driver.
Changes in V2:
Provide details about sel-gpio
--- .../devicetree/bindings/display/msm/dp.txt | 249 +++++++++++++++++++++ .../devicetree/bindings/display/msm/dpu.txt | 16 +- 2 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/msm/dp.txt
Documentation/devicetree/bindings/display/msm/dp.txt new file +249 -0
@@ -0,0 +1,249 @@ +Qualcomm Technologies, Inc. +DP is the master Display Port device which supports DP host controllers that are compatible with VESA Display Port interface specification. +DP Controller: Required properties: +- compatible: Should be "qcom,dp-display". +- reg: Base address and length of DP hardware's memory mapped regions. +- cell-index: Specifies the controller instance. +- reg-names: A list of strings that name the list of regs. + "dp_ahb" - DP controller memory region. + "dp_aux" - DP AUX memory region. + "dp_link" - DP link layer memory region. + "dp_p0" - DP pixel clock domain memory region. + "dp_phy" - DP PHY memory region. + "dp_ln_tx0" - USB3 DP PHY combo TX-0 lane memory region. + "dp_ln_tx1" - USB3 DP PHY combo TX-1 lane memory region. + "dp_mmss_cc" - Display Clock Control memory region. + "qfprom_physical" - QFPROM Phys memory region. + "dp_pll" - USB3 DP combo PLL memory region. + "usb3_dp_com" - USB3 DP PHY combo memory region. + "hdcp_physical" - DP HDCP memory region. +- interrupt-parent phandle to the interrupt parent device node. +- interrupts: The interrupt signal from the DP block. +- clocks: Clocks required for Display Port operation. See [1] for details on clock bindings. +- clock-names: Names of the clocks corresponding to handles. Following clocks are required: + "core_aux_clk", "core_usb_ref_clk_src","core_usb_ref_clk", "core_usb_cfg_ahb_clk", + "core_usb_pipe_clk", "ctrl_link_clk", "ctrl_link_iface_clk", "ctrl_crypto_clk", + "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent". +- pll-node: phandle to DP PLL node. +- vdda-1p2-supply: phandle to vdda 1.2V regulator node. +- vdda-0p9-supply: phandle to vdda 0.9V regulator node. +- qcom,aux-cfg0-settings: Specifies the DP AUX configuration 0 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg1-settings: Specifies the DP AUX configuration 1 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg2-settings: Specifies the DP AUX configuration 2 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg3-settings: Specifies the DP AUX configuration 3 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg4-settings: Specifies the DP AUX configuration 4 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg5-settings: Specifies the DP AUX configuration 5 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg6-settings: Specifies the DP AUX configuration 6 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg7-settings: Specifies the DP AUX configuration 7 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg8-settings: Specifies the DP AUX configuration 8 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg9-settings: Specifies the DP AUX configuration 9 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,max-pclk-frequency-khz: An integer specifying the maximum. pixel clock in KHz supported by Display Port. +- extcon: Phandle for the external connector class interface. +- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the a particular "type" of DP module. The module "types" + can be "core", "ctrl", and "phy". Within the same type, + there can be more than one instance of this binding, + in which case the entry would be appended with the + supply entry index. + e.g. qcom,ctrl-supply-entry@0 + -- qcom,supply-name: name of the supply (vdd/vdda/vddio) + -- qcom,supply-min-voltage: minimum voltage level (uV) + -- qcom,supply-max-voltage: maximum voltage level (uV) + -- qcom,supply-enable-load: load drawn (uA) from enabled supply + -- qcom,supply-disable-load: load drawn (uA) from disabled supply + -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on + -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on + -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off + -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off +- pinctrl-names: List of names to assign mdss pin states defined in pinctrl device node + Refer to pinctrl-bindings.txt +- pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin + controller. These pin configurations are installed in the pinctrl + device node. Refer to pinctrl-bindings.txt +DP Endpoint properties: + - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's + input endpoint. For port@1, set to the DPU interface output. See [2] for + device graph info. + +Optional properties: +- qcom,aux-en-gpio: Specifies the aux-channel enable gpio. +- qcom,aux-sel-gpio: Specifies the mux-selection that might be needed for aux interface. + + +DP PLL: Required properties: +- compatible: Should be "qcom,dp-pll-10nm". +- reg: Base address and length of DP hardware's memory mapped regions. +- cell-index: Specifies the PLL instance. +- reg-names: A list of strings that name the list of regs. + "pll_base" - DP PLL memory region. + "phy_base" - DP PHY memory region. + "ln_tx0_base" - USB3 DP PHY combo TX-0 lane memory region. + "ln_tx1_base" - USB3 DP PHY combo TX-1 lane memory region. + "gdsc_base" - gdsc memory region. +- interrupt-parent phandle to the interrupt parent device node. +- interrupts: The interrupt signal from the DP block. +- clocks: Clocks required for Display Port operation. See [1] for details on clock bindings. +- clock-names: Names of the clocks corresponding to handles. Following clocks are required: + "iface_clk", "ref_clk", cfg_ahb_clk", "pipe_clk". +- clock-rate: Initial clock rate to be configured. For the shared clocks, the default value is set to zero so that minimum clock value is configured. Non-zero clock + value can be used to configure DP pixel clock. + + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/graph.txt + +Example: + msm_dp: dp_display@ae90000{ + cell-index = <0>; + compatible = "qcom,dp-display"; + + reg = <0 0x90000 0x0dc>, + <0 0x90200 0x0c0>, + <0 0x90400 0x508>, + <0 0x90a00 0x094>, + <1 0xeaa00 0x200>, + <1 0xea200 0x200>, + <1 0xea600 0x200>, + <2 0x02000 0x1a0>, + <3 0x00000 0x621c>, + <1 0xea000 0x180>, + <1 0xe8000 0x20>, + <4 0xe1000 0x034>; + reg-names = "dp_ahb", "dp_aux", "dp_link", + "dp_p0", "dp_phy", "dp_ln_tx0", "dp_ln_tx1", + "dp_mmss_cc", "qfprom_physical", "dp_pll", + "usb3_dp_com", "hdcp_physical"; + + interrupt-parent = <&mdss>; + interrupts = <12 0>; + + extcon = <&usb_1_ssphy>; + clocks = <&dispcc DISP_CC_MDSS_DP_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>, + <&dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; + clock-names = "core_aux_clk", "core_ref_clk_src", + "core_usb_ref_clk", "core_usb_cfg_ahb_clk", + "core_usb_pipe_clk", "ctrl_link_clk", + "ctrl_link_iface_clk", "ctrl_pixel_clk", + "crypto_clk", "pixel_clk_rcg"; + + pll-node = <&dp_pll>; + qcom,aux-cfg0-settings = [20 00]; + qcom,aux-cfg1-settings = [24 13 23 1d]; + qcom,aux-cfg2-settings = [28 24]; + qcom,aux-cfg3-settings = [2c 00]; + qcom,aux-cfg4-settings = [30 0a]; + qcom,aux-cfg5-settings = [34 26]; + qcom,aux-cfg6-settings = [38 0a]; + qcom,aux-cfg7-settings = [3c 03]; + qcom,aux-cfg8-settings = [40 bb]; + qcom,aux-cfg9-settings = [44 03]; + + qcom,max-pclk-frequency-khz = <675000>; + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda-1p2"; + qcom,supply-min-voltage = <1200000>; + qcom,supply-max-voltage = <1200000>; + qcom,supply-enable-load = <21800>; + qcom,supply-disable-load = <4>; + }; + }; + + qcom,phy-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,phy-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda-0p9"; + qcom,supply-min-voltage = <880000>; + qcom,supply-max-voltage = <880000>; + qcom,supply-enable-load = <36000>; + qcom,supply-disable-load = <32>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + dp_out: endpoint { + }; + }; + }; + }; + + dp_pll: dp-pll@c011000 { + compatible = "qcom,dp-pll-10nm"; + label = "DP PLL"; + cell-index = <0>; + #clock-cells = <1>; + + reg = <1 0xea000 0x200>, + <1 0xeaa00 0x200>, + <1 0xea200 0x200>, + <1 0xea600 0x200>, + <2 0x03000 0x8>; + reg-names = "pll_base", "phy_base", "ln_tx0_base", + "ln_tx1_base", "gdsc_base"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "iface_clk", "ref_clk", + "cfg_ahb_clk", "pipe_clk"; + clock-rate = <0>; + + };
Documentation/devicetree/bindings/display/msm/dpu.txt +12 -4
@@ -58,8 +58,9 @@ Required properties: Documentation/devicetree/bindings/graph.txt Documentation/devicetree/bindings/media/video-interfaces.txt - Port 0 -> DPU_INTF1 (DSI1) - Port 1 -> DPU_INTF2 (DSI2) + Port 0 -> DPU_INTF0 (DP) + Port 1 -> DPU_INTF1 (DSI1) + Port 2 -> DPU_INTF2 (DSI2) Optional properties: - assigned-clocks: list of clock specifiers for clocks needing rate assignment
@@ -115,13 +116,20 @@ Example: port@0 { reg = <0>; - dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + dpu_intf0_out: endpoint { + remote-endpoint = <&dp_in>; }; }; port@1 { reg = <1>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@2 { + reg = <2>; dpu_intf2_out: endpoint { remote-endpoint = <&dsi1_in>; };
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 2/3 drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveAdd the needed displayPort files to enable DP driver on msm target.
"dp_display" module is the main module that calls into other sub-modules. "dp_drm" file represents the interface between DRM framework and DP driver.
changes in v2:
-- Update copyright markings on all relevant files.
-- Change pr_err() to DRM_ERROR()
-- Use APIs directly instead of function pointers.
-- Use drm_display_mode structure to store link parameters in the driver. -- Use macros for register definitions instead of hardcoded values. -- Replace writel_relaxed/readl_relaxed with writel/readl
and remove memory barriers.
-- Remove unnecessary NULL checks.
-- Use drm helper functions for dpcd read/write.
-- Use DRM_DEBUG_DP for debug msgs.
--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 12 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 26 + drivers/gpu/drm/msm/dp/dp_aux.c | 548 +++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 37 + drivers/gpu/drm/msm/dp/dp_catalog.c | 996 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 108 ++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1611 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 36 + drivers/gpu/drm/msm/dp/dp_display.c | 941 ++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 28 + drivers/gpu/drm/msm/dp/dp_drm.c | 189 ++++ drivers/gpu/drm/msm/dp/dp_drm.h | 20 + drivers/gpu/drm/msm/dp/dp_extcon.c | 228 ++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 85 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1216 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 132 +++ drivers/gpu/drm/msm/dp/dp_panel.c | 504 +++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 91 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 621 +++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 196 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 733 ++++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 51 + drivers/gpu/drm/msm/dp/dp_reg.h | 475 ++++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 41 + 28 files changed, 8958 insertions(+) create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h create mode 100644 drivers/gpu/drm/msm/dp/dp_display.c create mode 100644 drivers/gpu/drm/msm/dp/dp_display.h create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.c create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.h create mode 100644 drivers/gpu/drm/msm/dp/dp_link.c create mode 100644 drivers/gpu/drm/msm/dp/dp_link.h create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h create mode 100644 drivers/gpu/drm/msm/dp/dp_power.c create mode 100644 drivers/gpu/drm/msm/dp/dp_power.h create mode 100644 drivers/gpu/drm/msm/dp/dp_reg.h
drivers/gpu/drm/msm/Kconfig +9 -0
@@ -49,6 +49,15 @@ config DRM_MSM_HDMI_HDCP help Choose this option to enable HDCP state machine +config DRM_MSM_DP + bool "Enable DP support in MSM DRM driver" + depends on DRM_MSM + default n + help + Compile in support for DP driver in msm drm driver. DP external + display support is enabled through this config option. It can + be primary or secondary display on device. + config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSM
drivers/gpu/drm/msm/Makefile +12 -0
@@ -2,6 +2,7 @@ ccflags-y := -Idrivers/gpu/drm/msm ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi +ccflags-$(CONFIG_DRM_MSM_DP) += -Idrivers/gpu/drm/msm/dp msm-y := \ adreno/adreno_device.o \
@@ -96,6 +97,17 @@ msm-y := \ msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ + dp/dp_catalog.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o \ + dp/dp_extcon.o \ + dp/dp_link.o \ + dp/dp_panel.o \ + dp/dp_parser.o \ + dp/dp_power.o + msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +20 -0
@@ -991,6 +991,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,trace_dpu_enc_mode_set (DRMID (drm_enc)); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) +msm_dp_display_mode_set (priv->dp, drm_enc, mode, adj_mode); +list_for_each_entry (conn_iter, connector_list, head)if (conn_iter->encoder == drm_enc) conn = conn_iter;
@@ -1114,6 +1117,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) {struct dpu_encoder_virt *dpu_enc =NULL ;int ret =0 ; +struct msm_drm_private *priv;struct drm_display_mode *cur_mode =NULL ;if (!drm_enc) {
@@ -1124,6 +1128,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)mutex_lock (&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + priv = drm_enc->dev->dev_private;trace_dpu_enc_enable (DRMID (drm_enc), cur_mode->hdisplay, cur_mode->vdisplay);
@@ -1144,6 +1149,15 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)_dpu_encoder_virt_enable_helper (drm_enc); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { + ret =msm_dp_display_enable (priv->dp, + drm_enc); +if (ret) { +DPU_ERROR_ENC (dpu_enc,"dp display enable failed: %d\n" , + ret); + goto out; + } + } dpu_enc->enabled = true; out:
@@ -1180,6 +1194,12 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; dpu_kms =to_dpu_kms (priv->kms); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { +if (msm_dp_display_disable (priv->dp, drm_enc)) { +DPU_ERROR_ENC (dpu_enc,"dp display disable failed\n" ); +return ; + } + }trace_dpu_enc_disable (DRMID (drm_enc));/* wait for idle */
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +2 -0
@@ -14,7 +14,9 @@#include <linux/clk.h> #include <linux/clk/clk-conf.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/delay.h> +#include <drm/drmP.h> #include <drm/drm_print.h>
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +26 -0
@@ -15,6 +15,7 @@#include <linux/gpio.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/types.h> #define DEV_DBG(fmt, args...) pr_debug(fmt, ##args)
@@ -22,6 +23,29 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args) +struct dss_io_data { +u32 len; +void __iomem *base; +}; + +enum dss_vreg_type { +DSS_REG_LDO , +DSS_REG_VS , +}; + +struct dss_vreg { +struct regulator *vreg;/* vreg handle */ +char vreg_name[32 ]; +int min_voltage; +int max_voltage; +int enable_load; +int disable_load; +int pre_on_sleep; +int post_on_sleep; +int pre_off_sleep; +int post_off_sleep; +}; +struct dss_gpio {unsigned int gpio;unsigned int value;
@@ -42,6 +66,8 @@ struct dss_clk { };struct dss_module_power { +unsigned int num_vreg; +struct dss_vreg *vreg_config;unsigned int num_gpio;struct dss_gpio *gpio_config;unsigned int num_clk;
drivers/gpu/drm/msm/dp/dp_aux.c new file +548 -0
548 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_aux.h new file +37 -0
@@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#ifndef _DP_AUX_H_ +#define _DP_AUX_H_ + +#include "dp_catalog.h" +#include <drm/drm_dp_helper.h> + +enum dp_aux_error { +DP_AUX_ERR_NONE =0 , +DP_AUX_ERR_ADDR =-1 , +DP_AUX_ERR_TOUT =-2 , +DP_AUX_ERR_NACK =-3 , +DP_AUX_ERR_DEFER =-4 , +DP_AUX_ERR_NACK_DEFER =-5 , +}; + +struct dp_aux { +struct drm_dp_aux *drm_aux; +struct dp_aux_cfg *cfg; +}; + +int dp_aux_register (struct dp_aux *aux); +void dp_aux_unregister (struct dp_aux *aux); +void dp_aux_isr (struct dp_aux *aux); +void dp_aux_init (struct dp_aux *aux,struct dp_aux_cfg *aux_cfg); +void dp_aux_deinit (struct dp_aux *aux); +void dp_aux_reconfig (struct dp_aux *aux); + +struct dp_aux *dp_aux_get (struct device *dev,struct dp_catalog_aux *catalog, +struct dp_aux_cfg *aux_cfg); +void dp_aux_put (struct dp_aux *aux); + +#endif /*__DP_AUX_H_*/
drivers/gpu/drm/msm/dp/dp_catalog.c new file +996 -0
996 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_catalog.h new file +108 -0
108 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1611 -0
1,169 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +36 -0
Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.c new file +941 -0
941 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_display.h new file +28 -0
Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.c new file +189 -0
189 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_drm.h new file +20 -0
Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.c new file +228 -0
228 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_extcon.h new file +85 -0
85 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_link.c new file +1216 -0
1,216 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_link.h new file +132 -0
132 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_panel.c new file +504 -0
504 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_panel.h new file +91 -0
91 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_parser.c new file +621 -0
621 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_parser.h new file +196 -0
196 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_power.c new file +733 -0
733 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_power.h new file +51 -0
51 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_reg.h new file +475 -0
475 lines not on this page · raw message
drivers/gpu/drm/msm/msm_drv.h +41 -0
41 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Part of the diff is not shown here. View the raw message.
PATCH v2 3/3 drm/msm/dp: add support for DP PLL driver
In reply to Chandan UddarajuAdd the needed DP PLL specific files to support
display port interface on msm targets.
The DP driver calls the DP PLL driver registration. The DP driver sets the link and pixel clock sources.
Changes in v2:
-- Update copyright markings on all relevant files. -- Use DRM_DEBUG_DP for debug msgs.
--- drivers/gpu/drm/msm/Kconfig | 15 + drivers/gpu/drm/msm/Makefile | 6 + drivers/gpu/drm/msm/dp/dp_display.c | 50 +++ drivers/gpu/drm/msm/dp/dp_display.h | 3 + drivers/gpu/drm/msm/dp/dp_parser.h | 3 + drivers/gpu/drm/msm/dp/dp_power.h | 1 + drivers/gpu/drm/msm/dp/pll/dp_pll.c | 145 +++++++ drivers/gpu/drm/msm/dp/pll/dp_pll.h | 56 +++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c | 393 +++++++++++++++++++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h | 86 +++++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c | 522 ++++++++++++++++++++++++++ 11 files changed, 1280 insertions(+) create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll.c create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll.h create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h create mode 100644 drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c
drivers/gpu/drm/msm/Kconfig +15 -0
@@ -58,6 +58,21 @@ config DRM_MSM_DP display support is enabled through this config option. It can be primary or secondary display on device. +config DRM_MSM_DP_PLL + bool "Enable DP PLL driver in MSM DRM" + depends on DRM_MSM_DP && COMMON_CLK + default y + help + Choose this option to enable DP PLL driver which provides DP + source clocks under common clock framework. + +config DRM_MSM_DP_10NM_PLL + bool "Enable DP 10nm PLL driver in MSM DRM (used by SDM845)" + depends on DRM_MSM_DP + default y + help + Choose this option if DP PLL on SDM845 is used on the platform. + config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSM
drivers/gpu/drm/msm/Makefile +6 -0
@@ -137,4 +137,10 @@ msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o endif +ifeq ($(CONFIG_DRM_MSM_DP_PLL),y) +msm-y += dp/pll/dp_pll.o +msm-y += dp/pll/dp_pll_10nm.o +msm-y += dp/pll/dp_pll_10nm_util.o +endif + obj-$(CONFIG_DRM_MSM) += msm.o
drivers/gpu/drm/msm/dp/dp_display.c +50 -0
74 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_display.h +3 -0
@@ -25,4 +25,7 @@ int dp_display_get_modes(struct msm_dp *dp_display,bool dp_display_check_video_test (struct msm_dp *dp_display);int dp_display_get_test_bpp (struct msm_dp *dp_display); +void __init msm_dp_pll_driver_register (void ); +void __exit msm_dp_pll_driver_unregister(void); +#endif /* _DP_DISPLAY_H_ */
drivers/gpu/drm/msm/dp/dp_parser.h +3 -0
@@ -7,6 +7,7 @@#define _DP_PARSER_H_#include "dpu_io_util.h" +#include "pll/dp_pll.h" #define DP_LABEL "MDSS DP DISPLAY"#define AUX_CFG_LEN 10
@@ -166,6 +167,8 @@ struct dp_parser {struct dp_pinctrl pinctrl;struct dp_io io;struct dp_display_data disp_data; +struct msm_dp_pll *pll; +struct device *pll_dev;u8 l_map[4 ];struct dp_aux_cfg aux_cfg[AUX_CFG_LEN ];
drivers/gpu/drm/msm/dp/dp_power.h +1 -0
@@ -14,6 +14,7 @@* @init: initializes the regulators/core clocks/GPIOs/pinctrl * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl * @clk_enable: enable/disable the DP clocks +* @set_link_clk_parent: set the parent of DP link clock * @set_pixel_clk_parent: set the parent of DP pixel clock */ struct dp_power {
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +145 -0
145 lines not on this page · raw message
drivers/gpu/drm/msm/dp/pll/dp_pll.h new file +56 -0
56 lines not on this page · raw message
drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c new file +393 -0
393 lines not on this page · raw message
drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h new file +86 -0
86 lines not on this page · raw message
drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c new file +522 -0
522 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [DPU PATCH v2 3/3] drm/msm/dp: add support for DP PLL driver
Hi Chandan
A few comments in the following.
Mostly nitpicks / style stuff, not a throughly review.
Sam
drivers/gpu/drm/msm/Kconfig config DRM_MSM_DP · line 62
Quoted 2 lines
drivers/gpu/drm/msm/Kconfig +2
-0+config DRM_MSM_DP_PLL + bool "Enable DP PLL driver in MSM DRM"
So DRM_MSM_DP_PLL cannot be 'm'.
drivers/gpu/drm/msm/Makefile msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o · line 144
Quoted 11 lines
drivers/gpu/drm/msm/Makefile +5
-0@@ -137,4 +137,10 @@ msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o endif +ifeq ($(CONFIG_DRM_MSM_DP_PLL),y) +msm-y += dp/pll/dp_pll.o +msm-y += dp/pll/dp_pll_10nm.o +msm-y += dp/pll/dp_pll_10nm_util.o +endif
Please write this in the Kbuild caninical style like this:
msm-$(DRM_MSM_DP_PLL) += dp/pll/dp_pll.o msm-$(DRM_MSM_DP_PLL) += dp/pll/dp_pll_10nm.o etc.
Or even better - descend into msm/dp/pll to build it - this is normal kernel style.
Quoted 11 lines
drivers/gpu/drm/msm/Makefile +11
-0+ if (!dp_parser) { + DRM_ERROR("Parser not initialized.\n"); + return -EINVAL; + } + + pll_node = of_parse_phandle(pdev->dev.of_node, "pll-node", 0); + if (!pll_node) { + DRM_DEV_ERROR(&pdev->dev, "cannot find pll device\n"); + return -ENXIO; + } +
drivers/gpu/drm/msm/Makefile msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o
Quoted 10 lines
drivers/gpu/drm/msm/Makefile +10
-0+ pll_pdev = of_find_device_by_node(pll_node); + if (pll_pdev) + dp_parser->pll = platform_get_drvdata(pll_pdev); + + of_node_put(pll_node); + + if (!pll_pdev || !dp_parser->pll) { + DRM_DEV_ERROR(&pdev->dev, "%s: pll driver is not ready\n", __func__); + return -EPROBE_DEFER; + }
The use of DRM_*ERROR is inconsistent.
In one place DRM_ERROR is used, and string ends with '.'
In one place DRM_DEV_ERROR is used with a simple string.
In one place DRM_DEV_ERROR is used where the __func__ is added as parameter. When reading the code such inconsistencies makes it harder to follow the code.
Quoted 10 lines
drivers/gpu/drm/msm/Makefile +6
-0+ + dp_parser->pll_dev = get_device(&pll_pdev->dev); + + return 0; +} + static irqreturn_t dp_display_irq(int irq, void *dev_id) { struct dp_display_private *dp = dev_id;
drivers/gpu/drm/msm/Makefile static int dp_display_bind(struct device *dev, struct device *master, · line 161
Quoted 6 lines
drivers/gpu/drm/msm/Makefile +3
-0@@ -114,6 +156,12 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } + rc = dp_get_pll(dp); + if (rc) { + DRM_ERROR(" DP get PLL instance failed\n");
Any reason why the error is indented with a space? Also, is the DRM*ERROR in dp_get_pll() not enough?
drivers/gpu/drm/msm/dp/dp_power.h line 20
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.h +1
-0@@ -14,6 +14,7 @@* @init: initializes the regulators/core clocks/GPIOs/pinctrl * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl * @clk_enable: enable/disable the DP clocks +* @set_link_clk_parent: set the parent of DP link clock * @set_pixel_clk_parent: set the parent of DP pixel clock */ struct dp_power {
This chunk is unrelated - it just added some missing doc. Do it belong in another patch?
Quoted 17 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +11
-0@@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +*/ + +#include "dp_pll.h" + +int msm_dp_pll_util_parse_dt_clock (struct platform_device *pdev, +struct msm_dp_pll *pll) +{ +u32 i =0 , rc =0 ;
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 21
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+struct dss_module_power *mp = &pll->mp; +const char *clock_name; +u32 clock_rate; + + mp->num_clk =of_property_count_strings (pdev->dev.of_node, +"clock-names" ); +if (mp->num_clk <=0 ) { +DRM_ERROR ("clocks are not defined\n" ); + goto clk_err; + }
You have a pdev->dev, so use DRM_DEV_ERROR()
Quoted 14 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +14
-0+ +struct msm_dp_pll *msm_dp_pll_init (struct platform_device *pdev, +enum msm_dp_pll_type type,int id) +{ +struct device *dev = &pdev->dev; +struct msm_dp_pll *pll; + +switch (type) { +case MSM_DP_PLL_10NM : + pll =msm_dp_pll_10nm_init (pdev, id); +break ; +default : + pll =ERR_PTR (-ENXIO ); +break ;
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 73
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+ } + +if (IS_ERR (pll)) { +DRM_DEV_ERROR (dev,"%s: failed to init DP PLL\n" , __func__); +return pll; + } + + pll->type = type; + +DBG ("DP:%d PLL registered" , id);
Avoid rolling your own DEBUG macros.
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 83
Quoted 8 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +8
-0+} + +static const struct of_device_id dp_pll_dt_match[] = { +#ifdef CONFIG_DRM_MSM_DP_10NM_PLL + { .compatible ="qcom,dp-pll-10nm" }, +#endif + {} +};
We only have one entry here.
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ +static int dp_pll_driver_probe (struct platform_device *pdev) +{ +struct msm_dp_pll *pll; +struct device *dev = &pdev->dev; +const struct of_device_id *match;
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 99
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+enum msm_dp_pll_type type; + + match =of_match_node (dp_pll_dt_match, dev->of_node); +if (!match) +return -ENODEV ; + +if (!strcmp (match->compatible,"qcom,dp-pll-10nm" )) + type =MSM_DP_PLL_10NM ; +else + type =MSM_DP_PLL_MAX ;
So the if will always be true, because we can only match one compatible - no?
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 105
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ + pll =msm_dp_pll_init (pdev, type,0 ); +if (IS_ERR_OR_NULL (pll)) { +dev_info (dev, +"%s: pll init failed: %ld, need separate pll clk driver\n" , + __func__,PTR_ERR (pll));
dev_info => DRM_DEV_ERROR
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 119
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+static int dp_pll_driver_remove (struct platform_device *pdev) +{ +struct msm_dp_pll *pll =platform_get_drvdata (pdev); + +if (pll) { +//msm_dsi_pll_destroy(pll);
Debug artifact?
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 84
Quoted 3 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +3
-0+#define PLL_REG_W (base, offset, data) \ + writel_relaxed((data), (base) + (offset)) +#define PLL_REG_R (base, offset) readl_relaxed((base) + (offset))
I recall you wrote in the commit message that the _relaxed variants was dropped?
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 90
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ +struct msm_dp_pll *msm_dp_pll_init (struct platform_device *pdev, +enum msm_dp_pll_type type,int id); + +int msm_dp_pll_util_parse_dt_clock (struct platform_device *pdev, +struct msm_dp_pll *pll);
Indent of sencond line with additional function arguments has inconsistent indent.
Follwo same style in all files, preferable the DRM style.
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 99
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +9
-0+ +#ifdef CONFIG_DRM_MSM_DP_10NM_PLL +struct msm_dp_pll *msm_dp_pll_10nm_init (struct platform_device *pdev,int id); +#else +struct msm_dp_pll *msm_dp_pll_10nm_init (struct platform_device *pdev,int id) +{ +return ERR_PTR (-ENODEV ); +} +#endif
I cannot see how this works if CONFIG_DRM_MSM_DP_10NM_PLL is not defined. It looks like you have both a function in a header (no static inline?) and a function with the same name in a .c file.
Maybe this driver was not built without the CONFIG_DRM_MSM_DP_10NM_PLL set to y?
Quoted 38 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +38
-0+/* +* Display Port PLL driver block diagram for branch clocks +* +* +------------------------------+ +* | DP_VCO_CLK | +* | | +* | +-------------------+ | +* | | (DP PLL/VCO) | | +* | +---------+---------+ | +* | v | +* | +----------+-----------+ | +* | | hsclk_divsel_clk_src | | +* | +----------+-----------+ | +* +------------------------------+ +* | +* +------------<---------v------------>----------+ +* | | +* +-----v------------+ | +* | dp_link_clk_src | | +* | divsel_ten | | +* +---------+--------+ | +* | | +* | | +* v v +* Input to DISPCC block | +* for link clk, crypto clk | +* and interface clock | +* | +* | +* +--------<------------+-----------------+---<---+ +* | | | +* +-------v------+ +--------v-----+ +--------v------+ +* | vco_divided | | vco_divided | | vco_divided | +* | _clk_src | | _clk_src | | _clk_src | +* | | | | | | +* |divsel_six | | divsel_two | | divsel_four | +* +-------+------+ +-----+--------+ +--------+------+ +* | | |
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+* v------->----------v-------------<------v +* | +* +----------+---------+ +* | vco_divided_clk | +* | _src_mux | +* +---------+----------+ +* | +* v +* Input to DISPCC block +* for DP pixel clock
Nice drawing!
Try to avoid mixing space and tabs in the above.
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 8 lines
+ *
+ */drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/regmap.h> +#include <linux/clk.h>
Please sort in alphabetic order.
Quoted 1 line
+/* Op structures */
Op => Ops?
Quoted 4 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +4
-0+} + +static int clk_mux_determine_rate (struct clk_hw *hw, +struct clk_rate_request *req)
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+{ +int ret =0 ; + + ret =__clk_mux_determine_rate_closest (hw, req); +if (ret) +return ret; + +/* Set the new parent of mux if there is a new valid parent */ +if (hw->clk && req->best_parent_hw->clk) +clk_set_parent (hw->clk, req->best_parent_hw->clk);
Should you check error code here?
Quoted 14 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +14
-0+ +return 0 ; +} + +} + +static int dp_pll_10nm_register (struct dp_pll_10nm *pll_10nm) +{ +char clk_name[32 ], parent[32 ], vco_name[32 ]; +struct clk_init_data vco_init = { + .parent_names = (const char *[]){"bi_tcxo" }, + .num_parents =1 , + .name = vco_name, + .flags =CLK_IGNORE_UNUSED ,
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+ .ops = &dp_10nm_vco_clk_ops, + }; +struct device *dev = &pll_10nm->pdev->dev; +struct clk_hw **hws = pll_10nm->hws; +struct clk_hw_onecell_data *hw_data; +struct clk_hw *hw; +int num =0 ; +int ret; + +DBG ("DP->id = %d" , pll_10nm->id);
Avoid own DBG macros.
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +2
-0+ +DBG ("DP PLL%d" , id);
Again.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [DPU PATCH v2 2/3] drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveQuoted 77 lines · Chandan Uddaraju
Add the needed displayPort files to enable DP driver on msm target.
"
dp_display" module is the main module that calls into other sub-modules. "dp_drm" file represents the interface between DRM framework and DP driver.changes in v2:
-- Update copyright markings on all relevant files.
-- Changepr_err()toDRM_ERROR()
-- Use APIs directly instead of function pointers.
-- Usedrm_display_modestructure to store link parameters in the driver. -- Use macros for register definitions instead of hardcoded values. -- Replace writel_relaxed/readl_relaxed with writel/readl
and remove memory barriers.
-- Remove unnecessary NULL checks.
-- Use drm helper functions for dpcd read/write.
-- UseDRM_DEBUG_DPfor debug msgs.Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 12 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 26 + drivers/gpu/drm/msm/dp/dp_aux.c | 548 +++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 37 + drivers/gpu/drm/msm/dp/dp_catalog.c | 996 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 108 ++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1611 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 36 + drivers/gpu/drm/msm/dp/dp_display.c | 941 ++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 28 + drivers/gpu/drm/msm/dp/dp_drm.c | 189 ++++ drivers/gpu/drm/msm/dp/dp_drm.h | 20 + drivers/gpu/drm/msm/dp/dp_extcon.c | 228 ++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 85 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1216 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 132 +++ drivers/gpu/drm/msm/dp/dp_panel.c | 504 +++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 91 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 621 +++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 196 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 733 ++++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 51 + drivers/gpu/drm/msm/dp/dp_reg.h | 475 ++++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 41 + 28 files changed, 8958 insertions(+) create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h create mode 100644 drivers/gpu/drm/msm/dp/dp_display.c create mode 100644 drivers/gpu/drm/msm/dp/dp_display.h create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.c create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.h create mode 100644 drivers/gpu/drm/msm/dp/dp_link.c create mode 100644 drivers/gpu/drm/msm/dp/dp_link.h create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h create mode 100644 drivers/gpu/drm/msm/dp/dp_power.c create mode 100644 drivers/gpu/drm/msm/dp/dp_power.h create mode 100644 drivers/gpu/drm/msm/dp/dp_reg.hdrivers/gpu/drm/msm/Kconfig +0
-0
drivers/gpu/drm/msm/Kconfig config DRM_MSM_HDMI_HDCP · line 55
Quoted 7 lines
drivers/gpu/drm/msm/Kconfig +4
-0@@ -49,6 +49,15 @@ config DRM_MSM_HDMI_HDCP help Choose this option to enable HDCP state machine +config DRM_MSM_DP + bool "Enable DP support in MSM DRM driver" + depends on DRM_MSM + default n
default 'n' is the default so you shouldn't need this.
Quoted 102 lines
drivers/gpu/drm/msm/Kconfig +5
-0+ help + Compile in support for DP driver in msm drm driver. DP external + display support is enabled through this config option. It can + be primary or secondary display on device. + config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSMdrivers/gpu/drm/msm/Makefile +12
-0@@ -2,6 +2,7 @@ ccflags-y := -Idrivers/gpu/drm/msm ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi +ccflags-$(CONFIG_DRM_MSM_DP) += -Idrivers/gpu/drm/msm/dp msm-y := \ adreno/adreno_device.o \@@ -96,6 +97,17 @@ msm-y := \ msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ + dp/dp_catalog.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o \ + dp/dp_extcon.o \ + dp/dp_link.o \ + dp/dp_panel.o \ + dp/dp_parser.o \ + dp/dp_power.o + msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.odrivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +20
-0@@ -991,6 +991,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,trace_dpu_enc_mode_set (DRMID (drm_enc)); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) +msm_dp_display_mode_set (priv->dp, drm_enc, mode, adj_mode); +list_for_each_entry (conn_iter, connector_list, head)if (conn_iter->encoder == drm_enc) conn = conn_iter;@@ -1114,6 +1117,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) {struct dpu_encoder_virt *dpu_enc =NULL ;int ret =0 ; +struct msm_drm_private *priv;struct drm_display_mode *cur_mode =NULL ;if (!drm_enc) {@@ -1124,6 +1128,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)mutex_lock (&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + priv = drm_enc->dev->dev_private;trace_dpu_enc_enable (DRMID (drm_enc), cur_mode->hdisplay, cur_mode->vdisplay);@@ -1144,6 +1149,15 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)_dpu_encoder_virt_enable_helper (drm_enc); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { + ret =msm_dp_display_enable (priv->dp, + drm_enc); +if (ret) { +DPU_ERROR_ENC (dpu_enc,"dp display enable failed: %d\n" , + ret); + goto out; + } + } dpu_enc->enabled = true; out:@@ -1180,6 +1194,12 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; dpu_kms =to_dpu_kms (priv->kms); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { +if (msm_dp_display_disable (priv->dp, drm_enc)) { +DPU_ERROR_ENC (dpu_enc,"dp display disable failed\n" ); +return ; + } + }trace_dpu_enc_disable (DRMID (drm_enc));/* wait for idle */ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +0
-0
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 19
Quoted 6 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +2
-0@@ -14,7 +14,9 @@#include <linux/clk.h> #include <linux/clk/clk-conf.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/delay.h> +#include <drm/drmP.h>
What are these for? There aren't any other changes to the file. The second one especially shouldn't be needed for this particular file.
Quoted 66 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +0
-0#include <drm/drm_print.h> drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +26
-0@@ -15,6 +15,7 @@#include <linux/gpio.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/types.h> #define DEV_DBG(fmt, args...) pr_debug(fmt, ##args)@@ -22,6 +23,29 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args) +struct dss_io_data { +u32 len; +void __iomem *base; +}; + +enum dss_vreg_type { +DSS_REG_LDO , +DSS_REG_VS , +}; + +struct dss_vreg { +struct regulator *vreg;/* vreg handle */ +char vreg_name[32 ]; +int min_voltage; +int max_voltage; +int enable_load; +int disable_load; +int pre_on_sleep; +int post_on_sleep; +int pre_off_sleep; +int post_off_sleep; +}; +struct dss_gpio {unsigned int gpio;unsigned int value;@@ -42,6 +66,8 @@ struct dss_clk { };struct dss_module_power { +unsigned int num_vreg; +struct dss_vreg *vreg_config;unsigned int num_gpio;struct dss_gpio *gpio_config;unsigned int num_clk;drivers/gpu/drm/msm/dp/dp_aux.c new file +6
-0@@ -0,0 +1,548 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__
drivers/gpu/drm/msm/dp/dp_aux.c line 16
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ +#include <linux/delay.h> + +#include "dp_aux.h" + +#define DP_AUX_ENUM_STR (x) #x + +enum { +DP_AUX_DATA_INDEX_WRITE =BIT (31 ), +};
An anonymous enum of 1 isn't useful, especially when it is for an obvious bitmask. This would do better as a #define
Quoted 29 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +29
-0+ +struct dp_aux_private { +struct device *dev; +struct dp_aux dp_aux; +struct dp_catalog_aux *catalog; + +struct mutex mutex; +struct completion comp; + +u32 aux_error_num; +u32 retry_cnt; +bool cmd_busy; +bool native; +bool read; +bool no_send_addr; +bool no_send_stop; +u32 offset; +u32 segment; + +struct drm_dp_aux drm_aux; +}; + +static char *dp_aux_get_error (u32 aux_error) +{ +switch (aux_error) { +case DP_AUX_ERR_NONE : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NONE ); +case DP_AUX_ERR_ADDR : +return DP_AUX_ENUM_STR (DP_AUX_ERR_ADDR );
drivers/gpu/drm/msm/dp/dp_aux.c line 55
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+case DP_AUX_ERR_TOUT : +return DP_AUX_ENUM_STR (DP_AUX_ERR_TOUT ); +case DP_AUX_ERR_NACK : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NACK ); +case DP_AUX_ERR_DEFER : +return DP_AUX_ENUM_STR (DP_AUX_ERR_DEFER ); +case DP_AUX_ERR_NACK_DEFER : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NACK_DEFER ); +default : +return "unknown" ;
From the rest of the code context, it seems like this isn't possible? You always set the error to a known value.
drivers/gpu/drm/msm/dp/dp_aux.c line 57
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +2
-0+ } +}
This function goes out of its way to try to use stringification which seems unnecessary and doesn't save you any keystrokes. return "DP_AUX_ERR_NONE" works just as well;
drivers/gpu/drm/msm/dp/dp_aux.c line 64
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +7
-0+ +static u32 dp_aux_write (struct dp_aux_private *aux, +struct drm_dp_aux_msg *msg) +{ +u32 data[4 ], reg, len; +u8 *msgdata = msg->buffer; +int const aux_cmd_fifo_len =128 ;
Please don't use const registers. If you have to use a #define but its also okay to use constant numbers for things like this.
drivers/gpu/drm/msm/dp/dp_aux.c line 76
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +12
-0+int i =0 ; + +if (aux->read) + len =4 ; +else + len = msg->size +4 ; + +/* +* cmd fifo only has depth of 144 bytes +* limit buf length to 128 bytes here +*/ +if (len > aux_cmd_fifo_len) {
Especially here, where you specifically mention that you are limiting to 128 bytes. It is a lot easier to read if (len > 128) than it is to go back and figure out what aux_cmd_fifo_len is.
drivers/gpu/drm/msm/dp/dp_aux.c line 77
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+DRM_ERROR ("buf len error\n" );
Perhaps more information is useful here if this is an expected runtime issue. If this is just a potential developer mistake a WARN_ON() would be better than a custom string.
Quoted 42 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +42
-0+return 0 ; + } + +/* Pack cmd and write to HW */ + data[0 ] = (msg->address >>16 ) &0xf ;/* addr[19:16] */ +if (aux->read) + data[0 ] |=BIT (4 );/* R/W */ + + data[1 ] = (msg->address >>8 ) &0xff ;/* addr[15:8] */ + data[2 ] = msg->address &0xff ;/* addr[7:0] */ + data[3 ] = (msg->size -1 ) &0xff ;/* len[7:0] */ + +for (i =0 ; i < len; i++) { + reg = (i <4 ) ? data[i] : msgdata[i -4 ]; + reg = ((reg) <<8 ) &0x0000ff00 ;/* index = 0, write */ +if (i ==0 ) + reg |=DP_AUX_DATA_INDEX_WRITE ; + aux->catalog->data = reg; +dp_catalog_aux_write_data (aux->catalog); + } + +dp_catalog_aux_clear_trans (aux->catalog, false); + + reg =0 ;/* Transaction number == 1 */ +if (!aux->native) {/* i2c */ + reg |=BIT (8 ); + +if (aux->no_send_addr) + reg |=BIT (10 ); + +if (aux->no_send_stop) + reg |=BIT (11 ); + } + + reg |=BIT (9 ); + aux->catalog->data = reg; +dp_catalog_aux_write_trans (aux->catalog); + +return len; +} + +static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
drivers/gpu/drm/msm/dp/dp_aux.c line 129
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ struct drm_dp_aux_msg *msg) +{ +u32 ret =0 , len =0 , timeout; +int const aux_timeout_ms =HZ /4 ; + +reinit_completion (&aux->comp); + + len =dp_aux_write (aux, msg); +if (len ==0 ) { +DRM_ERROR ("DP AUX write failed\n" );
There is only one way for dp_aux_write() to fail, and that path already prints a log message. Another one is not needed.
Quoted 41 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +41
-0+return -EINVAL ; + } + + timeout =wait_for_completion_timeout (&aux->comp, aux_timeout_ms); +if (!timeout) { +DRM_ERROR ("aux %s timeout\n" , (aux->read ?"read" :"write" )); +return -ETIMEDOUT ; + } + +if (aux->aux_error_num ==DP_AUX_ERR_NONE ) { + ret = len; + }else { +DRM_ERROR_RATELIMITED ("aux err: %s\n" , +dp_aux_get_error (aux->aux_error_num)); + + ret = -EINVAL ; + } + +return ret; +} + +static void dp_aux_cmd_fifo_rx (struct dp_aux_private *aux, +struct drm_dp_aux_msg *msg) +{ +u32 data; +u8 *dp; +u32 i, actual_i; +u32 len = msg->size; + +dp_catalog_aux_clear_trans (aux->catalog, true); + + data =0 ; + data |=DP_AUX_DATA_INDEX_WRITE ;/* INDEX_WRITE */ + data |=BIT (0 );/* read */ + + aux->catalog->data = data; +dp_catalog_aux_write_data (aux->catalog); + + dp = msg->buffer; + +/* discard first byte */
drivers/gpu/drm/msm/dp/dp_aux.c line 180
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ data =dp_catalog_aux_read_data (aux->catalog); + +for (i =0 ; i < len; i++) { + data =dp_catalog_aux_read_data (aux->catalog); + *dp++ = (u8)((data >>8 ) &0xff ); + + actual_i = (data >>16 ) &0xFF ; +if (i != actual_i) +pr_warn ("Index mismatch: expected %d, found %d\n" , + i, actual_i);
This should match the other DRM_ macros. A more informative error message would be nice - I'm not quite sure from the code context what a index mismatch is or how it could possibly happen.
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +39
-0+ } +} + +static void dp_aux_native_handler (struct dp_aux_private *aux) +{ +u32 isr = aux->catalog->isr; + +if (isr &DP_INTR_AUX_I2C_DONE ) + aux->aux_error_num =DP_AUX_ERR_NONE ; +else if (isr &DP_INTR_WRONG_ADDR ) + aux->aux_error_num =DP_AUX_ERR_ADDR ; +else if (isr &DP_INTR_TIMEOUT ) + aux->aux_error_num =DP_AUX_ERR_TOUT ; +if (isr &DP_INTR_NACK_DEFER ) + aux->aux_error_num =DP_AUX_ERR_NACK ; + +complete (&aux->comp); +} + +static void dp_aux_i2c_handler (struct dp_aux_private *aux) +{ +u32 isr = aux->catalog->isr; + +if (isr &DP_INTR_AUX_I2C_DONE ) { +if (isr & (DP_INTR_I2C_NACK |DP_INTR_I2C_DEFER )) + aux->aux_error_num =DP_AUX_ERR_NACK ; +else + aux->aux_error_num =DP_AUX_ERR_NONE ; + }else { +if (isr &DP_INTR_WRONG_ADDR ) + aux->aux_error_num =DP_AUX_ERR_ADDR ; +else if (isr &DP_INTR_TIMEOUT ) + aux->aux_error_num =DP_AUX_ERR_TOUT ; +if (isr &DP_INTR_NACK_DEFER ) + aux->aux_error_num =DP_AUX_ERR_NACK_DEFER ; +if (isr &DP_INTR_I2C_NACK ) + aux->aux_error_num =DP_AUX_ERR_NACK ; +if (isr &DP_INTR_I2C_DEFER ) + aux->aux_error_num =DP_AUX_ERR_DEFER ;
drivers/gpu/drm/msm/dp/dp_aux.c line 229
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ } + +complete (&aux->comp); +} + +static void dp_aux_update_offset_and_segment (struct dp_aux_private *aux, +struct drm_dp_aux_msg *input_msg) +{ +u32 const edid_address =0x50 ; +u32 const segment_address =0x30 ;
As above, prefer if you used #define or inline constants rather than const here and throughout this code.
Quoted 230 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +230
-0+bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); +u8 *data =NULL ; + +if (aux->native || i2c_read || ((input_msg->address != edid_address) && + (input_msg->address != segment_address))) +return ; + + + data = input_msg->buffer; +if (input_msg->address == segment_address) + aux->segment = *data; +else + aux->offset = *data; +} + +/** +* dp_aux_transfer_helper() - helper function for EDID read transactions +* +* @aux: DP AUX private structure +* @input_msg: input message from DRM upstream APIs +* +* return: void +* +* This helper function is used to fix EDID reads for non-compliant +* sinks that do not handle the i2c middle-of-transaction flag correctly. +*/ +static void dp_aux_transfer_helper (struct dp_aux_private *aux, +struct drm_dp_aux_msg *input_msg) +{ +struct drm_dp_aux_msg helper_msg; +u32 const message_size =0x10 ; +u32 const segment_address =0x30 ; +bool i2c_mot = input_msg->request &DP_AUX_I2C_MOT ; +bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); + +if (!i2c_mot || !i2c_read || (input_msg->size ==0 )) +return ; + + aux->read = false; + aux->cmd_busy = true; + aux->no_send_addr = true; + aux->no_send_stop = true; + +/* +* Send the segment address for every i2c read in which the +* middle-of-tranaction flag is set. This is required to support EDID +* reads of more than 2 blocks as the segment address is reset to 0 +* since we are overriding the middle-of-transaction flag for read +* transactions. +*/ +memset (&helper_msg,0 ,sizeof (helper_msg)); + helper_msg.address = segment_address; + helper_msg.buffer = &aux->segment; + helper_msg.size =1 ; +dp_aux_cmd_fifo_tx (aux, &helper_msg); + +/* +* Send the offset address for every i2c read in which the +* middle-of-transaction flag is set. This will ensure that the sink +* will update its read pointer and return the correct portion of the +* EDID buffer in the subsequent i2c read trasntion triggered in the +* native AUX transfer function. +*/ +memset (&helper_msg,0 ,sizeof (helper_msg)); + helper_msg.address = input_msg->address; + helper_msg.buffer = &aux->offset; + helper_msg.size =1 ; +dp_aux_cmd_fifo_tx (aux, &helper_msg); + aux->offset += message_size; + +if (aux->offset ==0x80 || aux->offset ==0x100 ) + aux->segment =0x0 ;/* reset segment at end of block */ +} + +/* +* This function does the real job to process an AUX transaction. +* It will call aux_reset() function to reset the AUX channel, +* if the waiting is timeout. +*/ +static ssize_t dp_aux_transfer (struct drm_dp_aux *drm_aux, +struct drm_dp_aux_msg *msg) +{ +ssize_t ret; +int const aux_cmd_native_max =16 ; +int const aux_cmd_i2c_max =128 ; +int const retry_count =5 ; +struct dp_aux_private *aux =container_of (drm_aux, + struct dp_aux_private, drm_aux); + +mutex_lock (&aux->mutex); + + aux->native = msg->request & (DP_AUX_NATIVE_WRITE &DP_AUX_NATIVE_READ ); + +/* Ignore address only message */ +if ((msg->size ==0 ) || (msg->buffer ==NULL )) { + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_ACK :DP_AUX_I2C_REPLY_ACK ; + ret = msg->size; + goto unlock_exit; + } + +/* msg sanity check */ +if ((aux->native && (msg->size > aux_cmd_native_max)) || + (msg->size > aux_cmd_i2c_max)) { +DRM_ERROR ("%s: invalid msg: size(%zu), request(%x)\n" , + __func__, msg->size, msg->request); + ret = -EINVAL ; + goto unlock_exit; + } + +dp_aux_update_offset_and_segment (aux, msg); +dp_aux_transfer_helper (aux, msg); + + aux->read = msg->request & (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); + aux->cmd_busy = true; + +if (aux->read) { + aux->no_send_addr = true; + aux->no_send_stop = false; + }else { + aux->no_send_addr = true; + aux->no_send_stop = true; + } + + ret =dp_aux_cmd_fifo_tx (aux, msg); +if ((ret <0 ) && aux->native) { + aux->retry_cnt++; +if (!(aux->retry_cnt % retry_count)) +dp_catalog_aux_update_cfg (aux->catalog, + aux->dp_aux.cfg,PHY_AUX_CFG1 ); +dp_catalog_aux_reset (aux->catalog); + goto unlock_exit; + }else if (ret <0 ) { + goto unlock_exit; + } + +if (aux->aux_error_num ==DP_AUX_ERR_NONE ) { +if (aux->read) +dp_aux_cmd_fifo_rx (aux, msg); + + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_ACK :DP_AUX_I2C_REPLY_ACK ; + }else { +/* Reply defer to retry */ + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_DEFER :DP_AUX_I2C_REPLY_DEFER ; + } + +/* Return requested size for success or retry */ + ret = msg->size; + aux->retry_cnt =0 ; + +unlock_exit: + aux->cmd_busy = false; +mutex_unlock (&aux->mutex); +return ret; +} + +static void dp_aux_reset_phy_config_indices (struct dp_aux_cfg *aux_cfg) +{ +int i =0 ; + +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) + aux_cfg[i].current_index =0 ; +} + +void dp_aux_isr (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_catalog_aux_get_irq (aux->catalog, aux->cmd_busy); + +if (!aux->cmd_busy) +return ; + +if (aux->native) +dp_aux_native_handler (aux); +else +dp_aux_i2c_handler (aux); +} + +void dp_aux_reconfig (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_catalog_aux_update_cfg (aux->catalog, + dp_aux->cfg,PHY_AUX_CFG1 ); +dp_catalog_aux_reset (aux->catalog); +} + +void dp_aux_init (struct dp_aux *dp_aux,struct dp_aux_cfg *aux_cfg) +{ +struct dp_aux_private *aux; + +if (!dp_aux || !aux_cfg) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_aux_reset_phy_config_indices (aux_cfg); +dp_catalog_aux_setup (aux->catalog, aux_cfg); +dp_catalog_aux_reset (aux->catalog); +dp_catalog_aux_enable (aux->catalog, true); + aux->retry_cnt =0 ; +} + +void dp_aux_deinit (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); +
drivers/gpu/drm/msm/dp/dp_aux.c line 469
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+dp_catalog_aux_enable (aux->catalog, false); +} + +int dp_aux_register (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; +int ret =0 ; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" );
This can just be return -EINVAL;
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +3
-0+ ret = -EINVAL ; + goto exit; + }
drivers/gpu/drm/msm/dp/dp_aux.c line 482
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->drm_aux.name ="dpu_dp_aux" ; + aux->drm_aux.dev = aux->dev; + aux->drm_aux.transfer = dp_aux_transfer; + ret =drm_dp_aux_register (&aux->drm_aux); +if (ret) { +DRM_ERROR ("%s: failed to register drm aux: %d\n" , __func__, ret); + goto exit;
This can just be return ret;
drivers/gpu/drm/msm/dp/dp_aux.c line 486
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +4
-0+ } + dp_aux->drm_aux = &aux->drm_aux; +exit: +return ret;
The label can go away and this will be just return 0;
drivers/gpu/drm/msm/dp/dp_aux.c line 494
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +8
-0+} + +void dp_aux_unregister (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" );
A error message isn't needed here, you can just quietly return.
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +6
-0+return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); +drm_dp_aux_unregister (&aux->drm_aux); +}
drivers/gpu/drm/msm/dp/dp_aux.c line 510
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ +struct dp_aux *dp_aux_get (struct device *dev,struct dp_catalog_aux *catalog, +struct dp_aux_cfg *aux_cfg) +{ +int rc =0 ; +struct dp_aux_private *aux; +struct dp_aux *dp_aux; + +if (!catalog || !aux_cfg) { +DRM_ERROR ("invalid input\n" );
This can just be return ERR_PTR(-ENODEV);
drivers/gpu/drm/msm/dp/dp_aux.c line 516
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +6
-0+ rc = -ENODEV ; + goto error; + } + + aux =devm_kzalloc (dev,sizeof (*aux),GFP_KERNEL ); +if (!aux) {
This can just be return ERR_PTR(-ENOMEM);
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +7
-0+ rc = -ENOMEM ; + goto error; + } + +init_completion (&aux->comp); + aux->cmd_busy = false; +mutex_init (&aux->mutex);
drivers/gpu/drm/msm/dp/dp_aux.c line 533
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ + aux->dev = dev; + aux->catalog = catalog; + aux->dp_aux.cfg = aux_cfg; + dp_aux = &aux->dp_aux; + aux->retry_cnt =0 ; + +return dp_aux; +error: +return ERR_PTR (rc);
Label is not needed
drivers/gpu/drm/msm/dp/dp_aux.c line 545
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +12
-0+} + +void dp_aux_put (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) +return ; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +mutex_destroy (&aux->mutex);
You shouldn't need this if the memory is being freed immediately after this.
drivers/gpu/drm/msm/dp/dp_aux.c line 547
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+devm_kfree (aux->dev, aux);
You shouldn't need to call this if this function is only being called right before the component or device is removed. If that isn't the case (i.e. the memory is being allocated and freed during runtime) then don't use devm_.
If devm_ is indeed appropriate then none of this function is useful and it can be removed.
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_aux.h new file +9
-0@@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#ifndef _DP_AUX_H_ +#define _DP_AUX_H_ + +#include "dp_catalog.h"
drivers/gpu/drm/msm/dp/dp_aux.h line 19
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.h new file +10
-0+#include <drm/drm_dp_helper.h> + +enum dp_aux_error { +DP_AUX_ERR_NONE =0 , +DP_AUX_ERR_ADDR =-1 , +DP_AUX_ERR_TOUT =-2 , +DP_AUX_ERR_NACK =-3 , +DP_AUX_ERR_DEFER =-4 , +DP_AUX_ERR_NACK_DEFER =-5 , +};
For me, a enum with negative values is never useful because it wouldn't take advantage of any of the limited features of an enum. This can just as easily be #define.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_aux.h new file +18
-0+ +struct dp_aux { +struct drm_dp_aux *drm_aux; +struct dp_aux_cfg *cfg; +}; + +int dp_aux_register (struct dp_aux *aux); +void dp_aux_unregister (struct dp_aux *aux); +void dp_aux_isr (struct dp_aux *aux); +void dp_aux_init (struct dp_aux *aux,struct dp_aux_cfg *aux_cfg); +void dp_aux_deinit (struct dp_aux *aux); +void dp_aux_reconfig (struct dp_aux *aux); + +struct dp_aux *dp_aux_get (struct device *dev,struct dp_catalog_aux *catalog, +struct dp_aux_cfg *aux_cfg); +void dp_aux_put (struct dp_aux *aux); + +#endif /*__DP_AUX_H_*/ drivers/gpu/drm/msm/dp/dp_catalog.c new file +16
-0@@ -0,0 +1,996 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <drm/drm_dp_helper.h> + +#include "dp_catalog.h" +#include "dp_reg.h" + +#define POLLING_SLEEP_US 1000 +#define POLLING_TIMEOUT_US 10000
drivers/gpu/drm/msm/dp/dp_catalog.c line 26
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +#define REFTIMER_DEFAULT_VALUE 0x20000 +#define SCRAMBLER_RESET_COUNT_VALUE 0xFC + +#define dp_catalog_get_priv (x) { \ + struct dp_catalog *dp_catalog; \ + dp_catalog = container_of(x, struct dp_catalog, x); \ + catalog = container_of(dp_catalog, struct dp_catalog_private, \ + dp_catalog); \ +}
This should be a static inline function.
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +27
-0+#define DP_INTERRUPT_STATUS1 \ + (DP_INTR_AUX_I2C_DONE| \ + DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ + DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ + DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ + DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) + +#define DP_INTERRUPT_STATUS1_MASK (DP_INTERRUPT_STATUS1 << 2) + +#define DP_INTERRUPT_STATUS2 \ + (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ + DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) + +#define DP_INTERRUPT_STATUS2_MASK (DP_INTERRUPT_STATUS2 << 2) + +static u8 const vm_pre_emphasis[4 ][4 ] = { + {0x00 ,0x0B ,0x12 ,0xFF },/* pe0, 0 db */ + {0x00 ,0x0A ,0x12 ,0xFF },/* pe1, 3.5 db */ + {0x00 ,0x0C ,0xFF ,0xFF },/* pe2, 6.0 db */ + {0xFF ,0xFF ,0xFF ,0xFF }/* pe3, 9.5 db */ +}; + +/* voltage swing, 0.2v and 1.0v are not support */ +static u8 const vm_voltage_swing[4 ][4 ] = { + {0x07 ,0x0F ,0x14 ,0xFF },/* sw0, 0.4v */ + {0x11 ,0x1D ,0x1F ,0xFF },/* sw1, 0.6 v */ + {0x18 ,0x1F ,0xFF ,0xFF },/* sw1, 0.8 v */
drivers/gpu/drm/msm/dp/dp_catalog.c line 64
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ {0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ +}; + +struct dp_catalog_private { +struct device *dev; +struct dp_io *io; +struct dp_catalog dp_catalog; +}; + +static inline u32 dp_read_aux (struct dp_catalog_private *catalog,u32 offset)
Don't mark this inline, let the compiler decide, here and for all the following functions.
Quoted 115 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +115
-0+{ +return readl_relaxed (catalog->io->dp_aux.base + offset); +} + +static inline void dp_write_aux (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure aux reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_aux.base + offset); +} + +static inline u32 dp_read_ahb (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_ahb.base + offset); +} + +static inline void dp_write_ahb (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure phy reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_ahb.base + offset); +} + +static inline u32 dp_read_cc (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_cc_io.base + offset); +} + +static inline void dp_write_phy (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure phy reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->phy_io.base + offset); +} + +static inline void dp_write_pll (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->dp_pll_io.base + offset); +} + +static inline void dp_write_ln_tx0 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->ln_tx0_io.base + offset); +} + +static inline void dp_write_ln_tx1 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->ln_tx1_io.base + offset); +} + +static inline void dp_write_usb_cm (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure usb reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->usb3_dp_com.base + offset); +} + +static inline void dp_write_p0 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure interface reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_p0.base + offset); +} + +static inline u32 dp_read_link (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_link.base + offset); +} + +static inline void dp_write_link (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure link reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_link.base + offset); +} + +/* aux related catalog functions */ +u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux) +{ +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return 0 ; + } + +dp_catalog_get_priv (aux); + +return dp_read_aux (catalog,REG_DP_AUX_DATA ); +} + +int dp_catalog_aux_write_data (struct dp_catalog_aux *aux) +{ +int rc =0 ;
drivers/gpu/drm/msm/dp/dp_catalog.c line 189
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (aux); +dp_write_aux (catalog,REG_DP_AUX_DATA , aux->data); +return rc;
rc is only used to return 0 so you don't need it, and just return 0;
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+} + +int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux) +{ +int rc =0 ;
drivers/gpu/drm/msm/dp/dp_catalog.c line 204
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (aux); +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL , aux->data); +return rc;
Same as above.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +13
-0+} + +int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read) +{ +int rc =0 ; +u32 data =0 ; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } +
drivers/gpu/drm/msm/dp/dp_catalog.c line 227
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_catalog_get_priv (aux); + +if (read) { + data =dp_read_aux (catalog,REG_DP_AUX_TRANS_CTRL ); + data &= ~DP_AUX_TRANS_CTRL_GO ; +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL , data); + }else { +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL ,0 ); + } +return rc;
Same as above.
Quoted 129 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +129
-0+} + +void dp_catalog_aux_reset (struct dp_catalog_aux *aux) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux_ctrl =dp_read_aux (catalog,REG_DP_AUX_CTRL ); + + aux_ctrl |=DP_AUX_CTRL_RESET ; +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +usleep_range (1000 ,1100 );/* h/w recommended delay */ + + aux_ctrl &= ~DP_AUX_CTRL_RESET ; +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +} + +void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux_ctrl =dp_read_aux (catalog,REG_DP_AUX_CTRL ); + +if (enable) { +dp_write_aux (catalog,REG_DP_TIMEOUT_COUNT ,0xffff ); +dp_write_aux (catalog,REG_DP_AUX_LIMITS ,0xffff ); + aux_ctrl |=DP_AUX_CTRL_ENABLE ; + }else { + aux_ctrl &= ~DP_AUX_CTRL_ENABLE ; + } + +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +} + +void dp_catalog_aux_update_cfg (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg,enum dp_phy_aux_config_type type) +{ +struct dp_catalog_private *catalog; +u32 new_index =0 , current_index =0 ; + +if (!aux || !cfg || (type >=PHY_AUX_CFG_MAX )) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + current_index = cfg[type].current_index; + new_index = (current_index +1 ) % cfg[type].cfg_cnt; +DRM_DEBUG_DP ("Updating %s from 0x%08x to 0x%08x\n" , +dp_phy_aux_config_type_to_string (type), + cfg[type].lut[current_index], cfg[type].lut[new_index]); + +dp_write_phy (catalog, cfg[type].offset, + cfg[type].lut[new_index]); + cfg[type].current_index = new_index; +} + +void dp_catalog_aux_setup (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg) +{ +struct dp_catalog_private *catalog; +int i =0 ; + +if (!aux || !cfg) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + +dp_write_phy (catalog,REG_DP_PHY_PD_CTL ,DP_PHY_PD_CTL_PWRDN | +DP_PHY_PD_CTL_AUX_PWRDN |DP_PHY_PD_CTL_PLL_PWRDN | +DP_PHY_PD_CTL_DP_CLAMP_EN ); + +/* Turn on BIAS current for PHY/PLL */ +dp_write_pll (catalog, +QSERDES_COM_BIAS_EN_CLKBUFLR_EN ,QSERDES_COM_BIAS_EN | +QSERDES_COM_BIAS_EN_MUX |QSERDES_COM_CLKBUF_L_EN | +QSERDES_COM_EN_SYSCLK_TX_SEL ); + +/* DP AUX CFG register programming */ +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) { +DRM_DEBUG_DP ("%s: offset=0x%08x, value=0x%08x\n" , +dp_phy_aux_config_type_to_string (i), + cfg[i].offset, cfg[i].lut[cfg[i].current_index]); +dp_write_phy (catalog, cfg[i].offset, + cfg[i].lut[cfg[i].current_index]); + } + +dp_write_phy (catalog,REG_DP_PHY_AUX_INTERRUPT_MASK ,PHY_AUX_STOP_ERR_MASK | +PHY_AUX_DEC_ERR_MASK |PHY_AUX_SYNC_ERR_MASK | +PHY_AUX_ALIGN_ERR_MASK |PHY_AUX_REQ_ERR_MASK ); +} + +void dp_catalog_aux_get_irq (struct dp_catalog_aux *aux,bool cmd_busy) +{ +u32 ack; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux->isr =dp_read_ahb (catalog,REG_DP_INTR_STATUS ); + aux->isr &= ~DP_INTERRUPT_STATUS1_MASK ; + ack = aux->isr &DP_INTERRUPT_STATUS1 ; + ack <<=1 ; + ack |=DP_INTERRUPT_STATUS1_MASK ; +dp_write_ahb (catalog,REG_DP_INTR_STATUS , ack); +}
drivers/gpu/drm/msm/dp/dp_catalog.c line 366
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +/* controller related catalog functions */ +void dp_catalog_ctrl_update_transfer_unit (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + }
This check is done throughout this file. I haven't worked my way through all the code yet and it is hard to audit all the callers in a email client but this seems like mostly a sanity check on the developer and not an actual thing that can happen at runtime. If that is the case, you should save yourself the dozens and dozens of extra lines by either removing this or changing it:
if (!WARN_ON(ctrl))
return;
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +31
-0+dp_catalog_get_priv (ctrl); + +dp_write_link (catalog,REG_DP_VALID_BOUNDARY , ctrl->valid_boundary); +dp_write_link (catalog,REG_DP_TU , ctrl->dp_tu); +dp_write_link (catalog,REG_DP_VALID_BOUNDARY_2 , ctrl->valid_boundary2); +} + +void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_link (catalog,REG_DP_STATE_CTRL , state); +} + +void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 cfg) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl);
drivers/gpu/drm/msm/dp/dp_catalog.c line 408
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +DRM_DEBUG_DP ("DP_CONFIGURATION_CTRL=0x%x\n" , cfg); + +dp_write_link (catalog,REG_DP_CONFIGURATION_CTRL , cfg); +} + +void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +u32 ln_0 =0 , ln_1 =1 , ln_2 =2 , ln_3 =3 ;/* One-to-One mapping */
You can safely use inline constants in the four lines below. This is much more confusing.
Quoted 147 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +147
-0+u32 ln_mapping; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + ln_mapping = ln_0 <<LANE0_MAPPING_SHIFT ; + ln_mapping |= ln_1 <<LANE1_MAPPING_SHIFT ; + ln_mapping |= ln_2 <<LANE2_MAPPING_SHIFT ; + ln_mapping |= ln_3 <<LANE3_MAPPING_SHIFT ; + +dp_write_link (catalog,REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING , ln_mapping); +} + +void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +u32 mainlink_ctrl; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +if (enable) { +/* +* To make sure link reg writes happens before any other operation, +* dp_write_link() function uses writel() instread of writel_relaxed() +*/ +dp_write_link (catalog,REG_DP_MAINLINK_CTRL ,DP_MAINLINK_FB_BOUNDARY_SEL ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , +DP_MAINLINK_FB_BOUNDARY_SEL |DP_MAINLINK_CTRL_RESET ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL ,DP_MAINLINK_FB_BOUNDARY_SEL ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , +DP_MAINLINK_FB_BOUNDARY_SEL |DP_MAINLINK_CTRL_ENABLE ); + }else { + mainlink_ctrl =dp_read_link (catalog,REG_DP_MAINLINK_CTRL ); + mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE ; +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , mainlink_ctrl); + } +} + +void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl, +u32 colorimetry_cfg,u32 test_bits_depth) +{ +u32 misc_val; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + misc_val =dp_read_link (catalog,REG_DP_MISC1_MISC0 ); + misc_val |= colorimetry_cfg <<DP_MISC0_COLORIMETRY_CFG_SHIFT ; + misc_val |= test_bits_depth <<DP_MISC0_TEST_BITS_DEPTH_SHIFT ; +/* Configure clock to synchronous mode */ + misc_val |=DP_MISC0_SYNCHRONOUS_CLK ; + +DRM_DEBUG_DP ("misc settings = 0x%x\n" , misc_val); +dp_write_link (catalog,REG_DP_MISC1_MISC0 , misc_val); +} + +void dp_catalog_ctrl_config_msa (struct dp_catalog_ctrl *ctrl, +u32 rate,u32 stream_rate_khz, +bool fixed_nvid) +{ +u32 pixel_m, pixel_n; +u32 mvid, nvid; +u64 mvid_calc; +u32 const nvid_fixed =0x8000 ; +u32 const link_rate_hbr2 =540000 ; +u32 const link_rate_hbr3 =810000 ; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); +if (fixed_nvid) { +DRM_DEBUG_DP ("use fixed NVID=0x%x\n" , nvid_fixed); + nvid = nvid_fixed; + +DRM_DEBUG_DP ("link rate=%dkbps, stream_rate_khz=%uKhz" , + rate, stream_rate_khz); + +/* +* For intermediate results, use 64 bit arithmetic to avoid +* loss of precision. +*/ + mvid_calc = (u64 ) stream_rate_khz * nvid; + mvid_calc =div_u64 (mvid_calc, rate); + +/* +* truncate back to 32 bits as this final divided value will +* always be within the range of a 32 bit unsigned int. +*/ + mvid = (u32 ) mvid_calc; + }else { + pixel_m =dp_read_cc (catalog,MMSS_DP_PIXEL_M ); + pixel_n =dp_read_cc (catalog,MMSS_DP_PIXEL_N ); +DRM_DEBUG_DP ("pixel_m=0x%x, pixel_n=0x%x\n" , pixel_m, pixel_n); + + mvid = (pixel_m &0xFFFF ) *5 ; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m &0xFFFF ); + +DRM_DEBUG_DP ("rate = %d\n" , rate); + +if (link_rate_hbr2 == rate) + nvid *=2 ; + +if (link_rate_hbr3 == rate) + nvid *=3 ; + } + +DRM_DEBUG_DP ("mvid=0x%x, nvid=0x%x\n" , mvid, nvid); +dp_write_link (catalog,REG_DP_SOFTWARE_MVID , mvid); +dp_write_link (catalog,REG_DP_SOFTWARE_NVID , nvid); +} + +int dp_catalog_ctrl_set_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +int bit, ret; +u32 data; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (ctrl); + + bit =BIT (pattern -1 ); +DRM_DEBUG_DP ("hw: bit=%d train=%d\n" , bit, pattern); +dp_write_link (catalog,REG_DP_STATE_CTRL , bit);
drivers/gpu/drm/msm/dp/dp_catalog.c line 565
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ + bit =BIT (pattern -1 ) <<DP_MAINLINK_READY_LINK_TRAINING_SHIFT ; + +/* Poll for mainlink ready status */ + ret =readx_poll_timeout (readl, catalog->io->dp_link.base +REG_DP_MAINLINK_READY , + data, data & bit, +POLLING_SLEEP_US ,POLLING_TIMEOUT_US ); +if (ret <0 ) { +DRM_ERROR ("set pattern for link_train=%d failed\n" , pattern); +return ret;
You don't need return ret, just drop out and then return ret at the bottom of the function.
Quoted 43 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +43
-0+ } +return 0 ; +} + +void dp_catalog_ctrl_usb_reset (struct dp_catalog_ctrl *ctrl,bool flip) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_RESET_OVRD_CTRL , +USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX | +USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_PHY_MODE_CTRL , +USB3_DP_COM_PHY_MODE_DP ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SW_RESET , +USB3_DP_COM_SW_RESET_SET ); + +if (!flip)/* CC1 */ +dp_write_usb_cm (catalog,REG_USB3_DP_COM_TYPEC_CTRL , +USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX ); +else /* CC2 */ +dp_write_usb_cm (catalog,REG_USB3_DP_COM_TYPEC_CTRL , +USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX | +USB3_DP_COM_TYPEC_CTRL_PORTSEL ); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SWI_CTRL ,0x00 ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SW_RESET ,0x00 ); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_POWER_DOWN_CTRL , +USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_RESET_OVRD_CTRL ,0x00 ); + +} + +void dp_catalog_ctrl_reset (struct dp_catalog_ctrl *ctrl) +{ +u32 sw_reset;
drivers/gpu/drm/msm/dp/dp_catalog.c line 618
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base;
Base appears to be unused here.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +40
-0+ + sw_reset =dp_read_ahb (catalog,REG_DP_SW_RESET ); + + sw_reset |=DP_SW_RESET ; +dp_write_ahb (catalog,REG_DP_SW_RESET , sw_reset); +usleep_range (1000 ,1100 );/* h/w recommended delay */ + + sw_reset &= ~DP_SW_RESET ; +dp_write_ahb (catalog,REG_DP_SW_RESET , sw_reset); +} + +bool dp_catalog_ctrl_mainlink_ready (struct dp_catalog_ctrl *ctrl) +{ +u32 data; +int ret; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return false; + } + +dp_catalog_get_priv (ctrl); + +/* Poll for mainlink ready status */ + ret =readx_poll_timeout (readl, + catalog->io->dp_link.base +REG_DP_MAINLINK_READY , + data, data &DP_MAINLINK_READY_FOR_VIDEO , +POLLING_SLEEP_US ,POLLING_TIMEOUT_US ); +if (ret <0 ) { +DRM_ERROR ("mainlink not ready\n" ); +return false; + } + +return true; +} + +void dp_catalog_ctrl_enable_irq (struct dp_catalog_ctrl *ctrl, +bool enable) +{
drivers/gpu/drm/msm/dp/dp_catalog.c line 668
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base;
base also appears to be unused here.
Quoted 276 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +276
-0+ +if (enable) { +dp_write_ahb (catalog,REG_DP_INTR_STATUS ,DP_INTERRUPT_STATUS1_MASK ); +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 ,DP_INTERRUPT_STATUS2_MASK ); + }else { +dp_write_ahb (catalog,REG_DP_INTR_STATUS ,0x00 ); +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 ,0x00 ); + } +} + +void dp_catalog_ctrl_hpd_config (struct dp_catalog_ctrl *ctrl,bool en) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +if (en) { +u32 reftimer =dp_read_aux (catalog,REG_DP_DP_HPD_REFTIMER ); + +dp_write_aux (catalog,REG_DP_DP_HPD_INT_ACK , +DP_DP_HPD_PLUG_INT_ACK |DP_DP_IRQ_HPD_INT_ACK | +DP_DP_HPD_REPLUG_INT_ACK |DP_DP_HPD_UNPLUG_INT_ACK ); +dp_write_aux (catalog,REG_DP_DP_HPD_INT_MASK , +DP_DP_HPD_PLUG_INT_MASK |DP_DP_IRQ_HPD_INT_MASK | +DP_DP_HPD_REPLUG_INT_MASK |DP_DP_HPD_UNPLUG_INT_MASK ); + +/* Configure REFTIMER */ + reftimer |=REFTIMER_DEFAULT_VALUE ; +dp_write_aux (catalog,REG_DP_DP_HPD_REFTIMER , reftimer); +/* Enable HPD */ +dp_write_aux (catalog,REG_DP_DP_HPD_CTRL ,DP_DP_HPD_CTRL_HPD_EN ); + }else { +/* Disable HPD */ +dp_write_aux (catalog,REG_DP_DP_HPD_CTRL ,0x0 ); + } +} + +void dp_catalog_ctrl_get_interrupt (struct dp_catalog_ctrl *ctrl) +{ +u32 ack =0 ; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + ctrl->isr =dp_read_ahb (catalog,REG_DP_INTR_STATUS2 ); + ctrl->isr &= ~DP_INTERRUPT_STATUS2_MASK ; + ack = ctrl->isr &DP_INTERRUPT_STATUS2 ; + ack <<=1 ; + ack |=DP_INTERRUPT_STATUS2_MASK ; +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 , ack); +} + +void dp_catalog_ctrl_phy_reset (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_ahb (catalog,REG_DP_PHY_CTRL , +DP_PHY_CTRL_SW_RESET_PLL |DP_PHY_CTRL_SW_RESET ); +usleep_range (1000 ,1100 );/* h/w recommended delay */ +dp_write_ahb (catalog,REG_DP_PHY_CTRL ,0x0 ); +} + +void dp_catalog_ctrl_phy_lane_cfg (struct dp_catalog_ctrl *ctrl, +bool flipped,u8 ln_cnt) +{ +u32 info =0x0 ; +struct dp_catalog_private *catalog; +u8 orientation =BIT (!!flipped); + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + info = ln_cnt &DP_PHY_SPARE0_MASK ; + info |= (orientation &DP_PHY_SPARE0_MASK ) <<DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT ; +DRM_DEBUG_DP ("Shared Info = 0x%x\n" , info); + +dp_write_phy (catalog,REG_DP_PHY_SPARE0 , info); +} + +int dp_catalog_ctrl_update_vx_px (struct dp_catalog_ctrl *ctrl, +u8 v_level,u8 p_level) +{ +struct dp_catalog_private *catalog; +u8 value0, value1; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (ctrl); + +DRM_DEBUG_DP ("hw: v=%d p=%d\n" , v_level, p_level); + + value0 = vm_voltage_swing[v_level][p_level]; + value1 = vm_pre_emphasis[v_level][p_level]; + +if (value0 ==0xFF && value1 ==0xFF ) { +DRM_ERROR ("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n" , + v_level, value0, p_level, value1); +return -EINVAL ; + } +/* program default setting first */ +dp_write_ln_tx0 (catalog, TXn_TX_DRV_LVL,0x2A ); +dp_write_ln_tx1 (catalog, TXn_TX_DRV_LVL,0x2A ); +dp_write_ln_tx0 (catalog, TXn_TX_EMP_POST1_LVL,0x20 ); +dp_write_ln_tx1 (catalog, TXn_TX_EMP_POST1_LVL,0x20 ); + +/* Enable MUX to use Cursor values from these registers */ + value0 |=BIT (5 ); + value1 |=BIT (5 ); + +/* Configure host and panel only if both values are allowed */ +dp_write_ln_tx0 (catalog, TXn_TX_DRV_LVL, value0); +dp_write_ln_tx1 (catalog, TXn_TX_DRV_LVL, value0); +dp_write_ln_tx0 (catalog, TXn_TX_EMP_POST1_LVL, value1); +dp_write_ln_tx1 (catalog, TXn_TX_EMP_POST1_LVL, value1); +DRM_DEBUG_DP ("hw: vx_value=0x%x px_value=0x%x\n" , + value0, value1); + +return 0 ; +} + +void dp_catalog_ctrl_send_phy_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +struct dp_catalog_private *catalog; +u32 value =0x0 ; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +/* Make sure to clear the current pattern before starting a new one */ +dp_write_link (catalog,REG_DP_STATE_CTRL ,0x0 ); + +switch (pattern) { +case DP_LINK_QUAL_PATTERN_D10_2 : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_TRAINING_PATTERN1 ); +break ; +case DP_LINK_QUAL_PATTERN_ERROR_RATE : + value &= ~DP_HBR2_ERM_PATTERN ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=SCRAMBLER_RESET_COUNT_VALUE ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write_link (catalog,REG_DP_MAINLINK_LEVELS ,DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 ); +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE ); +break ; +case DP_LINK_QUAL_PATTERN_PRBS7 : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_PRBS7 ); +break ; +case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN ); +/* 00111110000011111000001111100000 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0 ,0x3E0F83E0 ); +/* 00001111100000111110000011111000 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1 ,0x0F83E0F8 ); +/* 1111100000111110 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2 ,0x0000F83E ); +break ; +case DP_LINK_QUAL_PATTERN_HBR2_EYE : + value =DP_HBR2_ERM_PATTERN ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=SCRAMBLER_RESET_COUNT_VALUE ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write_link (catalog,REG_DP_MAINLINK_LEVELS ,DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 ); +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE ); +break ; +default : +DRM_DEBUG_DP ("No valid test pattern requested: 0x%x\n" , pattern); +return ; + } +} + +u32 dp_catalog_ctrl_read_phy_pattern (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return 0 ; + } + +dp_catalog_get_priv (ctrl); + +return dp_read_link (catalog,REG_DP_MAINLINK_READY ); +} + +/* panel related catalog functions */ +int dp_catalog_panel_timing_cfg (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (panel); + +dp_write_link (catalog,REG_DP_TOTAL_HOR_VER , panel->total); +dp_write_link (catalog,REG_DP_START_HOR_VER_FROM_SYNC , panel->sync_start); +dp_write_link (catalog,REG_DP_HSYNC_VSYNC_WIDTH_POLARITY , panel->width_blanking); +dp_write_link (catalog,REG_DP_ACTIVE_HOR_VER , panel->dp_active); +return 0 ; +} + +void dp_catalog_panel_tpg_enable (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (panel); + +dp_write_p0 (catalog,MMSS_DP_INTF_CONFIG ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_HSYNC_CTL , panel->hsync_ctl); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PERIOD_F0 , panel->vsync_period * + panel->hsync_period); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0 , panel->v_sync_width * + panel->hsync_period); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PERIOD_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_HCTL , panel->display_hctl); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_HCTL ,0 ); +dp_write_p0 (catalog,MMSS_INTF_DISPLAY_V_START_F0 , panel->display_v_start); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_V_END_F0 , panel->display_v_end); +dp_write_p0 (catalog,MMSS_INTF_DISPLAY_V_START_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_V_END_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_START_F0 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_END_F0 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_START_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_END_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_POLARITY_CTL ,0 ); + +dp_write_p0 (catalog,MMSS_DP_TPG_MAIN_CONTROL ,DP_TPG_CHECKERED_RECT_PATTERN ); +dp_write_p0 (catalog,MMSS_DP_TPG_VIDEO_CONFIG , +DP_TPG_VIDEO_CONFIG_BPP_8BIT | +DP_TPG_VIDEO_CONFIG_RGB ); +dp_write_p0 (catalog,MMSS_DP_BIST_ENABLE ,DP_BIST_ENABLE_DPBIST_EN ); +dp_write_p0 (catalog,MMSS_DP_TIMING_ENGINE_EN ,DP_TIMING_ENGINE_EN_EN ); +DRM_DEBUG_DP ("%s: enabled tpg\n" , __func__); +} + +void dp_catalog_panel_tpg_disable (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) {
drivers/gpu/drm/msm/dp/dp_catalog.c line 954
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (panel); + +dp_write_p0 (catalog,MMSS_DP_TPG_MAIN_CONTROL ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_BIST_ENABLE ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_TIMING_ENGINE_EN ,0x0 ); +return ;
Don't need a bare return at the bottom of the function.
drivers/gpu/drm/msm/dp/dp_catalog.c line 966
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+} + +struct dp_catalog *dp_catalog_get (struct device *dev,struct dp_io *io) +{ +int rc =0 ; +struct dp_catalog *dp_catalog; +struct dp_catalog_private *catalog; + +if (!io) { +DRM_ERROR ("invalid input\n" ); + rc = -EINVAL ; + goto error;
This can just be return ERR_PTR(-EINVAL) assuming that io being NULL is an actual thing that can happen at run time and not just a developer goof.
drivers/gpu/drm/msm/dp/dp_catalog.c line 972
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +6
-0+ } + + catalog =devm_kzalloc (dev,sizeof (*catalog),GFP_KERNEL ); +if (!catalog) { + rc = -ENOMEM ; + goto error;
return ERR_PTR(-ENOMEM)
drivers/gpu/drm/msm/dp/dp_catalog.c line 982
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ } + + catalog->dev = dev; + catalog->io = io; + + dp_catalog = &catalog->dp_catalog; + +return dp_catalog; +error: +return ERR_PTR (rc);
And then the label isn't needed
drivers/gpu/drm/msm/dp/dp_catalog.c line 995
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +13
-0+} + +void dp_catalog_put (struct dp_catalog *dp_catalog) +{ +struct dp_catalog_private *catalog; + +if (!dp_catalog) +return ; + + catalog = container_of(dp_catalog, struct dp_catalog_private, + dp_catalog); + +devm_kfree (catalog->dev, catalog);
As above, devm_kfree shouldn't need to be called on memory that is about to be cleaned up by the component or the device so assuming this is a persistent memory object for the life of the component this entire function can go way.
Quoted 128 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_catalog.h new file +108
-0@@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +*/ + +#ifndef _DP_CATALOG_H_ +#define _DP_CATALOG_H_ + +#include "dp_parser.h" + +/* interrupts */ +#define DP_INTR_HPD BIT(0) +#define DP_INTR_AUX_I2C_DONE BIT(3) +#define DP_INTR_WRONG_ADDR BIT(6) +#define DP_INTR_TIMEOUT BIT(9) +#define DP_INTR_NACK_DEFER BIT(12) +#define DP_INTR_WRONG_DATA_CNT BIT(15) +#define DP_INTR_I2C_NACK BIT(18) +#define DP_INTR_I2C_DEFER BIT(21) +#define DP_INTR_PLL_UNLOCKED BIT(24) +#define DP_INTR_AUX_ERROR BIT(27) + +#define DP_INTR_READY_FOR_VIDEO BIT(0) +#define DP_INTR_IDLE_PATTERN_SENT BIT(3) +#define DP_INTR_FRAME_END BIT(6) +#define DP_INTR_CRC_UPDATED BIT(9) + +struct dp_catalog_aux { +u32 data; +u32 isr; +}; + +struct dp_catalog_ctrl { +u32 dp_tu; +u32 valid_boundary; +u32 valid_boundary2; +u32 isr; +}; + +struct dp_catalog_panel { +u32 total; +u32 sync_start; +u32 width_blanking; +u32 dp_active; + +/* TPG */ +u32 hsync_period; +u32 vsync_period; +u32 display_v_start; +u32 display_v_end; +u32 v_sync_width; +u32 hsync_ctl; +u32 display_hctl; +}; + +struct dp_catalog { +struct dp_catalog_aux aux; +struct dp_catalog_ctrl ctrl; +struct dp_catalog_panel panel; +}; + +/* AUX APIs */ +u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux); +int dp_catalog_aux_write_data (struct dp_catalog_aux *aux); +int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux); +int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read); +void dp_catalog_aux_reset (struct dp_catalog_aux *aux); +void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable); +void dp_catalog_aux_update_cfg (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg,enum dp_phy_aux_config_type type); +void dp_catalog_aux_setup (struct dp_catalog_aux *aux, +struct dp_aux_cfg *aux_cfg); +void dp_catalog_aux_get_irq (struct dp_catalog_aux *aux,bool cmd_busy); + +/* DP Controller APIs */ +void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state); +void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 config); +void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl,u32 cc,u32 tb); +void dp_catalog_ctrl_config_msa (struct dp_catalog_ctrl *ctrl,u32 rate, +u32 stream_rate_khz,bool fixed_nvid); +int dp_catalog_ctrl_set_pattern (struct dp_catalog_ctrl *ctrl,u32 pattern); +void dp_catalog_ctrl_reset (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_usb_reset (struct dp_catalog_ctrl *ctrl,bool flip); +bool dp_catalog_ctrl_mainlink_ready (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_enable_irq (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_hpd_config (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_phy_reset (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_phy_lane_cfg (struct dp_catalog_ctrl *ctrl,bool flipped, +u8 lane_cnt); +int dp_catalog_ctrl_update_vx_px (struct dp_catalog_ctrl *ctrl,u8 v_level, +u8 p_level); +void dp_catalog_ctrl_get_interrupt (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_update_transfer_unit (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_send_phy_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern); +u32 dp_catalog_ctrl_read_phy_pattern (struct dp_catalog_ctrl *ctrl); + +/* DP Panel APIs */ +int dp_catalog_panel_timing_cfg (struct dp_catalog_panel *panel); +void dp_catalog_panel_tpg_enable (struct dp_catalog_panel *panel); +void dp_catalog_panel_tpg_disable (struct dp_catalog_panel *panel); + +struct dp_catalog *dp_catalog_get (struct device *dev,struct dp_io *io); +void dp_catalog_put (struct dp_catalog *catalog); + +#endif /* _DP_CATALOG_H_ */ drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0@@ -0,0 +1,1611 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ +
drivers/gpu/drm/msm/dp/dp_ctrl.c line 17
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+#include <linux/types.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <drm/drm_fixed.h> + +#include "dp_reg.h" +#include "dp_ctrl.h" + +#define DP_KHZ_TO_HZ 1000 +#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000)/* 30 ms */
This looks like it should be msecs_to_jiffies()
drivers/gpu/drm/msm/dp/dp_ctrl.c line 18
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1
-0+#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2)
Maybe this one too, since I'm guessing the intended timeout is 500ms
Quoted 453 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +453
-0+ +#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) +#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) + +#define MR_LINK_TRAINING1 0x8 +#define MR_LINK_SYMBOL_ERM 0x80 +#define MR_LINK_PRBS7 0x100 +#define MR_LINK_CUSTOM80 0x200 + +struct dp_tu_calc_input { +u64 lclk;/* 162, 270, 540 and 810 */ +u64 pclk_khz;/* in KHz */ +u64 hactive;/* active h-width */ +u64 hporch;/* bp + fp + pulse */ +int nlanes;/* no.of.lanes */ +int bpp;/* bits */ +int pixel_enc;/* 444, 420, 422 */ +int dsc_en;/* dsc on/off */ +int async_en;/* async mode */ +}; + +struct dp_vc_tu_mapping_table { +u8 valid_boundary_link; +u16 delay_start_link; +bool boundary_moderation_en; +u8 valid_lower_boundary_link; +u8 upper_boundary_count; +u8 lower_boundary_count; +u8 tu_size_minus1; +}; + +struct dp_ctrl_private { +struct dp_ctrl dp_ctrl; + +struct device *dev; +struct dp_aux *aux; +struct dp_panel *panel; +struct dp_link *link; +struct dp_power *power; +struct dp_parser *parser; +struct dp_catalog_ctrl *catalog; + +struct completion idle_comp; +struct mutex push_idle_mutex; +struct completion video_comp; +}; + +void dp_ctrl_abort (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +atomic_set (&ctrl->dp_ctrl.aborted,1 ); +} + +void dp_ctrl_push_idle (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +mutex_lock (&ctrl->push_idle_mutex); + +reinit_completion (&ctrl->idle_comp); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,DP_STATE_CTRL_PUSH_IDLE ); + +if (!wait_for_completion_timeout (&ctrl->idle_comp, +IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES )) +pr_warn ("PUSH_IDLE pattern timedout\n" ); + +mutex_unlock (&ctrl->push_idle_mutex); +pr_debug ("mainlink off done\n" ); +} + +static void dp_ctrl_config_ctrl (struct dp_ctrl_private *ctrl) +{ +u32 config =0 , tbd; +u8 *dpcd = ctrl->panel->dpcd; + +/* Default-> LSCLK DIV: 1/4 LCLK */ + config |= (2 <<DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT ); + +/* Scrambler reset enable */ +if (dpcd[DP_EDP_CONFIGURATION_CAP ] &DP_ALTERNATE_SCRAMBLER_RESET_CAP ) + config |=DP_CONFIGURATION_CTRL_ASSR ; + + tbd =dp_link_get_test_bits_depth (ctrl->link, + ctrl->panel->dp_mode.bpp); + +if (tbd ==DP_TEST_BIT_DEPTH_UNKNOWN ) { +pr_debug ("BIT_DEPTH not set. Configure default\n" ); + tbd =DP_TEST_BIT_DEPTH_8 ; + } + + config |= tbd <<DP_CONFIGURATION_CTRL_BPC_SHIFT ; + +/* Num of Lanes */ + config |= ((ctrl->link->link_params.num_lanes -1 ) + <<DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT ); + +if (drm_dp_enhanced_frame_cap (dpcd)) + config |=DP_CONFIGURATION_CTRL_ENHANCED_FRAMING ; + + config |=DP_CONFIGURATION_CTRL_P_INTERLACED ;/* progressive video */ + +/* sync clock & static Mvid */ + config |=DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN ; + config |=DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK ; + +dp_catalog_ctrl_config_ctrl (ctrl->catalog, config); +} + +/** +* dp_ctrl_configure_source_params() - configures DP transmitter source params +* @ctrl: Display Port Driver data +* +* Configures the DP transmitter source params including details such as lane +* configuration, output format and sink/panel timing information. +*/ +static void dp_ctrl_configure_source_params (struct dp_ctrl_private *ctrl) +{ +u32 cc, tb; + +dp_catalog_ctrl_lane_mapping (ctrl->catalog); +dp_catalog_ctrl_mainlink_ctrl (ctrl->catalog, true); + +dp_ctrl_config_ctrl (ctrl); + + tb =dp_link_get_test_bits_depth (ctrl->link, + ctrl->panel->dp_mode.bpp); + cc =dp_link_get_colorimetry_config (ctrl->link); +dp_catalog_ctrl_config_misc (ctrl->catalog, cc, tb); +dp_panel_timing_cfg (ctrl->panel); +} + +/* +* The structure and few functions present below are IP/Hardware +* specific implementation. Most of the implementation will not +* have coding comments +*/ +struct tu_algo_data { +s64 lclk_fp; +s64 pclk_fp; +s64 lwidth; +s64 hbp_relative_to_pclk; +int nlanes; +int bpp; +int pixelEnc; +int dsc_en; +int async_en; +int bpc; + +uint delay_start_link_extra_pixclk; +int extra_buffer_margin; +s64 ratio_fp; +s64 original_ratio_fp; + +s64 err_fp; +s64 n_err_fp; +s64 n_n_err_fp; +int tu_size; +int tu_size_desired; +int tu_size_minus1; + +int valid_boundary_link; +s64 resulting_valid_fp; +s64 total_valid_fp; +s64 effective_valid_fp; +s64 effective_valid_recorded_fp; +int n_tus; +int n_tus_per_lane; +int paired_tus; +int remainder_tus; +int remainder_tus_upper; +int remainder_tus_lower; +int extra_bytes; +int filler_size; +int delay_start_link; + +int extra_pclk_cycles; +int extra_pclk_cycles_in_link_clk; +s64 ratio_by_tu_fp; +s64 average_valid2_fp; +int new_valid_boundary_link; +int remainder_symbols_exist; +int n_symbols; +s64 n_remainder_symbols_per_lane_fp; +s64 last_partial_tu_fp; +s64 TU_ratio_err_fp; + +int n_tus_incl_last_incomplete_tu; +int extra_pclk_cycles_tmp; +int extra_pclk_cycles_in_link_clk_tmp; +int extra_required_bytes_new_tmp; +int filler_size_tmp; +int lower_filler_size_tmp; +int delay_start_link_tmp; + +bool boundary_moderation_en; +int boundary_mod_lower_err; +int upper_boundary_count; +int lower_boundary_count; +int i_upper_boundary_count; +int i_lower_boundary_count; +int valid_lower_boundary_link; +int even_distribution_BF; +int even_distribution_legacy; +int even_distribution; +int min_hblank_violated; +s64 delay_start_time_fp; +s64 hbp_time_fp; +s64 hactive_time_fp; +s64 diff_abs_fp; + +s64 ratio; +}; + +static int _tu_param_compare (s64 a,s64 b) +{ +u32 a_int, a_frac; +u32 b_int, b_frac; + +if (a == b) +return 0 ; + + a_int = (a >>32 ) &0x7FFFFFFF ; + a_frac = a &0xFFFFFFFF ; + + b_int = (b >>32 ) &0x7FFFFFFF ; + b_frac = b &0xFFFFFFFF ; + +if (a_int > b_int) +return 1 ; +else if (a_int < b_int) +return 2 ; +else if (a_frac > b_frac) +return 1 ; +else +return 2 ; +} + +static void _tu_valid_boundary_calc (struct tu_algo_data *tu) +{ +s64 temp1_fp, temp2_fp, temp, temp1, temp2; +int compare_result_1, compare_result_2, compare_result_3; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + + tu->new_valid_boundary_link =drm_fixp2int_ceil (temp2_fp); + + temp = (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link-1 )); + tu->average_valid2_fp =drm_fixp_from_fraction (temp, + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + temp1_fp =drm_fixp_from_fraction (tu->bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu->lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, tu->average_valid2_fp); + tu->n_tus =drm_fixp2int (temp2_fp); + + temp1_fp =drm_fixp_from_fraction (tu->n_tus,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, tu->average_valid2_fp); + temp1_fp =drm_fixp_from_fraction (tu->n_symbols,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (tu->nlanes,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu->n_remainder_symbols_per_lane_fp = temp2_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + tu->last_partial_tu_fp = +drm_fixp_div (tu->n_remainder_symbols_per_lane_fp, + temp1_fp); + +if (tu->n_remainder_symbols_per_lane_fp !=0 ) + tu->remainder_symbols_exist =1 ; +else + tu->remainder_symbols_exist =0 ; + + temp1_fp =drm_fixp_from_fraction (tu->n_tus, tu->nlanes); + tu->n_tus_per_lane =drm_fixp2int (temp1_fp); + + tu->paired_tus = (int )((tu->n_tus_per_lane) / + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus * + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count); + +if ((tu->remainder_tus - tu->i_upper_boundary_count) >0 ) { + tu->remainder_tus_upper = tu->i_upper_boundary_count; + tu->remainder_tus_lower = tu->remainder_tus - + tu->i_upper_boundary_count; + }else { + tu->remainder_tus_upper = tu->remainder_tus; + tu->remainder_tus_lower =0 ; + } + + temp = tu->paired_tus * (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link -1 )) + + (tu->remainder_tus_upper * + tu->new_valid_boundary_link) + + (tu->remainder_tus_lower * + (tu->new_valid_boundary_link -1 )); + tu->total_valid_fp =drm_fixp_from_fraction (temp,1 ); + +if (tu->remainder_symbols_exist) { + temp1_fp = tu->total_valid_fp + + tu->n_remainder_symbols_per_lane_fp; + temp2_fp =drm_fixp_from_fraction (tu->n_tus_per_lane,1 ); + temp2_fp = temp2_fp + tu->last_partial_tu_fp; + temp1_fp =drm_fixp_div (temp1_fp, temp2_fp); + }else { + temp2_fp =drm_fixp_from_fraction (tu->n_tus_per_lane,1 ); + temp1_fp =drm_fixp_div (tu->total_valid_fp, temp2_fp); + } + tu->effective_valid_fp = temp1_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + tu->n_err_fp = tu->average_valid2_fp - temp2_fp; + + tu->even_distribution = tu->n_tus % tu->nlanes ==0 ?1 :0 ; + + temp1_fp =drm_fixp_from_fraction (tu->bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu->lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, tu->average_valid2_fp); + +if (temp2_fp) + tu->n_tus_incl_last_incomplete_tu =drm_fixp2int_ceil (temp2_fp); +else + tu->n_tus_incl_last_incomplete_tu =0 ; + + temp1 =0 ; + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->original_ratio_fp, temp1_fp); + temp1_fp = tu->average_valid2_fp - temp2_fp; + temp2_fp =drm_fixp_from_fraction (tu->n_tus_incl_last_incomplete_tu,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + temp1 =drm_fixp2int_ceil (temp1_fp); + + temp = tu->i_upper_boundary_count * tu->nlanes; + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu->new_valid_boundary_link,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (temp,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + +if (temp2_fp) + temp2 =drm_fixp2int_ceil (temp2_fp); +else + temp2 =0 ; + tu->extra_required_bytes_new_tmp = (int )(temp1 + temp2); + + temp1_fp =drm_fixp_from_fraction (8 , tu->bpp); + temp2_fp =drm_fixp_from_fraction ( + tu->extra_required_bytes_new_tmp,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu->extra_pclk_cycles_tmp =drm_fixp2int_ceil (temp1_fp); +else + tu->extra_pclk_cycles_tmp =0 ; + + temp1_fp =drm_fixp_from_fraction (tu->extra_pclk_cycles_tmp,1 ); + temp2_fp =drm_fixp_div (tu->lclk_fp, tu->pclk_fp); + temp1_fp =drm_fixp_mul (temp1_fp, temp2_fp); + +if (temp1_fp) + tu->extra_pclk_cycles_in_link_clk_tmp = +drm_fixp2int_ceil (temp1_fp); +else + tu->extra_pclk_cycles_in_link_clk_tmp =0 ; + + tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link; + + tu->lower_filler_size_tmp = tu->filler_size_tmp +1 ; + + tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp + + tu->lower_filler_size_tmp + + tu->extra_buffer_margin; + + temp1_fp =drm_fixp_from_fraction (tu->delay_start_link_tmp,1 ); + tu->delay_start_time_fp =drm_fixp_div (temp1_fp, tu->lclk_fp); + + compare_result_1 =_tu_param_compare (tu->n_n_err_fp, tu->diff_abs_fp); +if (compare_result_1 ==2 ) + compare_result_1 =1 ; +else + compare_result_1 =0 ; + + compare_result_2 =_tu_param_compare (tu->n_n_err_fp, tu->err_fp); +if (compare_result_2 ==2 ) + compare_result_2 =1 ; +else + compare_result_2 =0 ; + + compare_result_3 =_tu_param_compare (tu->hbp_time_fp, + tu->delay_start_time_fp); +if (compare_result_3 ==2 ) + compare_result_3 =0 ; +else + compare_result_3 =1 ; + +if (((tu->even_distribution ==1 ) || + ((tu->even_distribution_BF ==0 ) && + (tu->even_distribution_legacy ==0 ))) && + tu->n_err_fp >=0 && tu->n_n_err_fp >=0 && + compare_result_2 && + (compare_result_1 || (tu->min_hblank_violated ==1 )) && + (tu->new_valid_boundary_link -1 ) >0 && + compare_result_3 && + (tu->delay_start_link_tmp <=1023 )) { + tu->upper_boundary_count = tu->i_upper_boundary_count; + tu->lower_boundary_count = tu->i_lower_boundary_count; + tu->err_fp = tu->n_n_err_fp; + tu->boundary_moderation_en = true; + tu->tu_size_desired = tu->tu_size; + tu->valid_boundary_link = tu->new_valid_boundary_link; + tu->effective_valid_recorded_fp = tu->effective_valid_fp; + tu->even_distribution_BF =1 ; + tu->delay_start_link = tu->delay_start_link_tmp; + }else if (tu->boundary_mod_lower_err ==0 ) { + compare_result_1 =_tu_param_compare (tu->n_n_err_fp, + tu->diff_abs_fp); +if (compare_result_1 ==2 ) + tu->boundary_mod_lower_err =1 ; + } +} + +static void _dp_ctrl_calc_tu (struct dp_tu_calc_input *in, +struct dp_vc_tu_mapping_table *tu_table) +{ +struct tu_algo_data tu; +int compare_result_1, compare_result_2; +u64 temp =0 ; +s64 temp_fp =0 , temp1_fp =0 , temp2_fp =0 ;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 481
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ +s64 LCLK_FAST_SKEW_fp =drm_fixp_from_fraction (6 ,10000 );/* 0.0006 */ +s64 const_p49_fp =drm_fixp_from_fraction (49 ,100 );/* 0.49 */ +s64 const_p56_fp =drm_fixp_from_fraction (56 ,100 );/* 0.56 */ +s64 RATIO_SCALE_fp =drm_fixp_from_fraction (1001 ,1000 ); + +u8 DP_BRUTE_FORCE =1 ; +s64 BRUTE_FORCE_THRESHOLD_fp =drm_fixp_from_fraction (1 ,10 );/* 0.1 */ +uint EXTRA_PIXCLK_CYCLE_DELAY =4 ; +uint HBLANK_MARGIN =4 ;
I would prefer if you used lower case names for all variables unless these are constants in disguise and then if so move them to #define.
Quoted 88 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +88
-0+ +memset (&tu,0 ,sizeof (tu)); + + tu.lclk_fp =drm_fixp_from_fraction (in->lclk,1 ); + tu.pclk_fp =drm_fixp_from_fraction (in->pclk_khz,1000 ); + tu.lwidth = in->hactive; + tu.hbp_relative_to_pclk = in->hporch; + tu.nlanes = in->nlanes; + tu.bpp = in->bpp; + tu.pixelEnc = in->pixel_enc; + tu.dsc_en = in->dsc_en; + tu.async_en = in->async_en; + + tu.err_fp =drm_fixp_from_fraction (1000 ,1 );/* 1000 */ + +if (tu.pixelEnc ==420 ) { + temp_fp =drm_fixp_from_fraction (2 ,1 ); + tu.pclk_fp =drm_fixp_div (tu.pclk_fp, temp_fp); + tu.lwidth /=2 ; + tu.hbp_relative_to_pclk /=2 ; + } + +if (tu.pixelEnc ==422 ) { +switch (tu.bpp) { +case 24 : + tu.bpp =16 ; + tu.bpc =8 ; +break ; +case 30 : + tu.bpp =20 ; + tu.bpc =10 ; +break ; +default : + tu.bpp =16 ; + tu.bpc =8 ; +break ; + } + }else { + tu.bpc = tu.bpp/3 ; + } + + temp1_fp =drm_fixp_from_fraction (4 ,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, tu.lclk_fp); + temp_fp =drm_fixp_div (temp2_fp, tu.pclk_fp); + tu.extra_buffer_margin =drm_fixp2int_ceil (temp_fp); + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_mul (tu.pclk_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.nlanes,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu.ratio_fp =drm_fixp_div (temp2_fp, tu.lclk_fp); + + tu.original_ratio_fp = tu.ratio_fp; + tu.boundary_moderation_en = false; + tu.upper_boundary_count =0 ; + tu.lower_boundary_count =0 ; + tu.i_upper_boundary_count =0 ; + tu.i_lower_boundary_count =0 ; + tu.valid_lower_boundary_link =0 ; + tu.even_distribution_BF =0 ; + tu.even_distribution_legacy =0 ; + tu.even_distribution =0 ; + tu.delay_start_time_fp =0 ; + + tu.err_fp =drm_fixp_from_fraction (1000 ,1 ); + tu.n_err_fp =0 ; + tu.n_n_err_fp =0 ; + + tu.ratio =drm_fixp2int (tu.ratio_fp); +if ((((u32 )tu.lwidth % tu.nlanes) !=0 ) && + !tu.ratio && tu.dsc_en ==0 ) { + tu.ratio_fp =drm_fixp_mul (tu.ratio_fp, RATIO_SCALE_fp); + tu.ratio =drm_fixp2int (tu.ratio_fp); +if (tu.ratio) + tu.ratio_fp =drm_fixp_from_fraction (1 ,1 ); + } + +if (tu.ratio >1 ) + tu.ratio =1 ; + +if (tu.ratio ==1 ) + goto tu_size_calc; + + compare_result_1 =_tu_param_compare (tu.ratio_fp, const_p49_fp); +if (!compare_result_1 || compare_result_1 ==1 ) + compare_result_1 =1 ; +else + compare_result_1 =0 ;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 579
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ + compare_result_2 =_tu_param_compare (tu.ratio_fp, const_p56_fp); +if (!compare_result_2 || compare_result_2 ==2 ) + compare_result_2 =1 ; +else + compare_result_2 =0 ; + +if (tu.dsc_en && compare_result_1 && compare_result_2) { +HBLANK_MARGIN +=4 ; +DRM_DEBUG_DP ("Info: increase HBLANK_MARGIN to %d\n" ,HBLANK_MARGIN );
You seem to mix and match DRM_ logging macros and pr_logging macros in this file.
Quoted 277 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +277
-0+ } + +tu_size_calc: +for (tu.tu_size =32 ; tu.tu_size <=64 ; tu.tu_size++) { + temp1_fp =drm_fixp_from_fraction (tu.tu_size,1 ); + temp2_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + temp =drm_fixp2int_ceil (temp2_fp); + temp1_fp =drm_fixp_from_fraction (temp,1 ); + tu.n_err_fp = temp1_fp - temp2_fp; + +if (tu.n_err_fp < tu.err_fp) { + tu.err_fp = tu.n_err_fp; + tu.tu_size_desired = tu.tu_size; + } + } + + tu.tu_size_minus1 = tu.tu_size_desired -1 ; + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + tu.valid_boundary_link =drm_fixp2int_ceil (temp2_fp); + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp2_fp =drm_fixp_mul (temp2_fp, temp1_fp); + + temp1_fp =drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu.n_tus =drm_fixp2int (temp2_fp); + + tu.even_distribution_legacy = tu.n_tus % tu.nlanes ==0 ?1 :0 ; +DRM_DEBUG_DP ("Info: n_sym = %d, num_of_tus = %d\n" , + tu.valid_boundary_link, tu.n_tus); + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (tu.n_tus +1 ,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + + temp =drm_fixp2int (temp2_fp); +if (temp && temp2_fp) + tu.extra_bytes =drm_fixp2int_ceil (temp2_fp); +else + tu.extra_bytes =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.extra_bytes,1 ); + temp2_fp =drm_fixp_from_fraction (8 , tu.bpp); + temp1_fp =drm_fixp_mul (temp1_fp, temp2_fp); + + temp =drm_fixp2int (temp1_fp); +if (temp && temp1_fp) + tu.extra_pclk_cycles =drm_fixp2int_ceil (temp1_fp); +else + tu.extra_pclk_cycles =0 ; + + temp1_fp =drm_fixp_div (tu.lclk_fp, tu.pclk_fp); + temp2_fp =drm_fixp_from_fraction (tu.extra_pclk_cycles,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + + temp =drm_fixp2int (temp1_fp); +if (temp && temp1_fp) + tu.extra_pclk_cycles_in_link_clk =drm_fixp2int_ceil (temp1_fp); +else + tu.extra_pclk_cycles_in_link_clk =0 ; + + tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link; + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + tu.ratio_by_tu_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + + tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk + + tu.filler_size + tu.extra_buffer_margin; + + tu.resulting_valid_fp = +drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_div (tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + + temp1_fp =drm_fixp_from_fraction ( + (tu.hbp_relative_to_pclk -HBLANK_MARGIN ),1 ); + tu.hbp_time_fp =drm_fixp_div (temp1_fp, tu.pclk_fp); + + temp1_fp =drm_fixp_from_fraction (tu.delay_start_link,1 ); + tu.delay_start_time_fp =drm_fixp_div (temp1_fp, tu.lclk_fp); + + compare_result_1 =_tu_param_compare (tu.hbp_time_fp, + tu.delay_start_time_fp); +if (compare_result_1 ==2 )/* if (hbp_time_fp < delay_start_time_fp) */ + tu.min_hblank_violated =1 ; + + temp1_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + tu.hactive_time_fp =drm_fixp_div (temp1_fp, tu.pclk_fp); + + compare_result_2 =_tu_param_compare (tu.hactive_time_fp, + tu.delay_start_time_fp); +if (compare_result_2 ==2 ) + tu.min_hblank_violated =1 ; + + tu.delay_start_time_fp =0 ; + +/* brute force */ + + tu.delay_start_link_extra_pixclk =EXTRA_PIXCLK_CYCLE_DELAY ; + tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp; + + temp =drm_fixp2int (tu.diff_abs_fp); +if (!temp && tu.diff_abs_fp <=0xffff ) + tu.diff_abs_fp =0 ; + +/* if(diff_abs < 0) diff_abs *= -1 */ +if (tu.diff_abs_fp <0 ) + tu.diff_abs_fp =drm_fixp_mul (tu.diff_abs_fp,-1 ); + + tu.boundary_mod_lower_err =0 ; +if ((tu.diff_abs_fp !=0 && + ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) || + (tu.even_distribution_legacy ==0 ) || + (DP_BRUTE_FORCE ==1 ))) || + (tu.min_hblank_violated ==1 )) { +do { + tu.err_fp =drm_fixp_from_fraction (1000 ,1 ); + + temp1_fp =drm_fixp_div (tu.lclk_fp, tu.pclk_fp); + temp2_fp =drm_fixp_from_fraction ( + tu.delay_start_link_extra_pixclk,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu.extra_buffer_margin = +drm_fixp2int_ceil (temp1_fp); +else + tu.extra_buffer_margin =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu.n_symbols =drm_fixp2int_ceil (temp1_fp); +else + tu.n_symbols =0 ; + +for (tu.tu_size =32 ; tu.tu_size <=64 ; tu.tu_size++) { +for (tu.i_upper_boundary_count =1 ; + tu.i_upper_boundary_count <=15 ; + tu.i_upper_boundary_count++) { +for (tu.i_lower_boundary_count =1 ; + tu.i_lower_boundary_count <=15 ; + tu.i_lower_boundary_count++) { +_tu_valid_boundary_calc (&tu); + } + } + } + tu.delay_start_link_extra_pixclk--; + }while (tu.boundary_moderation_en != true && + tu.boundary_mod_lower_err ==1 && + tu.delay_start_link_extra_pixclk !=0 ); + +if (tu.boundary_moderation_en == true) { + temp1_fp =drm_fixp_from_fraction ( + (tu.upper_boundary_count * + tu.valid_boundary_link + + tu.lower_boundary_count * + (tu.valid_boundary_link -1 )),1 ); + temp2_fp =drm_fixp_from_fraction ( + (tu.upper_boundary_count + + tu.lower_boundary_count),1 ); + tu.resulting_valid_fp = +drm_fixp_div (temp1_fp, temp2_fp); + + temp1_fp =drm_fixp_from_fraction ( + tu.tu_size_desired,1 ); + tu.ratio_by_tu_fp = +drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + + tu.valid_lower_boundary_link = + tu.valid_boundary_link -1 ; + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, + tu.resulting_valid_fp); + tu.n_tus =drm_fixp2int (temp2_fp); + + tu.tu_size_minus1 = tu.tu_size_desired -1 ; + tu.even_distribution_BF =1 ; + + temp1_fp = +drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp = +drm_fixp_div (tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + } + } + + temp1_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp2_fp =drm_fixp_mul (LCLK_FAST_SKEW_fp, temp1_fp); + +if (temp2_fp) + temp =drm_fixp2int_ceil (temp2_fp); +else + temp =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.nlanes,1 ); + temp2_fp =drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_div (temp1_fp, temp2_fp); + temp1_fp =drm_fixp_from_fraction (temp,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + temp =drm_fixp2int (temp2_fp); + +if (tu.async_en) + tu.delay_start_link += (int )temp; + + temp1_fp =drm_fixp_from_fraction (tu.delay_start_link,1 ); + tu.delay_start_time_fp =drm_fixp_div (temp1_fp, tu.lclk_fp); + +/* OUTPUTS */ + tu_table->valid_boundary_link = tu.valid_boundary_link; + tu_table->delay_start_link = tu.delay_start_link; + tu_table->boundary_moderation_en = tu.boundary_moderation_en; + tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link; + tu_table->upper_boundary_count = tu.upper_boundary_count; + tu_table->lower_boundary_count = tu.lower_boundary_count; + tu_table->tu_size_minus1 = tu.tu_size_minus1; + +DRM_DEBUG_DP ("TU: valid_boundary_link: %d\n" , tu_table->valid_boundary_link); +DRM_DEBUG_DP ("TU: delay_start_link: %d\n" , tu_table->delay_start_link); +DRM_DEBUG_DP ("TU: boundary_moderation_en: %d\n" , + tu_table->boundary_moderation_en); +DRM_DEBUG_DP ("TU: valid_lower_boundary_link: %d\n" , + tu_table->valid_lower_boundary_link); +DRM_DEBUG_DP ("TU: upper_boundary_count: %d\n" , + tu_table->upper_boundary_count); +DRM_DEBUG_DP ("TU: lower_boundary_count: %d\n" , + tu_table->lower_boundary_count); +DRM_DEBUG_DP ("TU: tu_size_minus1: %d\n" , tu_table->tu_size_minus1); +} + +static void dp_ctrl_calc_tu_parameters (struct dp_ctrl_private *ctrl, +struct dp_vc_tu_mapping_table *tu_table) +{ +struct dp_tu_calc_input in; +struct drm_display_mode *drm_mode; + + drm_mode = &ctrl->panel->dp_mode.drm_mode; + + in.lclk = ctrl->link->link_params.rate /1000 ; + in.pclk_khz = drm_mode->clock; + in.hactive = drm_mode->hdisplay; + in.hporch = drm_mode->htotal - drm_mode->hdisplay; + in.nlanes = ctrl->link->link_params.num_lanes; + in.bpp = ctrl->panel->dp_mode.bpp; + in.pixel_enc =444 ; + in.dsc_en =0 ; + in.async_en =0 ; + +_dp_ctrl_calc_tu (&in, tu_table); +} + +static void dp_ctrl_setup_tr_unit (struct dp_ctrl_private *ctrl) +{ +u32 dp_tu =0x0 ; +u32 valid_boundary =0x0 ; +u32 valid_boundary2 =0x0 ; +struct dp_vc_tu_mapping_table tu_calc_table; + +dp_ctrl_calc_tu_parameters (ctrl, &tu_calc_table); + + dp_tu |= tu_calc_table.tu_size_minus1; + valid_boundary |= tu_calc_table.valid_boundary_link; + valid_boundary |= (tu_calc_table.delay_start_link <<16 );
drivers/gpu/drm/msm/dp/dp_ctrl.c line 866
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ + valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link <<1 ); + valid_boundary2 |= (tu_calc_table.upper_boundary_count <<16 ); + valid_boundary2 |= (tu_calc_table.lower_boundary_count <<20 ); + +if (tu_calc_table.boundary_moderation_en) + valid_boundary2 |=BIT (0 ); + +pr_debug ("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n" , + dp_tu, valid_boundary, valid_boundary2);
Like here - this should be DRM_DEBUG_DP?
Quoted 158 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +158
-0+ + ctrl->catalog->dp_tu = dp_tu; + ctrl->catalog->valid_boundary = valid_boundary; + ctrl->catalog->valid_boundary2 = valid_boundary2; + +dp_catalog_ctrl_update_transfer_unit (ctrl->catalog); +} + +static int dp_ctrl_wait4video_ready (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + +if (!wait_for_completion_timeout (&ctrl->video_comp, +WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES )) { +DRM_ERROR ("Link Train timedout\n" ); + ret = -ETIMEDOUT ; + } +return ret; +} + +static int dp_ctrl_update_vx_px (struct dp_ctrl_private *ctrl) +{ +struct dp_link *link = ctrl->link; +int ret =0 , lane; +u8 buf[4 ]; +u32 max_level_reached =0 ; +u32 voltage_swing_level = link->phy_params.v_level; +u32 pre_emphasis_level = link->phy_params.p_level; + + ret =dp_catalog_ctrl_update_vx_px (ctrl->catalog, + voltage_swing_level, pre_emphasis_level); +if (ret) +return ret; + +if (voltage_swing_level ==DP_TRAIN_VOLTAGE_SWING_MAX ) { +pr_debug ("max. voltage swing level reached %d\n" , + voltage_swing_level); + max_level_reached |=DP_TRAIN_MAX_SWING_REACHED ; + } + +if (pre_emphasis_level ==DP_TRAIN_PRE_EMPHASIS_MAX ) { +pr_debug ("max. pre-emphasis level reached %d\n" , + pre_emphasis_level); + max_level_reached |=DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ; + } + + pre_emphasis_level <<=DP_TRAIN_PRE_EMPHASIS_SHIFT ; + +for (lane =0 ; lane <4 ; lane++) + buf[lane] = voltage_swing_level | pre_emphasis_level | max_level_reached; + +pr_debug ("sink: p|v=0x%x\n" , voltage_swing_level | pre_emphasis_level); + ret =drm_dp_dpcd_write (ctrl->aux->drm_aux,DP_TRAINING_LANE0_SET , buf,4 ); +if (ret ==4 ) + ret =0 ; + +return ret; +} + +static bool dp_ctrl_train_pattern_set (struct dp_ctrl_private *ctrl, +u8 pattern) +{ +u8 buf[4 ]; +int ret =0 ; + +pr_debug ("sink: pattern=%x\n" , pattern); + + buf[0 ] = pattern; + ret =drm_dp_dpcd_writeb (ctrl->aux->drm_aux,DP_TRAINING_PATTERN_SET , buf[0 ]); +return ret ==1 ; +} + +static int dp_ctrl_read_link_status (struct dp_ctrl_private *ctrl, +u8 *link_status) +{ +int len =0 ; +u32 const offset =DP_LANE_ALIGN_STATUS_UPDATED -DP_LANE0_1_STATUS ; +u32 link_status_read_max_retries =100 ; + +while (--link_status_read_max_retries) { + len =drm_dp_dpcd_read_link_status (ctrl->aux->drm_aux, + link_status); +if (len !=DP_LINK_STATUS_SIZE ) { +DRM_ERROR ("DP link status read failed, err: %d\n" , len); +return len; + } + +if (!(link_status[offset] &DP_LINK_STATUS_UPDATED )) +return 0 ; + } + +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_train_1 (struct dp_ctrl_private *ctrl) +{ +int tries, old_v_level, ret =0 ; +u8 link_status[DP_LINK_STATUS_SIZE ]; +int const maximum_retries =5 ; + +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + + ret =dp_catalog_ctrl_set_pattern (ctrl->catalog,DP_TRAINING_PATTERN_1 ); +if (ret) +return ret; +dp_ctrl_train_pattern_set (ctrl,DP_TRAINING_PATTERN_1 | +DP_LINK_SCRAMBLING_DISABLE ); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + tries =0 ; + old_v_level = ctrl->link->phy_params.v_level; +for (tries =0 ; tries < maximum_retries; tries++) { +drm_dp_link_train_clock_recovery_delay (ctrl->panel->dpcd); + + ret =dp_ctrl_read_link_status (ctrl, link_status); +if (ret) +return ret; + +if (drm_dp_clock_recovery_ok (link_status, + ctrl->link->link_params.num_lanes)) { +return ret; + } + +if (ctrl->link->phy_params.v_level ==DP_TRAIN_VOLTAGE_SWING_MAX ) { +DRM_ERROR_RATELIMITED ("max v_level reached\n" ); +return -EAGAIN ; + } + +if (old_v_level != ctrl->link->phy_params.v_level) { + tries =0 ; + old_v_level = ctrl->link->phy_params.v_level; + } + +pr_debug ("clock recovery not done, adjusting vx px\n" ); + +dp_link_adjust_levels (ctrl->link, link_status); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + } + +DRM_ERROR ("max tries reached\n" ); +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_rate_down_shift (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + +switch (ctrl->link->link_params.rate) { +case 810000 : + ctrl->link->link_params.rate =540000 ; +break ; +case 540000 : + ctrl->link->link_params.rate =270000 ; +break ;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1034
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+case 270000 : +case 162000 : +default : + ctrl->link->link_params.rate =162000 ; +break ; + }; + +pr_debug ("new rate=0x%x\n" , ctrl->link->link_params.rate); + +return ret;
ret is unused in this function - return 0;
Quoted 145 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +145
-0+} + +static void dp_ctrl_clear_training_pattern (struct dp_ctrl_private *ctrl) +{ +dp_ctrl_train_pattern_set (ctrl,DP_TRAINING_PATTERN_DISABLE ); +drm_dp_link_train_channel_eq_delay (ctrl->panel->dpcd); +} + +static int dp_ctrl_link_training_2 (struct dp_ctrl_private *ctrl) +{ +int tries =0 , ret =0 ; +char pattern; +int const maximum_retries =5 ; +u8 link_status[DP_LINK_STATUS_SIZE ]; + +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + +if (drm_dp_tps3_supported (ctrl->panel->dpcd)) + pattern =DP_TRAINING_PATTERN_3 ; +else + pattern =DP_TRAINING_PATTERN_2 ; + + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + ret =dp_catalog_ctrl_set_pattern (ctrl->catalog, pattern); +if (ret) +return ret; + +dp_ctrl_train_pattern_set (ctrl, pattern |DP_RECOVERED_CLOCK_OUT_EN ); + +for (tries =0 ; tries <= maximum_retries; tries++) { +drm_dp_link_train_channel_eq_delay (ctrl->panel->dpcd); + + ret =dp_ctrl_read_link_status (ctrl, link_status); +if (ret) +return ret; + +if (drm_dp_channel_eq_ok (link_status, + ctrl->link->link_params.num_lanes)) +return ret; + +dp_link_adjust_levels (ctrl->link, link_status); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + } + +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_train (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; +u8 encoding =DP_SET_ANSI_8B10B ; +struct drm_dp_link link_info = {0 }; + + ctrl->link->phy_params.p_level =0 ; + ctrl->link->phy_params.v_level =0 ; + +dp_ctrl_config_ctrl (ctrl); + + ret =drm_dp_link_probe (ctrl->aux->drm_aux, &link_info); +if (ret <0 ) { +DRM_ERROR ("failed to retrieve link capabilities. ret=%d\n" , ret); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); +return ret; + } + +drm_dp_link_configure (ctrl->aux->drm_aux, &link_info); +drm_dp_dpcd_write (ctrl->aux->drm_aux,DP_MAIN_LINK_CHANNEL_CODING_SET , + &encoding,1 ); + + ret =dp_ctrl_link_train_1 (ctrl); +if (ret) { +DRM_ERROR ("link training #1 failed. ret=%d\n" , ret); + goto end; + } + +/* print success info as this is a result of user initiated action */ +DRM_DEBUG_DP ("link training #1 successful\n" ); + + ret =dp_ctrl_link_training_2 (ctrl); +if (ret) { +DRM_ERROR ("link training #2 failed. ret=%d\n" , ret); + goto end; + } + +/* print success info as this is a result of user initiated action */ +DRM_DEBUG_DP ("link training #2 successful\n" ); + +end: +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + +dp_ctrl_clear_training_pattern (ctrl); +return ret; +} + +static int dp_ctrl_setup_main_link (struct dp_ctrl_private *ctrl,bool train) +{ +bool mainlink_ready = false; +int ret =0 ; + +dp_catalog_ctrl_mainlink_ctrl (ctrl->catalog, true); + + ret =dp_link_psm_config (ctrl->link, &ctrl->panel->link_info, false); +if (ret) +return ret; + +if (ctrl->link->sink_request &DP_TEST_LINK_PHY_TEST_PATTERN ) +return ret; + +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 do a DP software reset. +*/ +dp_catalog_ctrl_reset (ctrl->catalog); + + ret =dp_ctrl_link_train (ctrl); +if (ret) +return ret; +Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1172
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+send_video: +/* +* Set up transfer unit values and set controller state to send +* video. +*/ +dp_ctrl_setup_tr_unit (ctrl); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,DP_STATE_CTRL_SEND_VIDEO ); + + ret =dp_ctrl_wait4video_ready (ctrl); +if (ret)
Why are you walking backwards in this list? Seems that going forward is clearer.
for(num = 0; num < ctrl->parser->mp[DP_CTRL_PM].num_clk; num++, cfg++) {
if (strcmp(cfg->clk_name, name)) {
cfg->rate = rate;
return;
}}
/* error message */
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This isn't exactly accurate - you aren't setting anything in the hardware but the clock doesn't exist in your list. You should say that it doesn't.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It will probably come up elsewhere too, but the clock names shouldn't have the _clk extension - they are only named in one spot and we know they are clocks. You should just name it "ctrl_link" (and update the DT and bindings of course).
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 41 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +41
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
If you are de-initing, a error message isn't needed here.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 199 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +199
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This can just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +31
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return rc;
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 37 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +37
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label isn't needed.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 51 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +51
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return ERR_PTR(-EINVAL) but this feels like one of those situations where you can feel pretty sure that the caller will populate everything correctly.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(-ENOMEM)
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +21
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Not needed.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You don't need to destroy the mutex if the memory is getting cleared in the next step.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As with the other usages of devm_kfree()
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 110 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +36
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.c new file +61
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This line should have a comma after it.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It is not possible for 'dp' to be NULL.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 25 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +25
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It is not possible for any of these to be NULL
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It should not be possible for any of these to be NULL either.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return rc;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return rc;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return rc;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label isn't needed and you can just return 0;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
These can never be NULL.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Neither can this, I don't believe.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_power_client_deinit is already returning void.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_display.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +27
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The result from container_of() can never be NULL.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 52 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +52
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You can can just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +15
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return 0 and the label isn't needed.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 50 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +50
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It doesn't appear to me that this will ever be true - there is only one caller.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_display.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return -EINVAL;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return -ENODEV;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return 0 and the label isn't needed
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As above, I don't think this will ever be NULL
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
but if it is, just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return -ENODEV;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 18 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +18
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Remove the label and return 0;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 188 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +188
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is only ever 0.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 37 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +37
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is only ever 0.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +15
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is only ever 0.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return 0;
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is only ever 0 and you don't need the label.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 130 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +130
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Neither pdev or pdev->dev.of_node can be NULL.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You don't need to devm_kfree, it will be done for you when the probe fails.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Not possible.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This is unneeded since the device is about to go poof.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_display.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You don't need to devm_kfree, it will be done when the device is destroyed.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +21
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You don't need this, just drop through.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 18 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +18
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This could also be WARN_ON(!encoder || !dp_display || !dev)
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_display_request_irq already prints error messages for you.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 167 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +106
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.h new file +28
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.c new file +20
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Prefer if you use a function for this for typechecking purposes.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 58 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +58
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
How big is dp_mode? Why do you need to kzalloc it and not have it it on the stack?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
ARe you missing a kfree here?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +39
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
I don't think these can be NULL if they are called from the drm_connector helper functions.
drivers/gpu/drm/msm/dp/dp_drm.h
Quoted 81 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +60
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.h new file +15
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
What are all these headers used for? It looks like this prototype only needs struct drm_connector and struct msm_dp.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 178 lines
drivers/gpu/drm/msm/dp/dp_drm.h new file +5
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.c new file +167
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
If you are unregistering this log message isn't useful.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Don't do a bare return at the bottom of a void function.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This could just be return ERR_PTR(-EINVAL)
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(-ENOMEM)
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
If this is really peristent memory across the live of the driver you don't need to devm_kfree() here because presumably this function failing will end up destroying the component. If that isn't the case (for example, if this struct is runtime) you should just use kzalloc() and manage the memory yourself.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_extcon.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This can just be return ERR_PTR(-EINVAL)
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +21
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As with the other devm_kfree() calls.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 165 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +1
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.h new file +85
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_link.c new file +67
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Instead of a goto that returns a value, just return the value directly.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 65 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +65
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +20
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This can be return -EINVAL;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label isn't needed, you can just return 0 and then I don't think ret is needed either.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 43 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +43
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As above - return directly instead of using the goto and I think ret is otherwise unused again.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ret;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ret;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +5
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label isn't needed.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 123 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +123
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return -EINVAL;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +22
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Return -EINVAL;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 108 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +108
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This can just be return 0;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 386 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +386
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
ret is unused in this function. You can return 0;
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 322 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +322
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(-EINVAL)
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This should be ERR_PTR(-ENOMEM)
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The label and return isn't needed.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same as the other devm_kfree() usages
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 215 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +1
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_link.h new file +132
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_panel.c new file +70
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is unused in this function - yo ucan return 0;
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 59 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +59
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It doesn't look like panel can ever be NULL here.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 297 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +297
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is unused in this function. You can return 0;
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +31
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc is unset in this function.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(-EINVAL) but really evaluate if this is possible since the caller would presumably have populated everything before calling.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PRTR(-ENOMEM)
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 29 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +29
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same as the other callers of devm_kfree()
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 143 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +1
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_panel.h new file +91
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_parser.c new file +39
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
msm_drv already has a msm_ioremap() function - you should consider reusing that.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +15
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Bonus that msm_ioremap() uses dev_ioremap() so you probably don't need this function.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +16
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Or this function.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Why is this fatal?
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
If you follow the above suggestions, then you don't need to call dp_parser_unmap_io_resources and you can return rc (well, actually, the PTR_ERR of the return pointer). Also, msm_ioremap() already prints a log message so you don't need one.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 102 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +102
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It looks like this is basically the same as:
char property[24];
snprintf(property, sizeof(property), "qcom,aux-cfg%d-settings", i);
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 43 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +42
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
of_property_read_u32 doesn't change the value of the pointer if it has an error, so this can be:
parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; of_property_read_u32(of_node, "qcom,max-pclk-frequency-khz", &parser->max_pclk_khz);
And thats it. In fact, this might not even qualify as a function - it seems like this would be a lot happier if it was done inline.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 52 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +52
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
use devm_kcalloc() here instead.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 30 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +30
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Is this even possible?
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 33 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +33
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
use devm_kcalloc()
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 80 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +80
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_parser_get_vreg prints a LOT of error messages. You don't need any more.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_parser.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This line doesn't seem useful.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 52 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +52
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
use devm_kcalloc()
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return -ENOMEM;
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +11
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
use devm_kcalloc()
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return -ENOMEM;
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +22
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Plenty of error messages in dp_parser_init_clk_data;
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_parser.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You should return the value that dp_parser_init_clk_data returned.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 30 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +30
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As discussed above, the "clk" extension is frowned upon. And I don't think you want to use strncmp here because you are comparing the entire string so use strcmp() instead.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +19
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This won't be NULL.
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 50 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +50
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Why does this stub even exist?
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 25 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +19
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Comma needed after this line.
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As with the other function that does something very similar, I don't think this is possible.
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
refrece -> reference
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 200 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +161
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_power.c new file +33
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This can just be return 0
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
this function is only called from one spot, so printing the return address isn't useful.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +14
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This will be done when the device/component is destroyed.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
All of this is spaghetti code that could be turned into just a few lines:
for( ; i >= 0; i--) {
if (in_vreg[i].vreg)
regulator_set_load(in_vreg[i].vreg, 0);
}
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +24
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This will be done for you when the component/device is destroyed.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +17
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As above, this is only called from one function.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +12
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As above.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As above
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 54 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +54
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The calling function prints ever so many error messages.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return rc;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label isn't needed and you can return 0;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 18 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +18
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The function you are calling prints error messages and anyway, you are in deinit so the error messages are probably not as interesting.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +16
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The called function has many error messages.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return rc;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Label not needed and you can return 0;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
if parser->pinctrl.pin is NULL this will return 0 which may not be your intention?
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You can skip this, drop out and return rc;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +20
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Do you want to use DRM_INFO here?
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +39
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You don't need a log message if you are in deinit
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +26
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You can drop out and return rc;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 82 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +81
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
It doesn't look like power can be NULL here.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 61 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +61
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
the called function already prints error messages.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +31
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The called function and friends prints lots of error messages.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +17
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This isn't a useful log message while you are tearing things down.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +21
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return -EINVAL;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 30 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +30
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Lable is not needed
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 33 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +33
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This will call pm_runtime_put_sync which is what you don't want, just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +5
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
All of the functions here should be printing sufficient error messages so you don't need any more.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 59 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +59
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(rc);
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
return ERR_PTR(-ENOMEM);
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +23
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same comment as all of the other devm_kfree() callers
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_power.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
<snip> I have no problem with the rest.
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Part of the diff is not shown here. View the raw message.
kbuild test robot
build botRe: [DPU PATCH v2 2/3] drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveThank you for the patch! Yet something to improve:
Hi Chandan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on robclark/msm-next]
[also build test ERROR on v5.0-rc1 next-20190108]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Chandan-Uddaraju/List-of-patches-for-DP-drivers-on-SnapDragon/20190109-052537 base: git://people.freedesktop.org/~robclark/linux msm-next config: arm-allmodconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=arm
All error/warnings (new ones prefixed by >>):
In file included from drivers/gpu/drm/msm/dp/dp_link.c:9:0:
drivers/gpu/drm/msm/dp/dp_panel.h:20:26: error: field 'drm_mode' has incomplete type
struct drm_display_mode drm_mode;
^~~~~~~~
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_get_period':
drivers/gpu/drm/msm/dp/dp_link.c:52:3: error: implicit declaration of function 'DRM_ERROR'; did you mean 'DRM_IOR'? [-Werror=implicit-function-declaration]
DRM_ERROR("failed to read test_audio_period (0x%x)\n", addr);
^~~~~~~~~
DRM_IOR
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_channel_period':
drivers/gpu/drm/msm/dp/dp_link.c:75:33: error: 'DP_TEST_AUDIO_PERIOD_CH1' undeclared (first use in this function); did you mean 'DP_TEST_BIT_DEPTH_12'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_BIT_DEPTH_12
drivers/gpu/drm/msm/dp/dp_link.c:75:33: note: each undeclared identifier is reported only once for each function it appears in
drivers/gpu/drm/msm/dp/dp_link.c:80:2: error: implicit declaration of function 'DRM_DEBUG_DP'; did you mean 'KERN_DEBUG'? [-Werror=implicit-function-declaration]
DRM_DEBUG_DP("test_audio_period_ch_1 = 0x%x\n", ret);
^~~~~~~~~~~~
KERN_DEBUG
>> drivers/gpu/drm/msm/dp/dp_link.c:82:33: error: 'DP_TEST_AUDIO_PERIOD_CH2' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH1'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH1
>> drivers/gpu/drm/msm/dp/dp_link.c:90:33: error: 'DP_TEST_AUDIO_PERIOD_CH3' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH2'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH2
>> drivers/gpu/drm/msm/dp/dp_link.c:97:33: error: 'DP_TEST_AUDIO_PERIOD_CH4' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH3'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH3
>> drivers/gpu/drm/msm/dp/dp_link.c:104:33: error: 'DP_TEST_AUDIO_PERIOD_CH5' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH4'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH4
>> drivers/gpu/drm/msm/dp/dp_link.c:111:33: error: 'DP_TEST_AUDIO_PERIOD_CH6' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH5'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH5
>> drivers/gpu/drm/msm/dp/dp_link.c:118:33: error: 'DP_TEST_AUDIO_PERIOD_CH7' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH6'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH6
>> drivers/gpu/drm/msm/dp/dp_link.c:125:33: error: 'DP_TEST_AUDIO_PERIOD_CH8' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH7'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH7
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_pattern_type':
>> drivers/gpu/drm/msm/dp/dp_link.c:143:5: error: 'DP_TEST_AUDIO_PATTERN_TYPE' undeclared (first use in this function); did you mean 'DP_TEST_PHY_PATTERN'?
DP_TEST_AUDIO_PATTERN_TYPE, &data);
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_PHY_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_mode':
drivers/gpu/drm/msm/dp/dp_link.c:172:47: error: 'DP_TEST_AUDIO_MODE' undeclared (first use in this function); did you mean 'DP_TEST_COUNT_MASK'?
rlen = drm_dp_dpcd_readb(link->aux->drm_aux, DP_TEST_AUDIO_MODE, &data);
^~~~~~~~~~~~~~~~~~
DP_TEST_COUNT_MASK
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_audio_test_requested':
>> drivers/gpu/drm/msm/dp/dp_link.c:577:5: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
DP_TEST_LINK_AUDIO_PATTERN |
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
>> drivers/gpu/drm/msm/dp/dp_link.c:578:5: error: 'DP_TEST_LINK_AUDIO_DISABLED_VIDEO' undeclared (first use in this function); did you mean 'DP_TEST_LINK_AUDIO_PATTERN'?
DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_AUDIO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_pattern_requested':
>> drivers/gpu/drm/msm/dp/dp_link.c:974:3: error: 'DP_TEST_LINK_AUDIO_DISABLED_VIDEO' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_audio_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:979:41: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN);
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_process_request':
drivers/gpu/drm/msm/dp/dp_link.c:1052:28: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_get_colorimetry_config':
>> drivers/gpu/drm/msm/dp/dp_link.c:1078:8: error: 'DP_TEST_DYNAMIC_RANGE_VESA' undeclared (first use in this function); did you mean 'DP_TEST_DYNAMIC_RANGE_CEA'?
cc = DP_TEST_DYNAMIC_RANGE_VESA;
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_DYNAMIC_RANGE_CEA
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_pattern_requested':
>> drivers/gpu/drm/msm/dp/dp_link.c:975:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_audio_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:980:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^cc1: some warnings being treated as errors
vim +82 drivers/gpu/drm/msm/dp/dp_link.c
69
70 static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
71 {
72 int ret = 0;
73 struct dp_link_test_audio *req = &link->dp_link.test_audio;
74
> 75 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
76 if (ret == -EINVAL)
77 goto exit;
78
79 req->test_audio_period_ch_1 = ret;
80 DRM_DEBUG_DP("test_audio_period_ch_1 = 0x%x\n", ret);
81
> 82 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
83 if (ret == -EINVAL)
84 goto exit;
85
86 req->test_audio_period_ch_2 = ret;
87 DRM_DEBUG_DP("test_audio_period_ch_2 = 0x%x\n", ret);
88
89 /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */
> 90 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
91 if (ret == -EINVAL)
92 goto exit;
93
94 req->test_audio_period_ch_3 = ret;
95 DRM_DEBUG_DP("test_audio_period_ch_3 = 0x%x\n", ret);
96
> 97 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
98 if (ret == -EINVAL)
99 goto exit;
100
101 req->test_audio_period_ch_4 = ret;
102 DRM_DEBUG_DP("test_audio_period_ch_4 = 0x%x\n", ret);
103
> 104 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
105 if (ret == -EINVAL)
106 goto exit;
107
108 req->test_audio_period_ch_5 = ret;
109 DRM_DEBUG_DP("test_audio_period_ch_5 = 0x%x\n", ret);
110
> 111 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
112 if (ret == -EINVAL)
113 goto exit;
114
115 req->test_audio_period_ch_6 = ret;
116 DRM_DEBUG_DP("test_audio_period_ch_6 = 0x%x\n", ret);
117
> 118 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
119 if (ret == -EINVAL)
120 goto exit;
121
122 req->test_audio_period_ch_7 = ret;
123 DRM_DEBUG_DP("test_audio_period_ch_7 = 0x%x\n", ret);
124
> 125 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
126 if (ret == -EINVAL)
127 goto exit;
128
129 req->test_audio_period_ch_8 = ret;
130 DRM_DEBUG_DP("test_audio_period_ch_8 = 0x%x\n", ret);
131 exit:
132 return ret;
133 }
134
135 static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
136 {
137 int ret = 0;
138 u8 data;
139 ssize_t rlen;
140 int const max_audio_pattern_type = 0x1;
141
142 rlen = drm_dp_dpcd_readb(link->aux->drm_aux,
> 143 DP_TEST_AUDIO_PATTERN_TYPE, &data);
144 if (rlen < 0) {
145 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
146 return rlen;
147 }
148
149 /* Audio Pattern Type - Bits 7:0 */
150 if ((int)data > max_audio_pattern_type) {
151 DRM_ERROR("invalid audio pattern type = 0x%x\n", data);
152 ret = -EINVAL;
153 goto exit;
154 }
155
156 link->dp_link.test_audio.test_audio_pattern_type = data;
157 DRM_DEBUG_DP("audio pattern type = 0x%x\n", data);
158 exit:
159 return ret;
160 }
161
162 static int dp_link_parse_audio_mode(struct dp_link_private *link)
163 {
164 int ret = 0;
165 u8 data;
166 ssize_t rlen;
167 int const max_audio_sampling_rate = 0x6;
168 int const max_audio_channel_count = 0x8;
169 int sampling_rate = 0x0;
170 int channel_count = 0x0;
171
> 172 rlen = drm_dp_dpcd_readb(link->aux->drm_aux, DP_TEST_AUDIO_MODE, &data); 173 if (rlen < 0) {
174 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
175 return rlen;
176 }
177
178 /* Sampling Rate - Bits 3:0 */
179 sampling_rate = data & 0xF;
180 if (sampling_rate > max_audio_sampling_rate) {
181 DRM_ERROR("sampling rate (0x%x) greater than max (0x%x)\n",
182 sampling_rate, max_audio_sampling_rate);
183 ret = -EINVAL;
184 goto exit;
185 }
186
187 /* Channel Count - Bits 7:4 */
188 channel_count = ((data & 0xF0) >> 4) + 1;
189 if (channel_count > max_audio_channel_count) {
190 DRM_ERROR("channel_count (0x%x) greater than max (0x%x)\n",
191 channel_count, max_audio_channel_count);
192 ret = -EINVAL;
193 goto exit;
194 }
195
196 link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
197 link->dp_link.test_audio.test_audio_channel_count = channel_count;
198 DRM_DEBUG_DP("sampling_rate = 0x%x, channel_count = 0x%x\n",
199 sampling_rate, channel_count);
200 exit:
201 return ret;
202 }
203
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
kbuild test robot
build botRe: [DPU PATCH v2 3/3] drm/msm/dp: add support for DP PLL driver
In reply to a message not in the archiveThank you for the patch! Yet something to improve:
Hi Chandan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on robclark/msm-next]
[also build test ERROR on v5.0-rc1 next-20190108]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Chandan-Uddaraju/List-of-patches-for-DP-drivers-on-SnapDragon/20190109-052537 base: git://people.freedesktop.org/~robclark/linux msm-next config: arm-allmodconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=arm
All error/warnings (new ones prefixed by >>):
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_channel_period':
>> drivers/gpu/drm/msm/dp/dp_link.c:75:33: error: 'DP_TEST_AUDIO_PERIOD_CH1' undeclared (first use in this function); did you mean 'DP_TEST_BIT_DEPTH_10'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_BIT_DEPTH_10
drivers/gpu/drm/msm/dp/dp_link.c:75:33: note: each undeclared identifier is reported only once for each function it appears in
drivers/gpu/drm/msm/dp/dp_link.c:82:33: error: 'DP_TEST_AUDIO_PERIOD_CH2' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH1'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH1
drivers/gpu/drm/msm/dp/dp_link.c:90:33: error: 'DP_TEST_AUDIO_PERIOD_CH3' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH2'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH2
drivers/gpu/drm/msm/dp/dp_link.c:97:33: error: 'DP_TEST_AUDIO_PERIOD_CH4' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH3'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH3
drivers/gpu/drm/msm/dp/dp_link.c:104:33: error: 'DP_TEST_AUDIO_PERIOD_CH5' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH4'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH4
drivers/gpu/drm/msm/dp/dp_link.c:111:33: error: 'DP_TEST_AUDIO_PERIOD_CH6' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH5'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH5
drivers/gpu/drm/msm/dp/dp_link.c:118:33: error: 'DP_TEST_AUDIO_PERIOD_CH7' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH6'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH6
drivers/gpu/drm/msm/dp/dp_link.c:125:33: error: 'DP_TEST_AUDIO_PERIOD_CH8' undeclared (first use in this function); did you mean 'DP_TEST_AUDIO_PERIOD_CH7'?
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
^~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_AUDIO_PERIOD_CH7
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_pattern_type':
drivers/gpu/drm/msm/dp/dp_link.c:143:5: error: 'DP_TEST_AUDIO_PATTERN_TYPE' undeclared (first use in this function); did you mean 'DP_TEST_PHY_PATTERN'?
DP_TEST_AUDIO_PATTERN_TYPE, &data);
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_PHY_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_parse_audio_mode':
>> drivers/gpu/drm/msm/dp/dp_link.c:172:47: error: 'DP_TEST_AUDIO_MODE' undeclared (first use in this function); did you mean 'DP_TEST_LINK_RATE'?
rlen = drm_dp_dpcd_readb(link->aux->drm_aux, DP_TEST_AUDIO_MODE, &data);
^~~~~~~~~~~~~~~~~~
DP_TEST_LINK_RATE
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_audio_test_requested':
drivers/gpu/drm/msm/dp/dp_link.c:577:5: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
DP_TEST_LINK_AUDIO_PATTERN |
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c:578:5: error: 'DP_TEST_LINK_AUDIO_DISABLED_VIDEO' undeclared (first use in this function); did you mean 'DP_TEST_LINK_AUDIO_PATTERN'?
DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_AUDIO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:974:3: error: 'DP_TEST_LINK_AUDIO_DISABLED_VIDEO' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_audio_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:979:41: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN);
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_process_request':
drivers/gpu/drm/msm/dp/dp_link.c:1052:28: error: 'DP_TEST_LINK_AUDIO_PATTERN' undeclared (first use in this function); did you mean 'DP_TEST_LINK_VIDEO_PATTERN'?
dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_LINK_VIDEO_PATTERN
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_get_colorimetry_config':
drivers/gpu/drm/msm/dp/dp_link.c:1078:8: error: 'DP_TEST_DYNAMIC_RANGE_VESA' undeclared (first use in this function); did you mean 'DP_TEST_DYNAMIC_RANGE_CEA'?
cc = DP_TEST_DYNAMIC_RANGE_VESA;
^~~~~~~~~~~~~~~~~~~~~~~~~~
DP_TEST_DYNAMIC_RANGE_CEA
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_video_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:975:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
drivers/gpu/drm/msm/dp/dp_link.c: In function 'dp_link_is_audio_pattern_requested':
drivers/gpu/drm/msm/dp/dp_link.c:980:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
--
drivers/gpu/drm/msm/dp/dp_power.c: In function 'dp_power_init':
>> drivers/gpu/drm/msm/dp/dp_power.c:677:28: warning: 'power' may be used uninitialized in this function [-Wmaybe-uninitialized]
pm_runtime_put_sync(&power->pdev->dev);
~~~~~^~~~~~vim +75 drivers/gpu/drm/msm/dp/dp_link.c
c24ff5297 Chandan Uddaraju 2019-01-07 69
c24ff5297 Chandan Uddaraju 2019-01-07 70 static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
c24ff5297 Chandan Uddaraju 2019-01-07 71 {
c24ff5297 Chandan Uddaraju 2019-01-07 72 int ret = 0;
c24ff5297 Chandan Uddaraju 2019-01-07 73 struct dp_link_test_audio *req = &link->dp_link.test_audio;
c24ff5297 Chandan Uddaraju 2019-01-07 74
c24ff5297 Chandan Uddaraju 2019-01-07 @75 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
c24ff5297 Chandan Uddaraju 2019-01-07 76 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 77 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 78
c24ff5297 Chandan Uddaraju 2019-01-07 79 req->test_audio_period_ch_1 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 80 DRM_DEBUG_DP("test_audio_period_ch_1 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 81
c24ff5297 Chandan Uddaraju 2019-01-07 82 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
c24ff5297 Chandan Uddaraju 2019-01-07 83 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 84 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 85
c24ff5297 Chandan Uddaraju 2019-01-07 86 req->test_audio_period_ch_2 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 87 DRM_DEBUG_DP("test_audio_period_ch_2 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 88
c24ff5297 Chandan Uddaraju 2019-01-07 89 /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */
c24ff5297 Chandan Uddaraju 2019-01-07 90 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
c24ff5297 Chandan Uddaraju 2019-01-07 91 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 92 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 93
c24ff5297 Chandan Uddaraju 2019-01-07 94 req->test_audio_period_ch_3 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 95 DRM_DEBUG_DP("test_audio_period_ch_3 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 96
c24ff5297 Chandan Uddaraju 2019-01-07 97 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
c24ff5297 Chandan Uddaraju 2019-01-07 98 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 99 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 100
c24ff5297 Chandan Uddaraju 2019-01-07 101 req->test_audio_period_ch_4 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 102 DRM_DEBUG_DP("test_audio_period_ch_4 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 103
c24ff5297 Chandan Uddaraju 2019-01-07 104 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
c24ff5297 Chandan Uddaraju 2019-01-07 105 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 106 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 107
c24ff5297 Chandan Uddaraju 2019-01-07 108 req->test_audio_period_ch_5 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 109 DRM_DEBUG_DP("test_audio_period_ch_5 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 110
c24ff5297 Chandan Uddaraju 2019-01-07 111 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
c24ff5297 Chandan Uddaraju 2019-01-07 112 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 113 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 114
c24ff5297 Chandan Uddaraju 2019-01-07 115 req->test_audio_period_ch_6 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 116 DRM_DEBUG_DP("test_audio_period_ch_6 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 117
c24ff5297 Chandan Uddaraju 2019-01-07 118 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
c24ff5297 Chandan Uddaraju 2019-01-07 119 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 120 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 121
c24ff5297 Chandan Uddaraju 2019-01-07 122 req->test_audio_period_ch_7 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 123 DRM_DEBUG_DP("test_audio_period_ch_7 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 124
c24ff5297 Chandan Uddaraju 2019-01-07 125 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
c24ff5297 Chandan Uddaraju 2019-01-07 126 if (ret == -EINVAL)
c24ff5297 Chandan Uddaraju 2019-01-07 127 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 128
c24ff5297 Chandan Uddaraju 2019-01-07 129 req->test_audio_period_ch_8 = ret;
c24ff5297 Chandan Uddaraju 2019-01-07 130 DRM_DEBUG_DP("test_audio_period_ch_8 = 0x%x\n", ret);
c24ff5297 Chandan Uddaraju 2019-01-07 131 exit:
c24ff5297 Chandan Uddaraju 2019-01-07 132 return ret;
c24ff5297 Chandan Uddaraju 2019-01-07 133 }
c24ff5297 Chandan Uddaraju 2019-01-07 134
c24ff5297 Chandan Uddaraju 2019-01-07 135 static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
c24ff5297 Chandan Uddaraju 2019-01-07 136 {
c24ff5297 Chandan Uddaraju 2019-01-07 137 int ret = 0;
c24ff5297 Chandan Uddaraju 2019-01-07 138 u8 data;
c24ff5297 Chandan Uddaraju 2019-01-07 139 ssize_t rlen;
c24ff5297 Chandan Uddaraju 2019-01-07 140 int const max_audio_pattern_type = 0x1;
c24ff5297 Chandan Uddaraju 2019-01-07 141
c24ff5297 Chandan Uddaraju 2019-01-07 142 rlen = drm_dp_dpcd_readb(link->aux->drm_aux,
c24ff5297 Chandan Uddaraju 2019-01-07 @143 DP_TEST_AUDIO_PATTERN_TYPE, &data);
c24ff5297 Chandan Uddaraju 2019-01-07 144 if (rlen < 0) {
c24ff5297 Chandan Uddaraju 2019-01-07 145 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
c24ff5297 Chandan Uddaraju 2019-01-07 146 return rlen;
c24ff5297 Chandan Uddaraju 2019-01-07 147 }
c24ff5297 Chandan Uddaraju 2019-01-07 148
c24ff5297 Chandan Uddaraju 2019-01-07 149 /* Audio Pattern Type - Bits 7:0 */
c24ff5297 Chandan Uddaraju 2019-01-07 150 if ((int)data > max_audio_pattern_type) {
c24ff5297 Chandan Uddaraju 2019-01-07 151 DRM_ERROR("invalid audio pattern type = 0x%x\n", data);
c24ff5297 Chandan Uddaraju 2019-01-07 152 ret = -EINVAL;
c24ff5297 Chandan Uddaraju 2019-01-07 153 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 154 }
c24ff5297 Chandan Uddaraju 2019-01-07 155
c24ff5297 Chandan Uddaraju 2019-01-07 156 link->dp_link.test_audio.test_audio_pattern_type = data;
c24ff5297 Chandan Uddaraju 2019-01-07 157 DRM_DEBUG_DP("audio pattern type = 0x%x\n", data);
c24ff5297 Chandan Uddaraju 2019-01-07 158 exit:
c24ff5297 Chandan Uddaraju 2019-01-07 159 return ret;
c24ff5297 Chandan Uddaraju 2019-01-07 160 }
c24ff5297 Chandan Uddaraju 2019-01-07 161
c24ff5297 Chandan Uddaraju 2019-01-07 162 static int dp_link_parse_audio_mode(struct dp_link_private *link)
c24ff5297 Chandan Uddaraju 2019-01-07 163 {
c24ff5297 Chandan Uddaraju 2019-01-07 164 int ret = 0;
c24ff5297 Chandan Uddaraju 2019-01-07 165 u8 data;
c24ff5297 Chandan Uddaraju 2019-01-07 166 ssize_t rlen;
c24ff5297 Chandan Uddaraju 2019-01-07 167 int const max_audio_sampling_rate = 0x6;
c24ff5297 Chandan Uddaraju 2019-01-07 168 int const max_audio_channel_count = 0x8;
c24ff5297 Chandan Uddaraju 2019-01-07 169 int sampling_rate = 0x0;
c24ff5297 Chandan Uddaraju 2019-01-07 170 int channel_count = 0x0;
c24ff5297 Chandan Uddaraju 2019-01-07 171
c24ff5297 Chandan Uddaraju 2019-01-07 @172 rlen = drm_dp_dpcd_readb(link->aux->drm_aux, DP_TEST_AUDIO_MODE, &data);
c24ff5297 Chandan Uddaraju 2019-01-07 173 if (rlen < 0) {
c24ff5297 Chandan Uddaraju 2019-01-07 174 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
c24ff5297 Chandan Uddaraju 2019-01-07 175 return rlen;
c24ff5297 Chandan Uddaraju 2019-01-07 176 }
c24ff5297 Chandan Uddaraju 2019-01-07 177
c24ff5297 Chandan Uddaraju 2019-01-07 178 /* Sampling Rate - Bits 3:0 */
c24ff5297 Chandan Uddaraju 2019-01-07 179 sampling_rate = data & 0xF;
c24ff5297 Chandan Uddaraju 2019-01-07 180 if (sampling_rate > max_audio_sampling_rate) {
c24ff5297 Chandan Uddaraju 2019-01-07 181 DRM_ERROR("sampling rate (0x%x) greater than max (0x%x)\n",
c24ff5297 Chandan Uddaraju 2019-01-07 182 sampling_rate, max_audio_sampling_rate);
c24ff5297 Chandan Uddaraju 2019-01-07 183 ret = -EINVAL;
c24ff5297 Chandan Uddaraju 2019-01-07 184 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 185 }
c24ff5297 Chandan Uddaraju 2019-01-07 186
c24ff5297 Chandan Uddaraju 2019-01-07 187 /* Channel Count - Bits 7:4 */
c24ff5297 Chandan Uddaraju 2019-01-07 188 channel_count = ((data & 0xF0) >> 4) + 1;
c24ff5297 Chandan Uddaraju 2019-01-07 189 if (channel_count > max_audio_channel_count) {
c24ff5297 Chandan Uddaraju 2019-01-07 190 DRM_ERROR("channel_count (0x%x) greater than max (0x%x)\n",
c24ff5297 Chandan Uddaraju 2019-01-07 191 channel_count, max_audio_channel_count);
c24ff5297 Chandan Uddaraju 2019-01-07 192 ret = -EINVAL;
c24ff5297 Chandan Uddaraju 2019-01-07 193 goto exit;
c24ff5297 Chandan Uddaraju 2019-01-07 194 }
c24ff5297 Chandan Uddaraju 2019-01-07 195
c24ff5297 Chandan Uddaraju 2019-01-07 196 link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
c24ff5297 Chandan Uddaraju 2019-01-07 197 link->dp_link.test_audio.test_audio_channel_count = channel_count;
c24ff5297 Chandan Uddaraju 2019-01-07 198 DRM_DEBUG_DP("sampling_rate = 0x%x, channel_count = 0x%x\n",
c24ff5297 Chandan Uddaraju 2019-01-07 199 sampling_rate, channel_count);
c24ff5297 Chandan Uddaraju 2019-01-07 200 exit:
c24ff5297 Chandan Uddaraju 2019-01-07 201 return ret;
c24ff5297 Chandan Uddaraju 2019-01-07 202 }
c24ff5297 Chandan Uddaraju 2019-01-07 203 :::::: The code at line 75 was first introduced by commit
:::::: c24ff5297c35cef4b4da979f2889b9291fe59523 drm/msm/dp: add displayPort driver support
:::::: TO: Chandan Uddaraju <[email protected]> :::::: CC: 0day robot <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [DPU PATCH v2 1/3] dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon 845
In reply to a message not in the archiveQuoted 78 lines · Chandan Uddaraju
Add bindings for Snapdragon 845 DisplayPort and
display-port PLL driver.Changes in V2:
Provide details about sel-gpioSigned-off-by Chandan Uddaraju <[email protected]>--- .../devicetree/bindings/display/msm/dp.txt | 249 +++++++++++++++++++++ .../devicetree/bindings/display/msm/dpu.txt | 16 +- 2 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/msm/dp.txtDocumentation/devicetree/bindings/display/msm/dp.txt new file +59
-0@@ -0,0 +1,249 @@ +Qualcomm Technologies, Inc. +DP is the master Display Port device which supports DP host controllers that are compatible with VESA Display Port interface specification. +DP Controller: Required properties: +- compatible: Should be "qcom,dp-display". +- reg: Base address and length of DP hardware's memory mapped regions. +- cell-index: Specifies the controller instance. +- reg-names: A list of strings that name the list of regs. + "dp_ahb" - DP controller memory region. + "dp_aux" - DP AUX memory region. + "dp_link" - DP link layer memory region. + "dp_p0" - DP pixel clock domain memory region. + "dp_phy" - DP PHY memory region. + "dp_ln_tx0" - USB3 DP PHY combo TX-0 lane memory region. + "dp_ln_tx1" - USB3 DP PHY combo TX-1 lane memory region. + "dp_mmss_cc" - Display Clock Control memory region. + "qfprom_physical" - QFPROM Phys memory region. + "dp_pll" - USB3 DP combo PLL memory region. + "usb3_dp_com" - USB3 DP PHY combo memory region. + "hdcp_physical" - DP HDCP memory region. +- interrupt-parent phandle to the interrupt parent device node. +- interrupts: The interrupt signal from the DP block. +- clocks: Clocks required for Display Port operation. See [1] for details on clock bindings. +- clock-names: Names of the clocks corresponding to handles. Following clocks are required: + "core_aux_clk", "core_usb_ref_clk_src","core_usb_ref_clk", "core_usb_cfg_ahb_clk", + "core_usb_pipe_clk", "ctrl_link_clk", "ctrl_link_iface_clk", "ctrl_crypto_clk", + "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent". +- pll-node: phandle to DP PLL node. +- vdda-1p2-supply: phandle to vdda 1.2V regulator node. +- vdda-0p9-supply: phandle to vdda 0.9V regulator node. +- qcom,aux-cfg0-settings: Specifies the DP AUX configuration 0 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg1-settings: Specifies the DP AUX configuration 1 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg2-settings: Specifies the DP AUX configuration 2 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg3-settings: Specifies the DP AUX configuration 3 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg4-settings: Specifies the DP AUX configuration 4 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg5-settings: Specifies the DP AUX configuration 5 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg6-settings: Specifies the DP AUX configuration 6 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg7-settings: Specifies the DP AUX configuration 7 settings. The first + entry in this array corresponds to the register offset
Documentation/devicetree/bindings/display/msm/dp.txt line 69
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg8-settings: Specifies the DP AUX configuration 8 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values. +- qcom,aux-cfg9-settings: Specifies the DP AUX configuration 9 settings. The first + entry in this array corresponds to the register offset + within DP AUX, while the remaining entries indicate the + programmable values.
You seem to have ignored the feedback from Stephen and myself. Also, if someone provides feeback on a version of your patch, you should Cc them on future versions so they have a chance to re-review.
Sean
Quoted 227 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +180
-0+- qcom,max-pclk-frequency-khz: An integer specifying the maximum. pixel clock in KHz supported by Display Port. +- extcon: Phandle for the external connector class interface. +- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the a particular "type" of DP module. The module "types" + can be "core", "ctrl", and "phy". Within the same type, + there can be more than one instance of this binding, + in which case the entry would be appended with the + supply entry index. + e.g. qcom,ctrl-supply-entry@0 + -- qcom,supply-name: name of the supply (vdd/vdda/vddio) + -- qcom,supply-min-voltage: minimum voltage level (uV) + -- qcom,supply-max-voltage: maximum voltage level (uV) + -- qcom,supply-enable-load: load drawn (uA) from enabled supply + -- qcom,supply-disable-load: load drawn (uA) from disabled supply + -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on + -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on + -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off + -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off +- pinctrl-names: List of names to assign mdss pin states defined in pinctrl device node + Refer to pinctrl-bindings.txt +- pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin + controller. These pin configurations are installed in the pinctrl + device node. Refer to pinctrl-bindings.txt +DP Endpoint properties: + - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's + input endpoint. For port@1, set to the DPU interface output. See [2] for + device graph info. + +Optional properties: +- qcom,aux-en-gpio: Specifies the aux-channel enable gpio. +- qcom,aux-sel-gpio: Specifies the mux-selection that might be needed for aux interface. + + +DP PLL: Required properties: +- compatible: Should be "qcom,dp-pll-10nm". +- reg: Base address and length of DP hardware's memory mapped regions. +- cell-index: Specifies the PLL instance. +- reg-names: A list of strings that name the list of regs. + "pll_base" - DP PLL memory region. + "phy_base" - DP PHY memory region. + "ln_tx0_base" - USB3 DP PHY combo TX-0 lane memory region. + "ln_tx1_base" - USB3 DP PHY combo TX-1 lane memory region. + "gdsc_base" - gdsc memory region. +- interrupt-parent phandle to the interrupt parent device node. +- interrupts: The interrupt signal from the DP block. +- clocks: Clocks required for Display Port operation. See [1] for details on clock bindings. +- clock-names: Names of the clocks corresponding to handles. Following clocks are required: + "iface_clk", "ref_clk", cfg_ahb_clk", "pipe_clk". +- clock-rate: Initial clock rate to be configured. For the shared clocks, the default value is set to zero so that minimum clock value is configured. Non-zero clock + value can be used to configure DP pixel clock. + + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/graph.txt + +Example: + msm_dp: dp_display@ae90000{ + cell-index = <0>; + compatible = "qcom,dp-display"; + + reg = <0 0x90000 0x0dc>, + <0 0x90200 0x0c0>, + <0 0x90400 0x508>, + <0 0x90a00 0x094>, + <1 0xeaa00 0x200>, + <1 0xea200 0x200>, + <1 0xea600 0x200>, + <2 0x02000 0x1a0>, + <3 0x00000 0x621c>, + <1 0xea000 0x180>, + <1 0xe8000 0x20>, + <4 0xe1000 0x034>; + reg-names = "dp_ahb", "dp_aux", "dp_link", + "dp_p0", "dp_phy", "dp_ln_tx0", "dp_ln_tx1", + "dp_mmss_cc", "qfprom_physical", "dp_pll", + "usb3_dp_com", "hdcp_physical"; + + interrupt-parent = <&mdss>; + interrupts = <12 0>; + + extcon = <&usb_1_ssphy>; + clocks = <&dispcc DISP_CC_MDSS_DP_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>, + <&dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; + clock-names = "core_aux_clk", "core_ref_clk_src", + "core_usb_ref_clk", "core_usb_cfg_ahb_clk", + "core_usb_pipe_clk", "ctrl_link_clk", + "ctrl_link_iface_clk", "ctrl_pixel_clk", + "crypto_clk", "pixel_clk_rcg"; + + pll-node = <&dp_pll>; + qcom,aux-cfg0-settings = [20 00]; + qcom,aux-cfg1-settings = [24 13 23 1d]; + qcom,aux-cfg2-settings = [28 24]; + qcom,aux-cfg3-settings = [2c 00]; + qcom,aux-cfg4-settings = [30 0a]; + qcom,aux-cfg5-settings = [34 26]; + qcom,aux-cfg6-settings = [38 0a]; + qcom,aux-cfg7-settings = [3c 03]; + qcom,aux-cfg8-settings = [40 bb]; + qcom,aux-cfg9-settings = [44 03]; + + qcom,max-pclk-frequency-khz = <675000>; + + qcom,ctrl-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,ctrl-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda-1p2"; + qcom,supply-min-voltage = <1200000>; + qcom,supply-max-voltage = <1200000>; + qcom,supply-enable-load = <21800>; + qcom,supply-disable-load = <4>; + }; + }; + + qcom,phy-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,phy-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdda-0p9"; + qcom,supply-min-voltage = <880000>; + qcom,supply-max-voltage = <880000>; + qcom,supply-enable-load = <36000>; + qcom,supply-disable-load = <32>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + dp_out: endpoint { + }; + }; + }; + }; + + dp_pll: dp-pll@c011000 { + compatible = "qcom,dp-pll-10nm"; + label = "DP PLL"; + cell-index = <0>; + #clock-cells = <1>; + + reg = <1 0xea000 0x200>, + <1 0xeaa00 0x200>, + <1 0xea200 0x200>, + <1 0xea600 0x200>, + <2 0x03000 0x8>; + reg-names = "pll_base", "phy_base", "ln_tx0_base", + "ln_tx1_base", "gdsc_base"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "iface_clk", "ref_clk", + "cfg_ahb_clk", "pipe_clk"; + clock-rate = <0>; + + };Documentation/devicetree/bindings/display/msm/dpu.txt +12
-4@@ -58,8 +58,9 @@ Required properties: Documentation/devicetree/bindings/graph.txt Documentation/devicetree/bindings/media/video-interfaces.txt - Port 0 -> DPU_INTF1 (DSI1) - Port 1 -> DPU_INTF2 (DSI2) + Port 0 -> DPU_INTF0 (DP) + Port 1 -> DPU_INTF1 (DSI1) + Port 2 -> DPU_INTF2 (DSI2) Optional properties: - assigned-clocks: list of clock specifiers for clocks needing rate assignment@@ -115,13 +116,20 @@ Example: port@0 { reg = <0>; - dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + dpu_intf0_out: endpoint { + remote-endpoint = <&dp_in>; }; }; port@1 { reg = <1>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@2 { + reg = <2>; dpu_intf2_out: endpoint { remote-endpoint = <&dsi1_in>; };Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [DPU PATCH v2 2/3] drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveQuoted 7 lines · Chandan Uddaraju
Add the needed displayPort files to enable DP driver on msm target.
"
dp_display" module is the main module that calls into other sub-modules. "dp_drm" file represents the interface between DRM framework and DP driver.
Quoted 11 lines
changes in v2:
-- Update copyright markings on all relevant files.
-- Changepr_err()toDRM_ERROR()
-- Use APIs directly instead of function pointers.
-- Usedrm_display_modestructure to store link parameters in the driver. -- Use macros for register definitions instead of hardcoded values. -- Replace writel_relaxed/readl_relaxed with writel/readl
and remove memory barriers.
-- Remove unnecessary NULL checks.
-- Use drm helper functions for dpcd read/write.
-- UseDRM_DEBUG_DPfor debug msgs.
So I started reviewing this (well, re-reviewing this since my first pass was eaten by an unfortunate power outage) and noticed a _bunch_ of my comments from the v1 review were ignored. I started adding them back to v2, but that's honestly just a waste of my time. It took me a _long_ time to review the v1, so you could at least go through and ensure all of the comments are addressed (either by responding to my questions, pushing back on my suggestions, or changing the code). Silently ignoring review feedback, especially on a review this in-depth is super annoying.
I've added some additional comments on the v2, so please also ensure those are addressed before you send a v3.
Sean
Quoted 109 lines
Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 12 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 26 + drivers/gpu/drm/msm/dp/dp_aux.c | 548 +++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 37 + drivers/gpu/drm/msm/dp/dp_catalog.c | 996 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 108 ++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1611 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 36 + drivers/gpu/drm/msm/dp/dp_display.c | 941 ++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 28 + drivers/gpu/drm/msm/dp/dp_drm.c | 189 ++++ drivers/gpu/drm/msm/dp/dp_drm.h | 20 + drivers/gpu/drm/msm/dp/dp_extcon.c | 228 ++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 85 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1216 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 132 +++ drivers/gpu/drm/msm/dp/dp_panel.c | 504 +++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 91 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 621 +++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 196 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 733 ++++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 51 + drivers/gpu/drm/msm/dp/dp_reg.h | 475 ++++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 41 + 28 files changed, 8958 insertions(+) create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h create mode 100644 drivers/gpu/drm/msm/dp/dp_display.c create mode 100644 drivers/gpu/drm/msm/dp/dp_display.h create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.c create mode 100644 drivers/gpu/drm/msm/dp/dp_extcon.h create mode 100644 drivers/gpu/drm/msm/dp/dp_link.c create mode 100644 drivers/gpu/drm/msm/dp/dp_link.h create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h create mode 100644 drivers/gpu/drm/msm/dp/dp_power.c create mode 100644 drivers/gpu/drm/msm/dp/dp_power.h create mode 100644 drivers/gpu/drm/msm/dp/dp_reg.hdrivers/gpu/drm/msm/Kconfig +9
-0@@ -49,6 +49,15 @@ config DRM_MSM_HDMI_HDCP help Choose this option to enable HDCP state machine +config DRM_MSM_DP + bool "Enable DP support in MSM DRM driver" + depends on DRM_MSM + default n + help + Compile in support for DP driver in msm drm driver. DP external + display support is enabled through this config option. It can + be primary or secondary display on device. + config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSMdrivers/gpu/drm/msm/Makefile +12
-0@@ -2,6 +2,7 @@ ccflags-y := -Idrivers/gpu/drm/msm ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi +ccflags-$(CONFIG_DRM_MSM_DP) += -Idrivers/gpu/drm/msm/dp msm-y := \ adreno/adreno_device.o \@@ -96,6 +97,17 @@ msm-y := \ msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ + dp/dp_catalog.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o \ + dp/dp_extcon.o \ + dp/dp_link.o \ + dp/dp_panel.o \ + dp/dp_parser.o \ + dp/dp_power.o + msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.odrivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +0
-0
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, · line 994
Quoted 4 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +1
-0@@ -991,6 +991,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,trace_dpu_enc_mode_set (DRMID (drm_enc)); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp)
Can you pull this out into a dpu_encoder_is_dp() helper instead of sprinkling this around?
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 3,520 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +19
-0+msm_dp_display_mode_set (priv->dp, drm_enc, mode, adj_mode); +list_for_each_entry (conn_iter, connector_list, head)if (conn_iter->encoder == drm_enc) conn = conn_iter;@@ -1114,6 +1117,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) {struct dpu_encoder_virt *dpu_enc =NULL ;int ret =0 ; +struct msm_drm_private *priv;struct drm_display_mode *cur_mode =NULL ;if (!drm_enc) {@@ -1124,6 +1128,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)mutex_lock (&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + priv = drm_enc->dev->dev_private;trace_dpu_enc_enable (DRMID (drm_enc), cur_mode->hdisplay, cur_mode->vdisplay);@@ -1144,6 +1149,15 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)_dpu_encoder_virt_enable_helper (drm_enc); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { + ret =msm_dp_display_enable (priv->dp, + drm_enc); +if (ret) { +DPU_ERROR_ENC (dpu_enc,"dp display enable failed: %d\n" , + ret); + goto out; + } + } dpu_enc->enabled = true; out:@@ -1180,6 +1194,12 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; dpu_kms =to_dpu_kms (priv->kms); +if (drm_enc->encoder_type ==DRM_MODE_ENCODER_TMDS && priv->dp) { +if (msm_dp_display_disable (priv->dp, drm_enc)) { +DPU_ERROR_ENC (dpu_enc,"dp display disable failed\n" ); +return ; + } + }trace_dpu_enc_disable (DRMID (drm_enc));/* wait for idle */ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +2
-0@@ -14,7 +14,9 @@#include <linux/clk.h> #include <linux/clk/clk-conf.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/delay.h> +#include <drm/drmP.h> #include <drm/drm_print.h> drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +26
-0@@ -15,6 +15,7 @@#include <linux/gpio.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/types.h> #define DEV_DBG(fmt, args...) pr_debug(fmt, ##args)@@ -22,6 +23,29 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args) +struct dss_io_data { +u32 len; +void __iomem *base; +}; + +enum dss_vreg_type { +DSS_REG_LDO , +DSS_REG_VS , +}; + +struct dss_vreg { +struct regulator *vreg;/* vreg handle */ +char vreg_name[32 ]; +int min_voltage; +int max_voltage; +int enable_load; +int disable_load; +int pre_on_sleep; +int post_on_sleep; +int pre_off_sleep; +int post_off_sleep; +}; +struct dss_gpio {unsigned int gpio;unsigned int value;@@ -42,6 +66,8 @@ struct dss_clk { };struct dss_module_power { +unsigned int num_vreg; +struct dss_vreg *vreg_config;unsigned int num_gpio;struct dss_gpio *gpio_config;unsigned int num_clk;drivers/gpu/drm/msm/dp/dp_aux.c new file +548
-0@@ -0,0 +1,548 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h> + +#include "dp_aux.h" + +#define DP_AUX_ENUM_STR (x) #x + +enum { +DP_AUX_DATA_INDEX_WRITE =BIT (31 ), +}; + +struct dp_aux_private { +struct device *dev; +struct dp_aux dp_aux; +struct dp_catalog_aux *catalog; + +struct mutex mutex; +struct completion comp; + +u32 aux_error_num; +u32 retry_cnt; +bool cmd_busy; +bool native; +bool read; +bool no_send_addr; +bool no_send_stop; +u32 offset; +u32 segment; + +struct drm_dp_aux drm_aux; +}; + +static char *dp_aux_get_error (u32 aux_error) +{ +switch (aux_error) { +case DP_AUX_ERR_NONE : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NONE ); +case DP_AUX_ERR_ADDR : +return DP_AUX_ENUM_STR (DP_AUX_ERR_ADDR ); +case DP_AUX_ERR_TOUT : +return DP_AUX_ENUM_STR (DP_AUX_ERR_TOUT ); +case DP_AUX_ERR_NACK : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NACK ); +case DP_AUX_ERR_DEFER : +return DP_AUX_ENUM_STR (DP_AUX_ERR_DEFER ); +case DP_AUX_ERR_NACK_DEFER : +return DP_AUX_ENUM_STR (DP_AUX_ERR_NACK_DEFER ); +default : +return "unknown" ; + } +} + +static u32 dp_aux_write (struct dp_aux_private *aux, +struct drm_dp_aux_msg *msg) +{ +u32 data[4 ], reg, len; +u8 *msgdata = msg->buffer; +int const aux_cmd_fifo_len =128 ; +int i =0 ; + +if (aux->read) + len =4 ; +else + len = msg->size +4 ; + +/* +* cmd fifo only has depth of 144 bytes +* limit buf length to 128 bytes here +*/ +if (len > aux_cmd_fifo_len) { +DRM_ERROR ("buf len error\n" ); +return 0 ; + } + +/* Pack cmd and write to HW */ + data[0 ] = (msg->address >>16 ) &0xf ;/* addr[19:16] */ +if (aux->read) + data[0 ] |=BIT (4 );/* R/W */ + + data[1 ] = (msg->address >>8 ) &0xff ;/* addr[15:8] */ + data[2 ] = msg->address &0xff ;/* addr[7:0] */ + data[3 ] = (msg->size -1 ) &0xff ;/* len[7:0] */ + +for (i =0 ; i < len; i++) { + reg = (i <4 ) ? data[i] : msgdata[i -4 ]; + reg = ((reg) <<8 ) &0x0000ff00 ;/* index = 0, write */ +if (i ==0 ) + reg |=DP_AUX_DATA_INDEX_WRITE ; + aux->catalog->data = reg; +dp_catalog_aux_write_data (aux->catalog); + } + +dp_catalog_aux_clear_trans (aux->catalog, false); + + reg =0 ;/* Transaction number == 1 */ +if (!aux->native) {/* i2c */ + reg |=BIT (8 ); + +if (aux->no_send_addr) + reg |=BIT (10 ); + +if (aux->no_send_stop) + reg |=BIT (11 ); + } + + reg |=BIT (9 ); + aux->catalog->data = reg; +dp_catalog_aux_write_trans (aux->catalog); + +return len; +} + +static int dp_aux_cmd_fifo_tx (struct dp_aux_private *aux, +struct drm_dp_aux_msg *msg) +{ +u32 ret =0 , len =0 , timeout; +int const aux_timeout_ms =HZ /4 ; + +reinit_completion (&aux->comp); + + len =dp_aux_write (aux, msg); +if (len ==0 ) { +DRM_ERROR ("DP AUX write failed\n" ); +return -EINVAL ; + } + + timeout =wait_for_completion_timeout (&aux->comp, aux_timeout_ms); +if (!timeout) { +DRM_ERROR ("aux %s timeout\n" , (aux->read ?"read" :"write" )); +return -ETIMEDOUT ; + } + +if (aux->aux_error_num ==DP_AUX_ERR_NONE ) { + ret = len; + }else { +DRM_ERROR_RATELIMITED ("aux err: %s\n" , +dp_aux_get_error (aux->aux_error_num)); + + ret = -EINVAL ; + } + +return ret; +} + +static void dp_aux_cmd_fifo_rx (struct dp_aux_private *aux, +struct drm_dp_aux_msg *msg) +{ +u32 data; +u8 *dp; +u32 i, actual_i; +u32 len = msg->size; + +dp_catalog_aux_clear_trans (aux->catalog, true); + + data =0 ; + data |=DP_AUX_DATA_INDEX_WRITE ;/* INDEX_WRITE */ + data |=BIT (0 );/* read */ + + aux->catalog->data = data; +dp_catalog_aux_write_data (aux->catalog); + + dp = msg->buffer; + +/* discard first byte */ + data =dp_catalog_aux_read_data (aux->catalog); + +for (i =0 ; i < len; i++) { + data =dp_catalog_aux_read_data (aux->catalog); + *dp++ = (u8)((data >>8 ) &0xff ); + + actual_i = (data >>16 ) &0xFF ; +if (i != actual_i) +pr_warn ("Index mismatch: expected %d, found %d\n" , + i, actual_i); + } +} + +static void dp_aux_native_handler (struct dp_aux_private *aux) +{ +u32 isr = aux->catalog->isr; + +if (isr &DP_INTR_AUX_I2C_DONE ) + aux->aux_error_num =DP_AUX_ERR_NONE ; +else if (isr &DP_INTR_WRONG_ADDR ) + aux->aux_error_num =DP_AUX_ERR_ADDR ; +else if (isr &DP_INTR_TIMEOUT ) + aux->aux_error_num =DP_AUX_ERR_TOUT ; +if (isr &DP_INTR_NACK_DEFER ) + aux->aux_error_num =DP_AUX_ERR_NACK ; + +complete (&aux->comp); +} + +static void dp_aux_i2c_handler (struct dp_aux_private *aux) +{ +u32 isr = aux->catalog->isr; + +if (isr &DP_INTR_AUX_I2C_DONE ) { +if (isr & (DP_INTR_I2C_NACK |DP_INTR_I2C_DEFER )) + aux->aux_error_num =DP_AUX_ERR_NACK ; +else + aux->aux_error_num =DP_AUX_ERR_NONE ; + }else { +if (isr &DP_INTR_WRONG_ADDR ) + aux->aux_error_num =DP_AUX_ERR_ADDR ; +else if (isr &DP_INTR_TIMEOUT ) + aux->aux_error_num =DP_AUX_ERR_TOUT ; +if (isr &DP_INTR_NACK_DEFER ) + aux->aux_error_num =DP_AUX_ERR_NACK_DEFER ; +if (isr &DP_INTR_I2C_NACK ) + aux->aux_error_num =DP_AUX_ERR_NACK ; +if (isr &DP_INTR_I2C_DEFER ) + aux->aux_error_num =DP_AUX_ERR_DEFER ; + } + +complete (&aux->comp); +} + +static void dp_aux_update_offset_and_segment (struct dp_aux_private *aux, +struct drm_dp_aux_msg *input_msg) +{ +u32 const edid_address =0x50 ; +u32 const segment_address =0x30 ; +bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); +u8 *data =NULL ; + +if (aux->native || i2c_read || ((input_msg->address != edid_address) && + (input_msg->address != segment_address))) +return ; + + + data = input_msg->buffer; +if (input_msg->address == segment_address) + aux->segment = *data; +else + aux->offset = *data; +} + +/** +* dp_aux_transfer_helper() - helper function for EDID read transactions +* +* @aux: DP AUX private structure +* @input_msg: input message from DRM upstream APIs +* +* return: void +* +* This helper function is used to fix EDID reads for non-compliant +* sinks that do not handle the i2c middle-of-transaction flag correctly. +*/ +static void dp_aux_transfer_helper (struct dp_aux_private *aux, +struct drm_dp_aux_msg *input_msg) +{ +struct drm_dp_aux_msg helper_msg; +u32 const message_size =0x10 ; +u32 const segment_address =0x30 ; +bool i2c_mot = input_msg->request &DP_AUX_I2C_MOT ; +bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); + +if (!i2c_mot || !i2c_read || (input_msg->size ==0 )) +return ; + + aux->read = false; + aux->cmd_busy = true; + aux->no_send_addr = true; + aux->no_send_stop = true; + +/* +* Send the segment address for every i2c read in which the +* middle-of-tranaction flag is set. This is required to support EDID +* reads of more than 2 blocks as the segment address is reset to 0 +* since we are overriding the middle-of-transaction flag for read +* transactions. +*/ +memset (&helper_msg,0 ,sizeof (helper_msg)); + helper_msg.address = segment_address; + helper_msg.buffer = &aux->segment; + helper_msg.size =1 ; +dp_aux_cmd_fifo_tx (aux, &helper_msg); + +/* +* Send the offset address for every i2c read in which the +* middle-of-transaction flag is set. This will ensure that the sink +* will update its read pointer and return the correct portion of the +* EDID buffer in the subsequent i2c read trasntion triggered in the +* native AUX transfer function. +*/ +memset (&helper_msg,0 ,sizeof (helper_msg)); + helper_msg.address = input_msg->address; + helper_msg.buffer = &aux->offset; + helper_msg.size =1 ; +dp_aux_cmd_fifo_tx (aux, &helper_msg); + aux->offset += message_size; + +if (aux->offset ==0x80 || aux->offset ==0x100 ) + aux->segment =0x0 ;/* reset segment at end of block */ +} + +/* +* This function does the real job to process an AUX transaction. +* It will call aux_reset() function to reset the AUX channel, +* if the waiting is timeout. +*/ +static ssize_t dp_aux_transfer (struct drm_dp_aux *drm_aux, +struct drm_dp_aux_msg *msg) +{ +ssize_t ret; +int const aux_cmd_native_max =16 ; +int const aux_cmd_i2c_max =128 ; +int const retry_count =5 ; +struct dp_aux_private *aux =container_of (drm_aux, + struct dp_aux_private, drm_aux); + +mutex_lock (&aux->mutex); + + aux->native = msg->request & (DP_AUX_NATIVE_WRITE &DP_AUX_NATIVE_READ ); + +/* Ignore address only message */ +if ((msg->size ==0 ) || (msg->buffer ==NULL )) { + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_ACK :DP_AUX_I2C_REPLY_ACK ; + ret = msg->size; + goto unlock_exit; + } + +/* msg sanity check */ +if ((aux->native && (msg->size > aux_cmd_native_max)) || + (msg->size > aux_cmd_i2c_max)) { +DRM_ERROR ("%s: invalid msg: size(%zu), request(%x)\n" , + __func__, msg->size, msg->request); + ret = -EINVAL ; + goto unlock_exit; + } + +dp_aux_update_offset_and_segment (aux, msg); +dp_aux_transfer_helper (aux, msg); + + aux->read = msg->request & (DP_AUX_I2C_READ &DP_AUX_NATIVE_READ ); + aux->cmd_busy = true; + +if (aux->read) { + aux->no_send_addr = true; + aux->no_send_stop = false; + }else { + aux->no_send_addr = true; + aux->no_send_stop = true; + } + + ret =dp_aux_cmd_fifo_tx (aux, msg); +if ((ret <0 ) && aux->native) { + aux->retry_cnt++; +if (!(aux->retry_cnt % retry_count)) +dp_catalog_aux_update_cfg (aux->catalog, + aux->dp_aux.cfg,PHY_AUX_CFG1 ); +dp_catalog_aux_reset (aux->catalog); + goto unlock_exit; + }else if (ret <0 ) { + goto unlock_exit; + } + +if (aux->aux_error_num ==DP_AUX_ERR_NONE ) { +if (aux->read) +dp_aux_cmd_fifo_rx (aux, msg); + + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_ACK :DP_AUX_I2C_REPLY_ACK ; + }else { +/* Reply defer to retry */ + msg->reply = aux->native ? +DP_AUX_NATIVE_REPLY_DEFER :DP_AUX_I2C_REPLY_DEFER ; + } + +/* Return requested size for success or retry */ + ret = msg->size; + aux->retry_cnt =0 ; + +unlock_exit: + aux->cmd_busy = false; +mutex_unlock (&aux->mutex); +return ret; +} + +static void dp_aux_reset_phy_config_indices (struct dp_aux_cfg *aux_cfg) +{ +int i =0 ; + +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) + aux_cfg[i].current_index =0 ; +} + +void dp_aux_isr (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_catalog_aux_get_irq (aux->catalog, aux->cmd_busy); + +if (!aux->cmd_busy) +return ; + +if (aux->native) +dp_aux_native_handler (aux); +else +dp_aux_i2c_handler (aux); +} + +void dp_aux_reconfig (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_catalog_aux_update_cfg (aux->catalog, + dp_aux->cfg,PHY_AUX_CFG1 ); +dp_catalog_aux_reset (aux->catalog); +} + +void dp_aux_init (struct dp_aux *dp_aux,struct dp_aux_cfg *aux_cfg) +{ +struct dp_aux_private *aux; + +if (!dp_aux || !aux_cfg) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_aux_reset_phy_config_indices (aux_cfg); +dp_catalog_aux_setup (aux->catalog, aux_cfg); +dp_catalog_aux_reset (aux->catalog); +dp_catalog_aux_enable (aux->catalog, true); + aux->retry_cnt =0 ; +} + +void dp_aux_deinit (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_catalog_aux_enable (aux->catalog, false); +} + +int dp_aux_register (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; +int ret =0 ; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); + ret = -EINVAL ; + goto exit; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->drm_aux.name ="dpu_dp_aux" ; + aux->drm_aux.dev = aux->dev; + aux->drm_aux.transfer = dp_aux_transfer; + ret =drm_dp_aux_register (&aux->drm_aux); +if (ret) { +DRM_ERROR ("%s: failed to register drm aux: %d\n" , __func__, ret); + goto exit; + } + dp_aux->drm_aux = &aux->drm_aux; +exit: +return ret; +} + +void dp_aux_unregister (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); +drm_dp_aux_unregister (&aux->drm_aux); +} + +struct dp_aux *dp_aux_get (struct device *dev,struct dp_catalog_aux *catalog, +struct dp_aux_cfg *aux_cfg) +{ +int rc =0 ; +struct dp_aux_private *aux; +struct dp_aux *dp_aux; + +if (!catalog || !aux_cfg) { +DRM_ERROR ("invalid input\n" ); + rc = -ENODEV ; + goto error; + } + + aux =devm_kzalloc (dev,sizeof (*aux),GFP_KERNEL ); +if (!aux) { + rc = -ENOMEM ; + goto error; + } + +init_completion (&aux->comp); + aux->cmd_busy = false; +mutex_init (&aux->mutex); + + aux->dev = dev; + aux->catalog = catalog; + aux->dp_aux.cfg = aux_cfg; + dp_aux = &aux->dp_aux; + aux->retry_cnt =0 ; + +return dp_aux; +error: +return ERR_PTR (rc); +} + +void dp_aux_put (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) +return ; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +mutex_destroy (&aux->mutex); + +devm_kfree (aux->dev, aux); +}drivers/gpu/drm/msm/dp/dp_aux.h new file +37
-0@@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#ifndef _DP_AUX_H_ +#define _DP_AUX_H_ + +#include "dp_catalog.h" +#include <drm/drm_dp_helper.h> + +enum dp_aux_error { +DP_AUX_ERR_NONE =0 , +DP_AUX_ERR_ADDR =-1 , +DP_AUX_ERR_TOUT =-2 , +DP_AUX_ERR_NACK =-3 , +DP_AUX_ERR_DEFER =-4 , +DP_AUX_ERR_NACK_DEFER =-5 , +}; + +struct dp_aux { +struct drm_dp_aux *drm_aux; +struct dp_aux_cfg *cfg; +}; + +int dp_aux_register (struct dp_aux *aux); +void dp_aux_unregister (struct dp_aux *aux); +void dp_aux_isr (struct dp_aux *aux); +void dp_aux_init (struct dp_aux *aux,struct dp_aux_cfg *aux_cfg); +void dp_aux_deinit (struct dp_aux *aux); +void dp_aux_reconfig (struct dp_aux *aux); + +struct dp_aux *dp_aux_get (struct device *dev,struct dp_catalog_aux *catalog, +struct dp_aux_cfg *aux_cfg); +void dp_aux_put (struct dp_aux *aux); + +#endif /*__DP_AUX_H_*/ drivers/gpu/drm/msm/dp/dp_catalog.c new file +996
-0@@ -0,0 +1,996 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <drm/drm_dp_helper.h> + +#include "dp_catalog.h" +#include "dp_reg.h" + +#define POLLING_SLEEP_US 1000 +#define POLLING_TIMEOUT_US 10000 + +#define REFTIMER_DEFAULT_VALUE 0x20000 +#define SCRAMBLER_RESET_COUNT_VALUE 0xFC + +#define dp_catalog_get_priv (x) { \ + struct dp_catalog *dp_catalog; \ + dp_catalog = container_of(x, struct dp_catalog, x); \ + catalog = container_of(dp_catalog, struct dp_catalog_private, \ + dp_catalog); \ +} + +#define DP_INTERRUPT_STATUS1 \ + (DP_INTR_AUX_I2C_DONE| \ + DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ + DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ + DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ + DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) + +#define DP_INTERRUPT_STATUS1_MASK (DP_INTERRUPT_STATUS1 << 2) + +#define DP_INTERRUPT_STATUS2 \ + (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ + DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) + +#define DP_INTERRUPT_STATUS2_MASK (DP_INTERRUPT_STATUS2 << 2) + +static u8 const vm_pre_emphasis[4 ][4 ] = { + {0x00 ,0x0B ,0x12 ,0xFF },/* pe0, 0 db */ + {0x00 ,0x0A ,0x12 ,0xFF },/* pe1, 3.5 db */ + {0x00 ,0x0C ,0xFF ,0xFF },/* pe2, 6.0 db */ + {0xFF ,0xFF ,0xFF ,0xFF }/* pe3, 9.5 db */ +}; + +/* voltage swing, 0.2v and 1.0v are not support */ +static u8 const vm_voltage_swing[4 ][4 ] = { + {0x07 ,0x0F ,0x14 ,0xFF },/* sw0, 0.4v */ + {0x11 ,0x1D ,0x1F ,0xFF },/* sw1, 0.6 v */ + {0x18 ,0x1F ,0xFF ,0xFF },/* sw1, 0.8 v */ + {0xFF ,0xFF ,0xFF ,0xFF }/* sw1, 1.2 v, optional */ +}; + +struct dp_catalog_private { +struct device *dev; +struct dp_io *io; +struct dp_catalog dp_catalog; +}; + +static inline u32 dp_read_aux (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_aux.base + offset); +} + +static inline void dp_write_aux (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure aux reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_aux.base + offset); +} + +static inline u32 dp_read_ahb (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_ahb.base + offset); +} + +static inline void dp_write_ahb (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure phy reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_ahb.base + offset); +} + +static inline u32 dp_read_cc (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_cc_io.base + offset); +} + +static inline void dp_write_phy (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure phy reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->phy_io.base + offset); +} + +static inline void dp_write_pll (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->dp_pll_io.base + offset); +} + +static inline void dp_write_ln_tx0 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->ln_tx0_io.base + offset); +} + +static inline void dp_write_ln_tx1 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +writel_relaxed (data, catalog->io->ln_tx1_io.base + offset); +} + +static inline void dp_write_usb_cm (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure usb reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->usb3_dp_com.base + offset); +} + +static inline void dp_write_p0 (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure interface reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_p0.base + offset); +} + +static inline u32 dp_read_link (struct dp_catalog_private *catalog,u32 offset) +{ +return readl_relaxed (catalog->io->dp_link.base + offset); +} + +static inline void dp_write_link (struct dp_catalog_private *catalog, +u32 offset,u32 data) +{ +/* +* To make sure link reg writes happens before any other operation, +* this function uses writel() instread of writel_relaxed() +*/ +writel (data, catalog->io->dp_link.base + offset); +} + +/* aux related catalog functions */ +u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux) +{ +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return 0 ; + } + +dp_catalog_get_priv (aux); + +return dp_read_aux (catalog,REG_DP_AUX_DATA ); +} + +int dp_catalog_aux_write_data (struct dp_catalog_aux *aux) +{ +int rc =0 ; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (aux); +dp_write_aux (catalog,REG_DP_AUX_DATA , aux->data); +return rc; +} + +int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux) +{ +int rc =0 ; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (aux); +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL , aux->data); +return rc; +} + +int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read) +{ +int rc =0 ; +u32 data =0 ; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (aux); + +if (read) { + data =dp_read_aux (catalog,REG_DP_AUX_TRANS_CTRL ); + data &= ~DP_AUX_TRANS_CTRL_GO ; +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL , data); + }else { +dp_write_aux (catalog,REG_DP_AUX_TRANS_CTRL ,0 ); + } +return rc; +} + +void dp_catalog_aux_reset (struct dp_catalog_aux *aux) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux_ctrl =dp_read_aux (catalog,REG_DP_AUX_CTRL ); + + aux_ctrl |=DP_AUX_CTRL_RESET ; +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +usleep_range (1000 ,1100 );/* h/w recommended delay */ + + aux_ctrl &= ~DP_AUX_CTRL_RESET ; +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +} + +void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux_ctrl =dp_read_aux (catalog,REG_DP_AUX_CTRL ); + +if (enable) { +dp_write_aux (catalog,REG_DP_TIMEOUT_COUNT ,0xffff ); +dp_write_aux (catalog,REG_DP_AUX_LIMITS ,0xffff ); + aux_ctrl |=DP_AUX_CTRL_ENABLE ; + }else { + aux_ctrl &= ~DP_AUX_CTRL_ENABLE ; + } + +dp_write_aux (catalog,REG_DP_AUX_CTRL , aux_ctrl); +} + +void dp_catalog_aux_update_cfg (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg,enum dp_phy_aux_config_type type) +{ +struct dp_catalog_private *catalog; +u32 new_index =0 , current_index =0 ; + +if (!aux || !cfg || (type >=PHY_AUX_CFG_MAX )) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + current_index = cfg[type].current_index; + new_index = (current_index +1 ) % cfg[type].cfg_cnt; +DRM_DEBUG_DP ("Updating %s from 0x%08x to 0x%08x\n" , +dp_phy_aux_config_type_to_string (type), + cfg[type].lut[current_index], cfg[type].lut[new_index]); + +dp_write_phy (catalog, cfg[type].offset, + cfg[type].lut[new_index]); + cfg[type].current_index = new_index; +} + +void dp_catalog_aux_setup (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg) +{ +struct dp_catalog_private *catalog; +int i =0 ; + +if (!aux || !cfg) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + +dp_write_phy (catalog,REG_DP_PHY_PD_CTL ,DP_PHY_PD_CTL_PWRDN | +DP_PHY_PD_CTL_AUX_PWRDN |DP_PHY_PD_CTL_PLL_PWRDN | +DP_PHY_PD_CTL_DP_CLAMP_EN ); + +/* Turn on BIAS current for PHY/PLL */ +dp_write_pll (catalog, +QSERDES_COM_BIAS_EN_CLKBUFLR_EN ,QSERDES_COM_BIAS_EN | +QSERDES_COM_BIAS_EN_MUX |QSERDES_COM_CLKBUF_L_EN | +QSERDES_COM_EN_SYSCLK_TX_SEL ); + +/* DP AUX CFG register programming */ +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) { +DRM_DEBUG_DP ("%s: offset=0x%08x, value=0x%08x\n" , +dp_phy_aux_config_type_to_string (i), + cfg[i].offset, cfg[i].lut[cfg[i].current_index]); +dp_write_phy (catalog, cfg[i].offset, + cfg[i].lut[cfg[i].current_index]); + } + +dp_write_phy (catalog,REG_DP_PHY_AUX_INTERRUPT_MASK ,PHY_AUX_STOP_ERR_MASK | +PHY_AUX_DEC_ERR_MASK |PHY_AUX_SYNC_ERR_MASK | +PHY_AUX_ALIGN_ERR_MASK |PHY_AUX_REQ_ERR_MASK ); +} + +void dp_catalog_aux_get_irq (struct dp_catalog_aux *aux,bool cmd_busy) +{ +u32 ack; +struct dp_catalog_private *catalog; + +if (!aux) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + aux->isr =dp_read_ahb (catalog,REG_DP_INTR_STATUS ); + aux->isr &= ~DP_INTERRUPT_STATUS1_MASK ; + ack = aux->isr &DP_INTERRUPT_STATUS1 ; + ack <<=1 ; + ack |=DP_INTERRUPT_STATUS1_MASK ; +dp_write_ahb (catalog,REG_DP_INTR_STATUS , ack); +} + +/* controller related catalog functions */ +void dp_catalog_ctrl_update_transfer_unit (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_link (catalog,REG_DP_VALID_BOUNDARY , ctrl->valid_boundary); +dp_write_link (catalog,REG_DP_TU , ctrl->dp_tu); +dp_write_link (catalog,REG_DP_VALID_BOUNDARY_2 , ctrl->valid_boundary2); +} + +void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_link (catalog,REG_DP_STATE_CTRL , state); +} + +void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 cfg) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +DRM_DEBUG_DP ("DP_CONFIGURATION_CTRL=0x%x\n" , cfg); + +dp_write_link (catalog,REG_DP_CONFIGURATION_CTRL , cfg); +} + +void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +u32 ln_0 =0 , ln_1 =1 , ln_2 =2 , ln_3 =3 ;/* One-to-One mapping */ +u32 ln_mapping; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + ln_mapping = ln_0 <<LANE0_MAPPING_SHIFT ; + ln_mapping |= ln_1 <<LANE1_MAPPING_SHIFT ; + ln_mapping |= ln_2 <<LANE2_MAPPING_SHIFT ; + ln_mapping |= ln_3 <<LANE3_MAPPING_SHIFT ; + +dp_write_link (catalog,REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING , ln_mapping); +} + +void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +u32 mainlink_ctrl; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +if (enable) { +/* +* To make sure link reg writes happens before any other operation, +* dp_write_link() function uses writel() instread of writel_relaxed() +*/ +dp_write_link (catalog,REG_DP_MAINLINK_CTRL ,DP_MAINLINK_FB_BOUNDARY_SEL ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , +DP_MAINLINK_FB_BOUNDARY_SEL |DP_MAINLINK_CTRL_RESET ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL ,DP_MAINLINK_FB_BOUNDARY_SEL ); +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , +DP_MAINLINK_FB_BOUNDARY_SEL |DP_MAINLINK_CTRL_ENABLE ); + }else { + mainlink_ctrl =dp_read_link (catalog,REG_DP_MAINLINK_CTRL ); + mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE ; +dp_write_link (catalog,REG_DP_MAINLINK_CTRL , mainlink_ctrl); + } +} + +void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl, +u32 colorimetry_cfg,u32 test_bits_depth) +{ +u32 misc_val; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + misc_val =dp_read_link (catalog,REG_DP_MISC1_MISC0 ); + misc_val |= colorimetry_cfg <<DP_MISC0_COLORIMETRY_CFG_SHIFT ; + misc_val |= test_bits_depth <<DP_MISC0_TEST_BITS_DEPTH_SHIFT ; +/* Configure clock to synchronous mode */ + misc_val |=DP_MISC0_SYNCHRONOUS_CLK ; + +DRM_DEBUG_DP ("misc settings = 0x%x\n" , misc_val); +dp_write_link (catalog,REG_DP_MISC1_MISC0 , misc_val); +} + +void dp_catalog_ctrl_config_msa (struct dp_catalog_ctrl *ctrl, +u32 rate,u32 stream_rate_khz, +bool fixed_nvid) +{ +u32 pixel_m, pixel_n; +u32 mvid, nvid; +u64 mvid_calc; +u32 const nvid_fixed =0x8000 ; +u32 const link_rate_hbr2 =540000 ; +u32 const link_rate_hbr3 =810000 ; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); +if (fixed_nvid) { +DRM_DEBUG_DP ("use fixed NVID=0x%x\n" , nvid_fixed); + nvid = nvid_fixed; + +DRM_DEBUG_DP ("link rate=%dkbps, stream_rate_khz=%uKhz" , + rate, stream_rate_khz); + +/* +* For intermediate results, use 64 bit arithmetic to avoid +* loss of precision. +*/ + mvid_calc = (u64 ) stream_rate_khz * nvid; + mvid_calc =div_u64 (mvid_calc, rate); + +/* +* truncate back to 32 bits as this final divided value will +* always be within the range of a 32 bit unsigned int. +*/ + mvid = (u32 ) mvid_calc; + }else { + pixel_m =dp_read_cc (catalog,MMSS_DP_PIXEL_M ); + pixel_n =dp_read_cc (catalog,MMSS_DP_PIXEL_N ); +DRM_DEBUG_DP ("pixel_m=0x%x, pixel_n=0x%x\n" , pixel_m, pixel_n); + + mvid = (pixel_m &0xFFFF ) *5 ; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m &0xFFFF ); + +DRM_DEBUG_DP ("rate = %d\n" , rate); + +if (link_rate_hbr2 == rate) + nvid *=2 ; + +if (link_rate_hbr3 == rate) + nvid *=3 ; + } + +DRM_DEBUG_DP ("mvid=0x%x, nvid=0x%x\n" , mvid, nvid); +dp_write_link (catalog,REG_DP_SOFTWARE_MVID , mvid); +dp_write_link (catalog,REG_DP_SOFTWARE_NVID , nvid); +} + +int dp_catalog_ctrl_set_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +int bit, ret; +u32 data; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (ctrl); + + bit =BIT (pattern -1 ); +DRM_DEBUG_DP ("hw: bit=%d train=%d\n" , bit, pattern); +dp_write_link (catalog,REG_DP_STATE_CTRL , bit); + + bit =BIT (pattern -1 ) <<DP_MAINLINK_READY_LINK_TRAINING_SHIFT ; + +/* Poll for mainlink ready status */ + ret =readx_poll_timeout (readl, catalog->io->dp_link.base +REG_DP_MAINLINK_READY , + data, data & bit, +POLLING_SLEEP_US ,POLLING_TIMEOUT_US ); +if (ret <0 ) { +DRM_ERROR ("set pattern for link_train=%d failed\n" , pattern); +return ret; + } +return 0 ; +} + +void dp_catalog_ctrl_usb_reset (struct dp_catalog_ctrl *ctrl,bool flip) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_RESET_OVRD_CTRL , +USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX | +USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_PHY_MODE_CTRL , +USB3_DP_COM_PHY_MODE_DP ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SW_RESET , +USB3_DP_COM_SW_RESET_SET ); + +if (!flip)/* CC1 */ +dp_write_usb_cm (catalog,REG_USB3_DP_COM_TYPEC_CTRL , +USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX ); +else /* CC2 */ +dp_write_usb_cm (catalog,REG_USB3_DP_COM_TYPEC_CTRL , +USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX | +USB3_DP_COM_TYPEC_CTRL_PORTSEL ); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SWI_CTRL ,0x00 ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_SW_RESET ,0x00 ); + +dp_write_usb_cm (catalog,REG_USB3_DP_COM_POWER_DOWN_CTRL , +USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN ); +dp_write_usb_cm (catalog,REG_USB3_DP_COM_RESET_OVRD_CTRL ,0x00 ); + +} + +void dp_catalog_ctrl_reset (struct dp_catalog_ctrl *ctrl) +{ +u32 sw_reset; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + + sw_reset =dp_read_ahb (catalog,REG_DP_SW_RESET ); + + sw_reset |=DP_SW_RESET ; +dp_write_ahb (catalog,REG_DP_SW_RESET , sw_reset); +usleep_range (1000 ,1100 );/* h/w recommended delay */ + + sw_reset &= ~DP_SW_RESET ; +dp_write_ahb (catalog,REG_DP_SW_RESET , sw_reset); +} + +bool dp_catalog_ctrl_mainlink_ready (struct dp_catalog_ctrl *ctrl) +{ +u32 data; +int ret; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return false; + } + +dp_catalog_get_priv (ctrl); + +/* Poll for mainlink ready status */ + ret =readx_poll_timeout (readl, + catalog->io->dp_link.base +REG_DP_MAINLINK_READY , + data, data &DP_MAINLINK_READY_FOR_VIDEO , +POLLING_SLEEP_US ,POLLING_TIMEOUT_US ); +if (ret <0 ) { +DRM_ERROR ("mainlink not ready\n" ); +return false; + } + +return true; +} + +void dp_catalog_ctrl_enable_irq (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + +if (enable) { +dp_write_ahb (catalog,REG_DP_INTR_STATUS ,DP_INTERRUPT_STATUS1_MASK ); +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 ,DP_INTERRUPT_STATUS2_MASK ); + }else { +dp_write_ahb (catalog,REG_DP_INTR_STATUS ,0x00 ); +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 ,0x00 ); + } +} + +void dp_catalog_ctrl_hpd_config (struct dp_catalog_ctrl *ctrl,bool en) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +if (en) { +u32 reftimer =dp_read_aux (catalog,REG_DP_DP_HPD_REFTIMER ); + +dp_write_aux (catalog,REG_DP_DP_HPD_INT_ACK , +DP_DP_HPD_PLUG_INT_ACK |DP_DP_IRQ_HPD_INT_ACK | +DP_DP_HPD_REPLUG_INT_ACK |DP_DP_HPD_UNPLUG_INT_ACK ); +dp_write_aux (catalog,REG_DP_DP_HPD_INT_MASK , +DP_DP_HPD_PLUG_INT_MASK |DP_DP_IRQ_HPD_INT_MASK | +DP_DP_HPD_REPLUG_INT_MASK |DP_DP_HPD_UNPLUG_INT_MASK ); + +/* Configure REFTIMER */ + reftimer |=REFTIMER_DEFAULT_VALUE ; +dp_write_aux (catalog,REG_DP_DP_HPD_REFTIMER , reftimer); +/* Enable HPD */ +dp_write_aux (catalog,REG_DP_DP_HPD_CTRL ,DP_DP_HPD_CTRL_HPD_EN ); + }else { +/* Disable HPD */ +dp_write_aux (catalog,REG_DP_DP_HPD_CTRL ,0x0 ); + } +} + +void dp_catalog_ctrl_get_interrupt (struct dp_catalog_ctrl *ctrl) +{ +u32 ack =0 ; +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + ctrl->isr =dp_read_ahb (catalog,REG_DP_INTR_STATUS2 ); + ctrl->isr &= ~DP_INTERRUPT_STATUS2_MASK ; + ack = ctrl->isr &DP_INTERRUPT_STATUS2 ; + ack <<=1 ; + ack |=DP_INTERRUPT_STATUS2_MASK ; +dp_write_ahb (catalog,REG_DP_INTR_STATUS2 , ack); +} + +void dp_catalog_ctrl_phy_reset (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +dp_write_ahb (catalog,REG_DP_PHY_CTRL , +DP_PHY_CTRL_SW_RESET_PLL |DP_PHY_CTRL_SW_RESET ); +usleep_range (1000 ,1100 );/* h/w recommended delay */ +dp_write_ahb (catalog,REG_DP_PHY_CTRL ,0x0 ); +} + +void dp_catalog_ctrl_phy_lane_cfg (struct dp_catalog_ctrl *ctrl, +bool flipped,u8 ln_cnt) +{ +u32 info =0x0 ; +struct dp_catalog_private *catalog; +u8 orientation =BIT (!!flipped); + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + info = ln_cnt &DP_PHY_SPARE0_MASK ; + info |= (orientation &DP_PHY_SPARE0_MASK ) <<DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT ; +DRM_DEBUG_DP ("Shared Info = 0x%x\n" , info); + +dp_write_phy (catalog,REG_DP_PHY_SPARE0 , info); +} + +int dp_catalog_ctrl_update_vx_px (struct dp_catalog_ctrl *ctrl, +u8 v_level,u8 p_level) +{ +struct dp_catalog_private *catalog; +u8 value0, value1; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (ctrl); + +DRM_DEBUG_DP ("hw: v=%d p=%d\n" , v_level, p_level); + + value0 = vm_voltage_swing[v_level][p_level]; + value1 = vm_pre_emphasis[v_level][p_level]; + +if (value0 ==0xFF && value1 ==0xFF ) { +DRM_ERROR ("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n" , + v_level, value0, p_level, value1); +return -EINVAL ; + } +/* program default setting first */ +dp_write_ln_tx0 (catalog, TXn_TX_DRV_LVL,0x2A ); +dp_write_ln_tx1 (catalog, TXn_TX_DRV_LVL,0x2A ); +dp_write_ln_tx0 (catalog, TXn_TX_EMP_POST1_LVL,0x20 ); +dp_write_ln_tx1 (catalog, TXn_TX_EMP_POST1_LVL,0x20 ); + +/* Enable MUX to use Cursor values from these registers */ + value0 |=BIT (5 ); + value1 |=BIT (5 ); + +/* Configure host and panel only if both values are allowed */ +dp_write_ln_tx0 (catalog, TXn_TX_DRV_LVL, value0); +dp_write_ln_tx1 (catalog, TXn_TX_DRV_LVL, value0); +dp_write_ln_tx0 (catalog, TXn_TX_EMP_POST1_LVL, value1); +dp_write_ln_tx1 (catalog, TXn_TX_EMP_POST1_LVL, value1); +DRM_DEBUG_DP ("hw: vx_value=0x%x px_value=0x%x\n" , + value0, value1); + +return 0 ; +} + +void dp_catalog_ctrl_send_phy_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +struct dp_catalog_private *catalog; +u32 value =0x0 ; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + +/* Make sure to clear the current pattern before starting a new one */ +dp_write_link (catalog,REG_DP_STATE_CTRL ,0x0 ); + +switch (pattern) { +case DP_LINK_QUAL_PATTERN_D10_2 : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_TRAINING_PATTERN1 ); +break ; +case DP_LINK_QUAL_PATTERN_ERROR_RATE : + value &= ~DP_HBR2_ERM_PATTERN ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=SCRAMBLER_RESET_COUNT_VALUE ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write_link (catalog,REG_DP_MAINLINK_LEVELS ,DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 ); +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE ); +break ; +case DP_LINK_QUAL_PATTERN_PRBS7 : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_PRBS7 ); +break ; +case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM : +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN ); +/* 00111110000011111000001111100000 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0 ,0x3E0F83E0 ); +/* 00001111100000111110000011111000 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1 ,0x0F83E0F8 ); +/* 1111100000111110 */ +dp_write_link (catalog,REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2 ,0x0000F83E ); +break ; +case DP_LINK_QUAL_PATTERN_HBR2_EYE : + value =DP_HBR2_ERM_PATTERN ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=SCRAMBLER_RESET_COUNT_VALUE ; +dp_write_link (catalog,REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write_link (catalog,REG_DP_MAINLINK_LEVELS ,DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 ); +dp_write_link (catalog,REG_DP_STATE_CTRL ,DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE ); +break ; +default : +DRM_DEBUG_DP ("No valid test pattern requested: 0x%x\n" , pattern); +return ; + } +} + +u32 dp_catalog_ctrl_read_phy_pattern (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; + +if (!ctrl) { +DRM_ERROR ("invalid input\n" ); +return 0 ; + } + +dp_catalog_get_priv (ctrl); + +return dp_read_link (catalog,REG_DP_MAINLINK_READY ); +} + +/* panel related catalog functions */ +int dp_catalog_panel_timing_cfg (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) { +DRM_ERROR ("invalid input\n" ); +return -EINVAL ; + } + +dp_catalog_get_priv (panel); + +dp_write_link (catalog,REG_DP_TOTAL_HOR_VER , panel->total); +dp_write_link (catalog,REG_DP_START_HOR_VER_FROM_SYNC , panel->sync_start); +dp_write_link (catalog,REG_DP_HSYNC_VSYNC_WIDTH_POLARITY , panel->width_blanking); +dp_write_link (catalog,REG_DP_ACTIVE_HOR_VER , panel->dp_active); +return 0 ; +} + +void dp_catalog_panel_tpg_enable (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (panel); + +dp_write_p0 (catalog,MMSS_DP_INTF_CONFIG ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_HSYNC_CTL , panel->hsync_ctl); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PERIOD_F0 , panel->vsync_period * + panel->hsync_period); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0 , panel->v_sync_width * + panel->hsync_period); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PERIOD_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_HCTL , panel->display_hctl); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_HCTL ,0 ); +dp_write_p0 (catalog,MMSS_INTF_DISPLAY_V_START_F0 , panel->display_v_start); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_V_END_F0 , panel->display_v_end); +dp_write_p0 (catalog,MMSS_INTF_DISPLAY_V_START_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_DISPLAY_V_END_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_START_F0 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_END_F0 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_START_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_ACTIVE_V_END_F1 ,0 ); +dp_write_p0 (catalog,MMSS_DP_INTF_POLARITY_CTL ,0 ); + +dp_write_p0 (catalog,MMSS_DP_TPG_MAIN_CONTROL ,DP_TPG_CHECKERED_RECT_PATTERN ); +dp_write_p0 (catalog,MMSS_DP_TPG_VIDEO_CONFIG , +DP_TPG_VIDEO_CONFIG_BPP_8BIT | +DP_TPG_VIDEO_CONFIG_RGB ); +dp_write_p0 (catalog,MMSS_DP_BIST_ENABLE ,DP_BIST_ENABLE_DPBIST_EN ); +dp_write_p0 (catalog,MMSS_DP_TIMING_ENGINE_EN ,DP_TIMING_ENGINE_EN_EN ); +DRM_DEBUG_DP ("%s: enabled tpg\n" , __func__); +} + +void dp_catalog_panel_tpg_disable (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; + +if (!panel) { +DRM_ERROR ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (panel); + +dp_write_p0 (catalog,MMSS_DP_TPG_MAIN_CONTROL ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_BIST_ENABLE ,0x0 ); +dp_write_p0 (catalog,MMSS_DP_TIMING_ENGINE_EN ,0x0 ); +return ; +} + +struct dp_catalog *dp_catalog_get (struct device *dev,struct dp_io *io) +{ +int rc =0 ; +struct dp_catalog *dp_catalog; +struct dp_catalog_private *catalog; + +if (!io) { +DRM_ERROR ("invalid input\n" ); + rc = -EINVAL ; + goto error; + } + + catalog =devm_kzalloc (dev,sizeof (*catalog),GFP_KERNEL ); +if (!catalog) { + rc = -ENOMEM ; + goto error; + } + + catalog->dev = dev; + catalog->io = io; + + dp_catalog = &catalog->dp_catalog; + +return dp_catalog; +error: +return ERR_PTR (rc); +} + +void dp_catalog_put (struct dp_catalog *dp_catalog) +{ +struct dp_catalog_private *catalog; + +if (!dp_catalog) +return ; + + catalog = container_of(dp_catalog, struct dp_catalog_private, + dp_catalog); + +devm_kfree (catalog->dev, catalog); +}drivers/gpu/drm/msm/dp/dp_catalog.h new file +108
-0@@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +*/ + +#ifndef _DP_CATALOG_H_ +#define _DP_CATALOG_H_ + +#include "dp_parser.h" + +/* interrupts */ +#define DP_INTR_HPD BIT(0) +#define DP_INTR_AUX_I2C_DONE BIT(3) +#define DP_INTR_WRONG_ADDR BIT(6) +#define DP_INTR_TIMEOUT BIT(9) +#define DP_INTR_NACK_DEFER BIT(12) +#define DP_INTR_WRONG_DATA_CNT BIT(15) +#define DP_INTR_I2C_NACK BIT(18) +#define DP_INTR_I2C_DEFER BIT(21) +#define DP_INTR_PLL_UNLOCKED BIT(24) +#define DP_INTR_AUX_ERROR BIT(27) + +#define DP_INTR_READY_FOR_VIDEO BIT(0) +#define DP_INTR_IDLE_PATTERN_SENT BIT(3) +#define DP_INTR_FRAME_END BIT(6) +#define DP_INTR_CRC_UPDATED BIT(9) + +struct dp_catalog_aux { +u32 data; +u32 isr; +}; + +struct dp_catalog_ctrl { +u32 dp_tu; +u32 valid_boundary; +u32 valid_boundary2; +u32 isr; +}; + +struct dp_catalog_panel { +u32 total; +u32 sync_start; +u32 width_blanking; +u32 dp_active; + +/* TPG */ +u32 hsync_period; +u32 vsync_period; +u32 display_v_start; +u32 display_v_end; +u32 v_sync_width; +u32 hsync_ctl; +u32 display_hctl; +}; + +struct dp_catalog { +struct dp_catalog_aux aux; +struct dp_catalog_ctrl ctrl; +struct dp_catalog_panel panel; +}; + +/* AUX APIs */ +u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux); +int dp_catalog_aux_write_data (struct dp_catalog_aux *aux); +int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux); +int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read); +void dp_catalog_aux_reset (struct dp_catalog_aux *aux); +void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable); +void dp_catalog_aux_update_cfg (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg,enum dp_phy_aux_config_type type); +void dp_catalog_aux_setup (struct dp_catalog_aux *aux, +struct dp_aux_cfg *aux_cfg); +void dp_catalog_aux_get_irq (struct dp_catalog_aux *aux,bool cmd_busy); + +/* DP Controller APIs */ +void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state); +void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 config); +void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl,u32 cc,u32 tb); +void dp_catalog_ctrl_config_msa (struct dp_catalog_ctrl *ctrl,u32 rate, +u32 stream_rate_khz,bool fixed_nvid); +int dp_catalog_ctrl_set_pattern (struct dp_catalog_ctrl *ctrl,u32 pattern); +void dp_catalog_ctrl_reset (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_usb_reset (struct dp_catalog_ctrl *ctrl,bool flip); +bool dp_catalog_ctrl_mainlink_ready (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_enable_irq (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_hpd_config (struct dp_catalog_ctrl *ctrl,bool enable); +void dp_catalog_ctrl_phy_reset (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_phy_lane_cfg (struct dp_catalog_ctrl *ctrl,bool flipped, +u8 lane_cnt); +int dp_catalog_ctrl_update_vx_px (struct dp_catalog_ctrl *ctrl,u8 v_level, +u8 p_level); +void dp_catalog_ctrl_get_interrupt (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_update_transfer_unit (struct dp_catalog_ctrl *ctrl); +void dp_catalog_ctrl_send_phy_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern); +u32 dp_catalog_ctrl_read_phy_pattern (struct dp_catalog_ctrl *ctrl); + +/* DP Panel APIs */ +int dp_catalog_panel_timing_cfg (struct dp_catalog_panel *panel); +void dp_catalog_panel_tpg_enable (struct dp_catalog_panel *panel); +void dp_catalog_panel_tpg_disable (struct dp_catalog_panel *panel); + +struct dp_catalog *dp_catalog_get (struct device *dev,struct dp_io *io); +void dp_catalog_put (struct dp_catalog *catalog); + +#endif /* _DP_CATALOG_H_ */ drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1611
-0@@ -0,0 +1,1611 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/types.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <drm/drm_fixed.h> + +#include "dp_reg.h" +#include "dp_ctrl.h" + +#define DP_KHZ_TO_HZ 1000 +#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000)/* 30 ms */ +#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2) + +#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) +#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) + +#define MR_LINK_TRAINING1 0x8 +#define MR_LINK_SYMBOL_ERM 0x80 +#define MR_LINK_PRBS7 0x100 +#define MR_LINK_CUSTOM80 0x200 + +struct dp_tu_calc_input { +u64 lclk;/* 162, 270, 540 and 810 */ +u64 pclk_khz;/* in KHz */ +u64 hactive;/* active h-width */ +u64 hporch;/* bp + fp + pulse */ +int nlanes;/* no.of.lanes */ +int bpp;/* bits */ +int pixel_enc;/* 444, 420, 422 */ +int dsc_en;/* dsc on/off */ +int async_en;/* async mode */ +}; + +struct dp_vc_tu_mapping_table { +u8 valid_boundary_link; +u16 delay_start_link; +bool boundary_moderation_en; +u8 valid_lower_boundary_link; +u8 upper_boundary_count; +u8 lower_boundary_count; +u8 tu_size_minus1; +}; + +struct dp_ctrl_private { +struct dp_ctrl dp_ctrl; + +struct device *dev; +struct dp_aux *aux; +struct dp_panel *panel; +struct dp_link *link; +struct dp_power *power; +struct dp_parser *parser; +struct dp_catalog_ctrl *catalog; + +struct completion idle_comp; +struct mutex push_idle_mutex; +struct completion video_comp; +}; + +void dp_ctrl_abort (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +atomic_set (&ctrl->dp_ctrl.aborted,1 ); +} + +void dp_ctrl_push_idle (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +mutex_lock (&ctrl->push_idle_mutex); + +reinit_completion (&ctrl->idle_comp); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,DP_STATE_CTRL_PUSH_IDLE ); + +if (!wait_for_completion_timeout (&ctrl->idle_comp, +IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES )) +pr_warn ("PUSH_IDLE pattern timedout\n" ); + +mutex_unlock (&ctrl->push_idle_mutex); +pr_debug ("mainlink off done\n" ); +} + +static void dp_ctrl_config_ctrl (struct dp_ctrl_private *ctrl) +{ +u32 config =0 , tbd; +u8 *dpcd = ctrl->panel->dpcd; + +/* Default-> LSCLK DIV: 1/4 LCLK */ + config |= (2 <<DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT ); + +/* Scrambler reset enable */ +if (dpcd[DP_EDP_CONFIGURATION_CAP ] &DP_ALTERNATE_SCRAMBLER_RESET_CAP ) + config |=DP_CONFIGURATION_CTRL_ASSR ; + + tbd =dp_link_get_test_bits_depth (ctrl->link, + ctrl->panel->dp_mode.bpp); + +if (tbd ==DP_TEST_BIT_DEPTH_UNKNOWN ) { +pr_debug ("BIT_DEPTH not set. Configure default\n" ); + tbd =DP_TEST_BIT_DEPTH_8 ; + } + + config |= tbd <<DP_CONFIGURATION_CTRL_BPC_SHIFT ; + +/* Num of Lanes */ + config |= ((ctrl->link->link_params.num_lanes -1 ) + <<DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT ); + +if (drm_dp_enhanced_frame_cap (dpcd)) + config |=DP_CONFIGURATION_CTRL_ENHANCED_FRAMING ; + + config |=DP_CONFIGURATION_CTRL_P_INTERLACED ;/* progressive video */ + +/* sync clock & static Mvid */ + config |=DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN ; + config |=DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK ; + +dp_catalog_ctrl_config_ctrl (ctrl->catalog, config); +} + +/** +* dp_ctrl_configure_source_params() - configures DP transmitter source params +* @ctrl: Display Port Driver data +* +* Configures the DP transmitter source params including details such as lane +* configuration, output format and sink/panel timing information. +*/ +static void dp_ctrl_configure_source_params (struct dp_ctrl_private *ctrl) +{ +u32 cc, tb; + +dp_catalog_ctrl_lane_mapping (ctrl->catalog); +dp_catalog_ctrl_mainlink_ctrl (ctrl->catalog, true); + +dp_ctrl_config_ctrl (ctrl); + + tb =dp_link_get_test_bits_depth (ctrl->link, + ctrl->panel->dp_mode.bpp); + cc =dp_link_get_colorimetry_config (ctrl->link); +dp_catalog_ctrl_config_misc (ctrl->catalog, cc, tb); +dp_panel_timing_cfg (ctrl->panel); +} + +/* +* The structure and few functions present below are IP/Hardware +* specific implementation. Most of the implementation will not +* have coding comments +*/ +struct tu_algo_data { +s64 lclk_fp; +s64 pclk_fp; +s64 lwidth; +s64 hbp_relative_to_pclk; +int nlanes; +int bpp; +int pixelEnc; +int dsc_en; +int async_en; +int bpc; + +uint delay_start_link_extra_pixclk; +int extra_buffer_margin; +s64 ratio_fp; +s64 original_ratio_fp; + +s64 err_fp; +s64 n_err_fp; +s64 n_n_err_fp; +int tu_size; +int tu_size_desired; +int tu_size_minus1; + +int valid_boundary_link; +s64 resulting_valid_fp; +s64 total_valid_fp; +s64 effective_valid_fp; +s64 effective_valid_recorded_fp; +int n_tus; +int n_tus_per_lane; +int paired_tus; +int remainder_tus; +int remainder_tus_upper; +int remainder_tus_lower; +int extra_bytes; +int filler_size; +int delay_start_link; + +int extra_pclk_cycles; +int extra_pclk_cycles_in_link_clk; +s64 ratio_by_tu_fp; +s64 average_valid2_fp; +int new_valid_boundary_link; +int remainder_symbols_exist; +int n_symbols; +s64 n_remainder_symbols_per_lane_fp; +s64 last_partial_tu_fp; +s64 TU_ratio_err_fp; + +int n_tus_incl_last_incomplete_tu; +int extra_pclk_cycles_tmp; +int extra_pclk_cycles_in_link_clk_tmp; +int extra_required_bytes_new_tmp; +int filler_size_tmp; +int lower_filler_size_tmp; +int delay_start_link_tmp; + +bool boundary_moderation_en; +int boundary_mod_lower_err; +int upper_boundary_count; +int lower_boundary_count; +int i_upper_boundary_count; +int i_lower_boundary_count; +int valid_lower_boundary_link; +int even_distribution_BF; +int even_distribution_legacy; +int even_distribution; +int min_hblank_violated; +s64 delay_start_time_fp; +s64 hbp_time_fp; +s64 hactive_time_fp; +s64 diff_abs_fp; + +s64 ratio; +}; + +static int _tu_param_compare (s64 a,s64 b) +{ +u32 a_int, a_frac; +u32 b_int, b_frac; + +if (a == b) +return 0 ; + + a_int = (a >>32 ) &0x7FFFFFFF ; + a_frac = a &0xFFFFFFFF ; + + b_int = (b >>32 ) &0x7FFFFFFF ; + b_frac = b &0xFFFFFFFF ; + +if (a_int > b_int) +return 1 ; +else if (a_int < b_int) +return 2 ; +else if (a_frac > b_frac) +return 1 ; +else +return 2 ; +} + +static void _tu_valid_boundary_calc (struct tu_algo_data *tu) +{ +s64 temp1_fp, temp2_fp, temp, temp1, temp2; +int compare_result_1, compare_result_2, compare_result_3; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + + tu->new_valid_boundary_link =drm_fixp2int_ceil (temp2_fp); + + temp = (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link-1 )); + tu->average_valid2_fp =drm_fixp_from_fraction (temp, + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + temp1_fp =drm_fixp_from_fraction (tu->bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu->lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, tu->average_valid2_fp); + tu->n_tus =drm_fixp2int (temp2_fp); + + temp1_fp =drm_fixp_from_fraction (tu->n_tus,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, tu->average_valid2_fp); + temp1_fp =drm_fixp_from_fraction (tu->n_symbols,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (tu->nlanes,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu->n_remainder_symbols_per_lane_fp = temp2_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + tu->last_partial_tu_fp = +drm_fixp_div (tu->n_remainder_symbols_per_lane_fp, + temp1_fp); + +if (tu->n_remainder_symbols_per_lane_fp !=0 ) + tu->remainder_symbols_exist =1 ; +else + tu->remainder_symbols_exist =0 ; + + temp1_fp =drm_fixp_from_fraction (tu->n_tus, tu->nlanes); + tu->n_tus_per_lane =drm_fixp2int (temp1_fp); + + tu->paired_tus = (int )((tu->n_tus_per_lane) / + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus * + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count); + +if ((tu->remainder_tus - tu->i_upper_boundary_count) >0 ) { + tu->remainder_tus_upper = tu->i_upper_boundary_count; + tu->remainder_tus_lower = tu->remainder_tus - + tu->i_upper_boundary_count; + }else { + tu->remainder_tus_upper = tu->remainder_tus; + tu->remainder_tus_lower =0 ; + } + + temp = tu->paired_tus * (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link -1 )) + + (tu->remainder_tus_upper * + tu->new_valid_boundary_link) + + (tu->remainder_tus_lower * + (tu->new_valid_boundary_link -1 )); + tu->total_valid_fp =drm_fixp_from_fraction (temp,1 ); + +if (tu->remainder_symbols_exist) { + temp1_fp = tu->total_valid_fp + + tu->n_remainder_symbols_per_lane_fp; + temp2_fp =drm_fixp_from_fraction (tu->n_tus_per_lane,1 ); + temp2_fp = temp2_fp + tu->last_partial_tu_fp; + temp1_fp =drm_fixp_div (temp1_fp, temp2_fp); + }else { + temp2_fp =drm_fixp_from_fraction (tu->n_tus_per_lane,1 ); + temp1_fp =drm_fixp_div (tu->total_valid_fp, temp2_fp); + } + tu->effective_valid_fp = temp1_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp; + + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->ratio_fp, temp1_fp); + tu->n_err_fp = tu->average_valid2_fp - temp2_fp; + + tu->even_distribution = tu->n_tus % tu->nlanes ==0 ?1 :0 ; + + temp1_fp =drm_fixp_from_fraction (tu->bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu->lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, tu->average_valid2_fp); + +if (temp2_fp) + tu->n_tus_incl_last_incomplete_tu =drm_fixp2int_ceil (temp2_fp); +else + tu->n_tus_incl_last_incomplete_tu =0 ; + + temp1 =0 ; + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->original_ratio_fp, temp1_fp); + temp1_fp = tu->average_valid2_fp - temp2_fp; + temp2_fp =drm_fixp_from_fraction (tu->n_tus_incl_last_incomplete_tu,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + temp1 =drm_fixp2int_ceil (temp1_fp); + + temp = tu->i_upper_boundary_count * tu->nlanes; + temp1_fp =drm_fixp_from_fraction (tu->tu_size,1 ); + temp2_fp =drm_fixp_mul (tu->original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu->new_valid_boundary_link,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (temp,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + +if (temp2_fp) + temp2 =drm_fixp2int_ceil (temp2_fp); +else + temp2 =0 ; + tu->extra_required_bytes_new_tmp = (int )(temp1 + temp2); + + temp1_fp =drm_fixp_from_fraction (8 , tu->bpp); + temp2_fp =drm_fixp_from_fraction ( + tu->extra_required_bytes_new_tmp,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu->extra_pclk_cycles_tmp =drm_fixp2int_ceil (temp1_fp); +else + tu->extra_pclk_cycles_tmp =0 ; + + temp1_fp =drm_fixp_from_fraction (tu->extra_pclk_cycles_tmp,1 ); + temp2_fp =drm_fixp_div (tu->lclk_fp, tu->pclk_fp); + temp1_fp =drm_fixp_mul (temp1_fp, temp2_fp); + +if (temp1_fp) + tu->extra_pclk_cycles_in_link_clk_tmp = +drm_fixp2int_ceil (temp1_fp); +else + tu->extra_pclk_cycles_in_link_clk_tmp =0 ; + + tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link; + + tu->lower_filler_size_tmp = tu->filler_size_tmp +1 ; + + tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp + + tu->lower_filler_size_tmp + + tu->extra_buffer_margin; + + temp1_fp =drm_fixp_from_fraction (tu->delay_start_link_tmp,1 ); + tu->delay_start_time_fp =drm_fixp_div (temp1_fp, tu->lclk_fp); + + compare_result_1 =_tu_param_compare (tu->n_n_err_fp, tu->diff_abs_fp); +if (compare_result_1 ==2 ) + compare_result_1 =1 ; +else + compare_result_1 =0 ; + + compare_result_2 =_tu_param_compare (tu->n_n_err_fp, tu->err_fp); +if (compare_result_2 ==2 ) + compare_result_2 =1 ; +else + compare_result_2 =0 ; + + compare_result_3 =_tu_param_compare (tu->hbp_time_fp, + tu->delay_start_time_fp); +if (compare_result_3 ==2 ) + compare_result_3 =0 ; +else + compare_result_3 =1 ; + +if (((tu->even_distribution ==1 ) || + ((tu->even_distribution_BF ==0 ) && + (tu->even_distribution_legacy ==0 ))) && + tu->n_err_fp >=0 && tu->n_n_err_fp >=0 && + compare_result_2 && + (compare_result_1 || (tu->min_hblank_violated ==1 )) && + (tu->new_valid_boundary_link -1 ) >0 && + compare_result_3 && + (tu->delay_start_link_tmp <=1023 )) { + tu->upper_boundary_count = tu->i_upper_boundary_count; + tu->lower_boundary_count = tu->i_lower_boundary_count; + tu->err_fp = tu->n_n_err_fp; + tu->boundary_moderation_en = true; + tu->tu_size_desired = tu->tu_size; + tu->valid_boundary_link = tu->new_valid_boundary_link; + tu->effective_valid_recorded_fp = tu->effective_valid_fp; + tu->even_distribution_BF =1 ; + tu->delay_start_link = tu->delay_start_link_tmp; + }else if (tu->boundary_mod_lower_err ==0 ) { + compare_result_1 =_tu_param_compare (tu->n_n_err_fp, + tu->diff_abs_fp); +if (compare_result_1 ==2 ) + tu->boundary_mod_lower_err =1 ; + } +} + +static void _dp_ctrl_calc_tu (struct dp_tu_calc_input *in, +struct dp_vc_tu_mapping_table *tu_table) +{ +struct tu_algo_data tu; +int compare_result_1, compare_result_2; +u64 temp =0 ; +s64 temp_fp =0 , temp1_fp =0 , temp2_fp =0 ; + +s64 LCLK_FAST_SKEW_fp =drm_fixp_from_fraction (6 ,10000 );/* 0.0006 */ +s64 const_p49_fp =drm_fixp_from_fraction (49 ,100 );/* 0.49 */ +s64 const_p56_fp =drm_fixp_from_fraction (56 ,100 );/* 0.56 */ +s64 RATIO_SCALE_fp =drm_fixp_from_fraction (1001 ,1000 ); + +u8 DP_BRUTE_FORCE =1 ; +s64 BRUTE_FORCE_THRESHOLD_fp =drm_fixp_from_fraction (1 ,10 );/* 0.1 */ +uint EXTRA_PIXCLK_CYCLE_DELAY =4 ; +uint HBLANK_MARGIN =4 ; + +memset (&tu,0 ,sizeof (tu)); + + tu.lclk_fp =drm_fixp_from_fraction (in->lclk,1 ); + tu.pclk_fp =drm_fixp_from_fraction (in->pclk_khz,1000 ); + tu.lwidth = in->hactive; + tu.hbp_relative_to_pclk = in->hporch; + tu.nlanes = in->nlanes; + tu.bpp = in->bpp; + tu.pixelEnc = in->pixel_enc; + tu.dsc_en = in->dsc_en; + tu.async_en = in->async_en; + + tu.err_fp =drm_fixp_from_fraction (1000 ,1 );/* 1000 */ + +if (tu.pixelEnc ==420 ) { + temp_fp =drm_fixp_from_fraction (2 ,1 ); + tu.pclk_fp =drm_fixp_div (tu.pclk_fp, temp_fp); + tu.lwidth /=2 ; + tu.hbp_relative_to_pclk /=2 ; + } + +if (tu.pixelEnc ==422 ) { +switch (tu.bpp) { +case 24 : + tu.bpp =16 ; + tu.bpc =8 ; +break ; +case 30 : + tu.bpp =20 ; + tu.bpc =10 ; +break ; +default : + tu.bpp =16 ; + tu.bpc =8 ; +break ; + } + }else { + tu.bpc = tu.bpp/3 ; + } + + temp1_fp =drm_fixp_from_fraction (4 ,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, tu.lclk_fp); + temp_fp =drm_fixp_div (temp2_fp, tu.pclk_fp); + tu.extra_buffer_margin =drm_fixp2int_ceil (temp_fp); + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_mul (tu.pclk_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.nlanes,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu.ratio_fp =drm_fixp_div (temp2_fp, tu.lclk_fp); + + tu.original_ratio_fp = tu.ratio_fp; + tu.boundary_moderation_en = false; + tu.upper_boundary_count =0 ; + tu.lower_boundary_count =0 ; + tu.i_upper_boundary_count =0 ; + tu.i_lower_boundary_count =0 ; + tu.valid_lower_boundary_link =0 ; + tu.even_distribution_BF =0 ; + tu.even_distribution_legacy =0 ; + tu.even_distribution =0 ; + tu.delay_start_time_fp =0 ; + + tu.err_fp =drm_fixp_from_fraction (1000 ,1 ); + tu.n_err_fp =0 ; + tu.n_n_err_fp =0 ; + + tu.ratio =drm_fixp2int (tu.ratio_fp); +if ((((u32 )tu.lwidth % tu.nlanes) !=0 ) && + !tu.ratio && tu.dsc_en ==0 ) { + tu.ratio_fp =drm_fixp_mul (tu.ratio_fp, RATIO_SCALE_fp); + tu.ratio =drm_fixp2int (tu.ratio_fp); +if (tu.ratio) + tu.ratio_fp =drm_fixp_from_fraction (1 ,1 ); + } + +if (tu.ratio >1 ) + tu.ratio =1 ; + +if (tu.ratio ==1 ) + goto tu_size_calc; + + compare_result_1 =_tu_param_compare (tu.ratio_fp, const_p49_fp); +if (!compare_result_1 || compare_result_1 ==1 ) + compare_result_1 =1 ; +else + compare_result_1 =0 ; + + compare_result_2 =_tu_param_compare (tu.ratio_fp, const_p56_fp); +if (!compare_result_2 || compare_result_2 ==2 ) + compare_result_2 =1 ; +else + compare_result_2 =0 ; + +if (tu.dsc_en && compare_result_1 && compare_result_2) { +HBLANK_MARGIN +=4 ; +DRM_DEBUG_DP ("Info: increase HBLANK_MARGIN to %d\n" ,HBLANK_MARGIN ); + } + +tu_size_calc: +for (tu.tu_size =32 ; tu.tu_size <=64 ; tu.tu_size++) { + temp1_fp =drm_fixp_from_fraction (tu.tu_size,1 ); + temp2_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + temp =drm_fixp2int_ceil (temp2_fp); + temp1_fp =drm_fixp_from_fraction (temp,1 ); + tu.n_err_fp = temp1_fp - temp2_fp; + +if (tu.n_err_fp < tu.err_fp) { + tu.err_fp = tu.n_err_fp; + tu.tu_size_desired = tu.tu_size; + } + } + + tu.tu_size_minus1 = tu.tu_size_desired -1 ; + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + tu.valid_boundary_link =drm_fixp2int_ceil (temp2_fp); + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp2_fp =drm_fixp_mul (temp2_fp, temp1_fp); + + temp1_fp =drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + temp2_fp =drm_fixp_div (temp2_fp, temp1_fp); + tu.n_tus =drm_fixp2int (temp2_fp); + + tu.even_distribution_legacy = tu.n_tus % tu.nlanes ==0 ?1 :0 ; +DRM_DEBUG_DP ("Info: n_sym = %d, num_of_tus = %d\n" , + tu.valid_boundary_link, tu.n_tus); + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp =drm_fixp_from_fraction (tu.n_tus +1 ,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + + temp =drm_fixp2int (temp2_fp); +if (temp && temp2_fp) + tu.extra_bytes =drm_fixp2int_ceil (temp2_fp); +else + tu.extra_bytes =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.extra_bytes,1 ); + temp2_fp =drm_fixp_from_fraction (8 , tu.bpp); + temp1_fp =drm_fixp_mul (temp1_fp, temp2_fp); + + temp =drm_fixp2int (temp1_fp); +if (temp && temp1_fp) + tu.extra_pclk_cycles =drm_fixp2int_ceil (temp1_fp); +else + tu.extra_pclk_cycles =0 ; + + temp1_fp =drm_fixp_div (tu.lclk_fp, tu.pclk_fp); + temp2_fp =drm_fixp_from_fraction (tu.extra_pclk_cycles,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + + temp =drm_fixp2int (temp1_fp); +if (temp && temp1_fp) + tu.extra_pclk_cycles_in_link_clk =drm_fixp2int_ceil (temp1_fp); +else + tu.extra_pclk_cycles_in_link_clk =0 ; + + tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link; + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + tu.ratio_by_tu_fp =drm_fixp_mul (tu.ratio_fp, temp1_fp); + + tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk + + tu.filler_size + tu.extra_buffer_margin; + + tu.resulting_valid_fp = +drm_fixp_from_fraction (tu.valid_boundary_link,1 ); + + temp1_fp =drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp =drm_fixp_div (tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + + temp1_fp =drm_fixp_from_fraction ( + (tu.hbp_relative_to_pclk -HBLANK_MARGIN ),1 ); + tu.hbp_time_fp =drm_fixp_div (temp1_fp, tu.pclk_fp); + + temp1_fp =drm_fixp_from_fraction (tu.delay_start_link,1 ); + tu.delay_start_time_fp =drm_fixp_div (temp1_fp, tu.lclk_fp); + + compare_result_1 =_tu_param_compare (tu.hbp_time_fp, + tu.delay_start_time_fp); +if (compare_result_1 ==2 )/* if (hbp_time_fp < delay_start_time_fp) */ + tu.min_hblank_violated =1 ; + + temp1_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + tu.hactive_time_fp =drm_fixp_div (temp1_fp, tu.pclk_fp); + + compare_result_2 =_tu_param_compare (tu.hactive_time_fp, + tu.delay_start_time_fp); +if (compare_result_2 ==2 ) + tu.min_hblank_violated =1 ; + + tu.delay_start_time_fp =0 ; + +/* brute force */ + + tu.delay_start_link_extra_pixclk =EXTRA_PIXCLK_CYCLE_DELAY ; + tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp; + + temp =drm_fixp2int (tu.diff_abs_fp); +if (!temp && tu.diff_abs_fp <=0xffff ) + tu.diff_abs_fp =0 ; + +/* if(diff_abs < 0) diff_abs *= -1 */ +if (tu.diff_abs_fp <0 ) + tu.diff_abs_fp =drm_fixp_mul (tu.diff_abs_fp,-1 ); + + tu.boundary_mod_lower_err =0 ; +if ((tu.diff_abs_fp !=0 && + ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) || + (tu.even_distribution_legacy ==0 ) || + (DP_BRUTE_FORCE ==1 ))) || + (tu.min_hblank_violated ==1 )) { +do { + tu.err_fp =drm_fixp_from_fraction (1000 ,1 ); + + temp1_fp =drm_fixp_div (tu.lclk_fp, tu.pclk_fp); + temp2_fp =drm_fixp_from_fraction ( + tu.delay_start_link_extra_pixclk,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu.extra_buffer_margin = +drm_fixp2int_ceil (temp1_fp); +else + tu.extra_buffer_margin =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + +if (temp1_fp) + tu.n_symbols =drm_fixp2int_ceil (temp1_fp); +else + tu.n_symbols =0 ; + +for (tu.tu_size =32 ; tu.tu_size <=64 ; tu.tu_size++) { +for (tu.i_upper_boundary_count =1 ; + tu.i_upper_boundary_count <=15 ; + tu.i_upper_boundary_count++) { +for (tu.i_lower_boundary_count =1 ; + tu.i_lower_boundary_count <=15 ; + tu.i_lower_boundary_count++) { +_tu_valid_boundary_calc (&tu); + } + } + } + tu.delay_start_link_extra_pixclk--; + }while (tu.boundary_moderation_en != true && + tu.boundary_mod_lower_err ==1 && + tu.delay_start_link_extra_pixclk !=0 ); + +if (tu.boundary_moderation_en == true) { + temp1_fp =drm_fixp_from_fraction ( + (tu.upper_boundary_count * + tu.valid_boundary_link + + tu.lower_boundary_count * + (tu.valid_boundary_link -1 )),1 ); + temp2_fp =drm_fixp_from_fraction ( + (tu.upper_boundary_count + + tu.lower_boundary_count),1 ); + tu.resulting_valid_fp = +drm_fixp_div (temp1_fp, temp2_fp); + + temp1_fp =drm_fixp_from_fraction ( + tu.tu_size_desired,1 ); + tu.ratio_by_tu_fp = +drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + + tu.valid_lower_boundary_link = + tu.valid_boundary_link -1 ; + + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp1_fp =drm_fixp_mul (temp2_fp, temp1_fp); + temp2_fp =drm_fixp_div (temp1_fp, + tu.resulting_valid_fp); + tu.n_tus =drm_fixp2int (temp2_fp); + + tu.tu_size_minus1 = tu.tu_size_desired -1 ; + tu.even_distribution_BF =1 ; + + temp1_fp = +drm_fixp_from_fraction (tu.tu_size_desired,1 ); + temp2_fp = +drm_fixp_div (tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + } + } + + temp1_fp =drm_fixp_from_fraction (tu.lwidth,1 ); + temp2_fp =drm_fixp_mul (LCLK_FAST_SKEW_fp, temp1_fp); + +if (temp2_fp) + temp =drm_fixp2int_ceil (temp2_fp); +else + temp =0 ; + + temp1_fp =drm_fixp_from_fraction (tu.nlanes,1 ); + temp2_fp =drm_fixp_mul (tu.original_ratio_fp, temp1_fp); + temp1_fp =drm_fixp_from_fraction (tu.bpp,8 ); + temp2_fp =drm_fixp_div (temp1_fp, temp2_fp); + temp1_fp =drm_fixp_from_fraction (temp,1 ); + temp2_fp =drm_fixp_mul (temp1_fp, temp2_fp); + temp =drm_fixp2int (temp2_fp); + +if (tu.async_en) + tu.delay_start_link += (int )temp; + + temp1_fp =drm_fixp_from_fraction (tu.delay_start_link,1 ); + tu.delay_start_time_fp =drm_fixp_div (temp1_fp, tu.lclk_fp); + +/* OUTPUTS */ + tu_table->valid_boundary_link = tu.valid_boundary_link; + tu_table->delay_start_link = tu.delay_start_link; + tu_table->boundary_moderation_en = tu.boundary_moderation_en; + tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link; + tu_table->upper_boundary_count = tu.upper_boundary_count; + tu_table->lower_boundary_count = tu.lower_boundary_count; + tu_table->tu_size_minus1 = tu.tu_size_minus1; + +DRM_DEBUG_DP ("TU: valid_boundary_link: %d\n" , tu_table->valid_boundary_link); +DRM_DEBUG_DP ("TU: delay_start_link: %d\n" , tu_table->delay_start_link); +DRM_DEBUG_DP ("TU: boundary_moderation_en: %d\n" , + tu_table->boundary_moderation_en); +DRM_DEBUG_DP ("TU: valid_lower_boundary_link: %d\n" , + tu_table->valid_lower_boundary_link); +DRM_DEBUG_DP ("TU: upper_boundary_count: %d\n" , + tu_table->upper_boundary_count); +DRM_DEBUG_DP ("TU: lower_boundary_count: %d\n" , + tu_table->lower_boundary_count); +DRM_DEBUG_DP ("TU: tu_size_minus1: %d\n" , tu_table->tu_size_minus1); +} + +static void dp_ctrl_calc_tu_parameters (struct dp_ctrl_private *ctrl, +struct dp_vc_tu_mapping_table *tu_table) +{ +struct dp_tu_calc_input in; +struct drm_display_mode *drm_mode; + + drm_mode = &ctrl->panel->dp_mode.drm_mode; + + in.lclk = ctrl->link->link_params.rate /1000 ; + in.pclk_khz = drm_mode->clock; + in.hactive = drm_mode->hdisplay; + in.hporch = drm_mode->htotal - drm_mode->hdisplay; + in.nlanes = ctrl->link->link_params.num_lanes; + in.bpp = ctrl->panel->dp_mode.bpp; + in.pixel_enc =444 ; + in.dsc_en =0 ; + in.async_en =0 ; + +_dp_ctrl_calc_tu (&in, tu_table); +} + +static void dp_ctrl_setup_tr_unit (struct dp_ctrl_private *ctrl) +{ +u32 dp_tu =0x0 ; +u32 valid_boundary =0x0 ; +u32 valid_boundary2 =0x0 ; +struct dp_vc_tu_mapping_table tu_calc_table; + +dp_ctrl_calc_tu_parameters (ctrl, &tu_calc_table); + + dp_tu |= tu_calc_table.tu_size_minus1; + valid_boundary |= tu_calc_table.valid_boundary_link; + valid_boundary |= (tu_calc_table.delay_start_link <<16 ); + + valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link <<1 ); + valid_boundary2 |= (tu_calc_table.upper_boundary_count <<16 ); + valid_boundary2 |= (tu_calc_table.lower_boundary_count <<20 ); + +if (tu_calc_table.boundary_moderation_en) + valid_boundary2 |=BIT (0 ); + +pr_debug ("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n" , + dp_tu, valid_boundary, valid_boundary2); + + ctrl->catalog->dp_tu = dp_tu; + ctrl->catalog->valid_boundary = valid_boundary; + ctrl->catalog->valid_boundary2 = valid_boundary2; + +dp_catalog_ctrl_update_transfer_unit (ctrl->catalog); +} + +static int dp_ctrl_wait4video_ready (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + +if (!wait_for_completion_timeout (&ctrl->video_comp, +WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES )) { +DRM_ERROR ("Link Train timedout\n" ); + ret = -ETIMEDOUT ; + } +return ret; +} + +static int dp_ctrl_update_vx_px (struct dp_ctrl_private *ctrl) +{ +struct dp_link *link = ctrl->link; +int ret =0 , lane; +u8 buf[4 ]; +u32 max_level_reached =0 ; +u32 voltage_swing_level = link->phy_params.v_level; +u32 pre_emphasis_level = link->phy_params.p_level; + + ret =dp_catalog_ctrl_update_vx_px (ctrl->catalog, + voltage_swing_level, pre_emphasis_level); +if (ret) +return ret; + +if (voltage_swing_level ==DP_TRAIN_VOLTAGE_SWING_MAX ) { +pr_debug ("max. voltage swing level reached %d\n" , + voltage_swing_level); + max_level_reached |=DP_TRAIN_MAX_SWING_REACHED ; + } + +if (pre_emphasis_level ==DP_TRAIN_PRE_EMPHASIS_MAX ) { +pr_debug ("max. pre-emphasis level reached %d\n" , + pre_emphasis_level); + max_level_reached |=DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ; + } + + pre_emphasis_level <<=DP_TRAIN_PRE_EMPHASIS_SHIFT ; + +for (lane =0 ; lane <4 ; lane++) + buf[lane] = voltage_swing_level | pre_emphasis_level | max_level_reached; + +pr_debug ("sink: p|v=0x%x\n" , voltage_swing_level | pre_emphasis_level); + ret =drm_dp_dpcd_write (ctrl->aux->drm_aux,DP_TRAINING_LANE0_SET , buf,4 ); +if (ret ==4 ) + ret =0 ; + +return ret; +} + +static bool dp_ctrl_train_pattern_set (struct dp_ctrl_private *ctrl, +u8 pattern) +{ +u8 buf[4 ]; +int ret =0 ; + +pr_debug ("sink: pattern=%x\n" , pattern); + + buf[0 ] = pattern; + ret =drm_dp_dpcd_writeb (ctrl->aux->drm_aux,DP_TRAINING_PATTERN_SET , buf[0 ]); +return ret ==1 ; +} + +static int dp_ctrl_read_link_status (struct dp_ctrl_private *ctrl, +u8 *link_status) +{ +int len =0 ; +u32 const offset =DP_LANE_ALIGN_STATUS_UPDATED -DP_LANE0_1_STATUS ; +u32 link_status_read_max_retries =100 ; + +while (--link_status_read_max_retries) { + len =drm_dp_dpcd_read_link_status (ctrl->aux->drm_aux, + link_status); +if (len !=DP_LINK_STATUS_SIZE ) { +DRM_ERROR ("DP link status read failed, err: %d\n" , len); +return len; + } + +if (!(link_status[offset] &DP_LINK_STATUS_UPDATED )) +return 0 ; + } + +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_train_1 (struct dp_ctrl_private *ctrl) +{ +int tries, old_v_level, ret =0 ; +u8 link_status[DP_LINK_STATUS_SIZE ]; +int const maximum_retries =5 ; + +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + + ret =dp_catalog_ctrl_set_pattern (ctrl->catalog,DP_TRAINING_PATTERN_1 ); +if (ret) +return ret; +dp_ctrl_train_pattern_set (ctrl,DP_TRAINING_PATTERN_1 | +DP_LINK_SCRAMBLING_DISABLE ); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + tries =0 ; + old_v_level = ctrl->link->phy_params.v_level; +for (tries =0 ; tries < maximum_retries; tries++) { +drm_dp_link_train_clock_recovery_delay (ctrl->panel->dpcd); + + ret =dp_ctrl_read_link_status (ctrl, link_status); +if (ret) +return ret; + +if (drm_dp_clock_recovery_ok (link_status, + ctrl->link->link_params.num_lanes)) { +return ret; + } + +if (ctrl->link->phy_params.v_level ==DP_TRAIN_VOLTAGE_SWING_MAX ) { +DRM_ERROR_RATELIMITED ("max v_level reached\n" ); +return -EAGAIN ; + } + +if (old_v_level != ctrl->link->phy_params.v_level) { + tries =0 ; + old_v_level = ctrl->link->phy_params.v_level; + } + +pr_debug ("clock recovery not done, adjusting vx px\n" ); + +dp_link_adjust_levels (ctrl->link, link_status); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + } + +DRM_ERROR ("max tries reached\n" ); +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_rate_down_shift (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + +switch (ctrl->link->link_params.rate) { +case 810000 : + ctrl->link->link_params.rate =540000 ; +break ; +case 540000 : + ctrl->link->link_params.rate =270000 ; +break ; +case 270000 : +case 162000 : +default : + ctrl->link->link_params.rate =162000 ; +break ; + }; + +pr_debug ("new rate=0x%x\n" , ctrl->link->link_params.rate); + +return ret; +} + +static void dp_ctrl_clear_training_pattern (struct dp_ctrl_private *ctrl) +{ +dp_ctrl_train_pattern_set (ctrl,DP_TRAINING_PATTERN_DISABLE ); +drm_dp_link_train_channel_eq_delay (ctrl->panel->dpcd); +} + +static int dp_ctrl_link_training_2 (struct dp_ctrl_private *ctrl) +{ +int tries =0 , ret =0 ; +char pattern; +int const maximum_retries =5 ; +u8 link_status[DP_LINK_STATUS_SIZE ]; + +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + +if (drm_dp_tps3_supported (ctrl->panel->dpcd)) + pattern =DP_TRAINING_PATTERN_3 ; +else + pattern =DP_TRAINING_PATTERN_2 ; + + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + ret =dp_catalog_ctrl_set_pattern (ctrl->catalog, pattern); +if (ret) +return ret; + +dp_ctrl_train_pattern_set (ctrl, pattern |DP_RECOVERED_CLOCK_OUT_EN ); + +for (tries =0 ; tries <= maximum_retries; tries++) { +drm_dp_link_train_channel_eq_delay (ctrl->panel->dpcd); + + ret =dp_ctrl_read_link_status (ctrl, link_status); +if (ret) +return ret; + +if (drm_dp_channel_eq_ok (link_status, + ctrl->link->link_params.num_lanes)) +return ret; + +dp_link_adjust_levels (ctrl->link, link_status); + ret =dp_ctrl_update_vx_px (ctrl); +if (ret) +return ret; + + } + +return -ETIMEDOUT ; +} + +static int dp_ctrl_link_train (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; +u8 encoding =DP_SET_ANSI_8B10B ; +struct drm_dp_link link_info = {0 }; + + ctrl->link->phy_params.p_level =0 ; + ctrl->link->phy_params.v_level =0 ; + +dp_ctrl_config_ctrl (ctrl); + + ret =drm_dp_link_probe (ctrl->aux->drm_aux, &link_info); +if (ret <0 ) { +DRM_ERROR ("failed to retrieve link capabilities. ret=%d\n" , ret); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); +return ret; + } + +drm_dp_link_configure (ctrl->aux->drm_aux, &link_info); +drm_dp_dpcd_write (ctrl->aux->drm_aux,DP_MAIN_LINK_CHANNEL_CODING_SET , + &encoding,1 ); + + ret =dp_ctrl_link_train_1 (ctrl); +if (ret) { +DRM_ERROR ("link training #1 failed. ret=%d\n" , ret); + goto end; + } + +/* print success info as this is a result of user initiated action */ +DRM_DEBUG_DP ("link training #1 successful\n" ); + + ret =dp_ctrl_link_training_2 (ctrl); +if (ret) { +DRM_ERROR ("link training #2 failed. ret=%d\n" , ret); + goto end; + } + +/* print success info as this is a result of user initiated action */ +DRM_DEBUG_DP ("link training #2 successful\n" ); + +end: +dp_catalog_ctrl_state_ctrl (ctrl->catalog,0 ); + +dp_ctrl_clear_training_pattern (ctrl); +return ret; +} + +static int dp_ctrl_setup_main_link (struct dp_ctrl_private *ctrl,bool train) +{ +bool mainlink_ready = false; +int ret =0 ; + +dp_catalog_ctrl_mainlink_ctrl (ctrl->catalog, true); + + ret =dp_link_psm_config (ctrl->link, &ctrl->panel->link_info, false); +if (ret) +return ret; + +if (ctrl->link->sink_request &DP_TEST_LINK_PHY_TEST_PATTERN ) +return ret; + +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 do a DP software reset. +*/ +dp_catalog_ctrl_reset (ctrl->catalog); + + ret =dp_ctrl_link_train (ctrl); +if (ret) +return ret; + +send_video: +/* +* Set up transfer unit values and set controller state to send +* video. +*/ +dp_ctrl_setup_tr_unit (ctrl); +dp_catalog_ctrl_state_ctrl (ctrl->catalog,DP_STATE_CTRL_SEND_VIDEO );Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +36
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.c new file +27
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
As mentioned in v1 review, please remove this
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_display.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This is unused
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 162 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +162
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
I spent a bit of time trying to unravel this in v1, but you didn't respond to my comments or change this code. Could you please do one or the other?
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 360 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +360
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Remove please
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 102 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +102
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Please remove
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 2,867 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +289
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.h new file +28
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.c new file +189
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.h new file +20
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.c new file +228
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.h new file +85
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_link.c new file +1216
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_link.h new file +132
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_panel.c new file +504
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_panel.h new file +91
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_parser.c new file +25
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This error message is still using the old function name
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +16
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Thanks for moving these. You probably also want to update the function names so they're consistent with their new file (ie: dp_parser_io*)
drivers/gpu/drm/msm/dp/dp_parser.c
Quoted 580 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +580
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Remove
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +30
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
From v1:
Delete the function and just print the enum value
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 122 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +122
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Asked in v1 to remove this.
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +16
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This seems unused
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
And this
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
No need for this to be a callback, just expose the function and call it.
drivers/gpu/drm/msm/dp/dp_parser.h
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +22
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
The whole separate parser concept is overkill imo. Just do the dt parsing where applicable (ie: instead of doing all of the dp_power parsing in dp_parser, just parse in dp_power, same with aux, etc.). It just adds a layer of indirection for no benefit.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +33
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
So these are the types of checks I was talking about in v1, if num_vreg is > 0 and in_vreg is NULL, we have a serious problem that is definitely worthy of a crash.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +5
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This will fit on one line
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +40
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
I don't get a good feeling about jumping out and back into the loop here. This seems like it'd be pretty easy to break with future changes. How about simplifying this function to (uncompiled/untested):
static int dp_power_init_vreg(struct device *dev, struct dss_vreg *in_vreg,
int num_vreg)
{
int i, rc;
for (i = 0; i < num_vreg; i++) {
struct regulator *reg;
reg = devm_regulator_get(dev, in_vreg[i].vreg_name);
rc = PTR_RET(reg);
if (rc) {
DRM_DEV_ERROR(dev, "%s get failed. (%d)\n",
in_vreg[i].vreg_name, rc);
goto error;
}
if (regulator_count_voltages(reg) > 0)
rc = regulator_set_voltage(reg, in_vreg[i].min_voltage,
in_vreg[i].max_voltage);
if (rc < 0) {
DRM_DEV_ERROR(dev, "%s set_voltage fail (%d)\n",
in_vreg[i].vreg_name, rc);
goto error;
}
}
in_vreg[i].vreg = reg;
}
return 0;error:
for (i--; i >= 0; i--) {
if (regulator_count_voltages(in_vreg[i].vreg) > 0)
regulator_set_load(in_vreg[i].vreg, 0);
in_vreg[i].vreg = NULL;
}
return rc;
}drivers/gpu/drm/msm/dp/dp_power.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same comment here as above
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Or you could save a level of indent and do:
if (!curr_vreg->vreg)
continue;drivers/gpu/drm/msm/dp/dp_power.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
No need for the type local, just do the count check in the if (like I've done above)
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Do you also need to clear the load here?
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +2
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This is unnecessary
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_power.c new file +1
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This is likely unnecessary too, right?
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 56 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +56
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
These are 2 completely separate functions smashed into one. Please split off into dp_power_enable/disable_vreg
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Instead of setting up a label for this, just call the set_load in the error condition above.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This is just copied from the disable path above. So once these functions are split out, just call the _disable function in case of error.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Please update these function names to match the rest of the file (ie:
dp_power_*)
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +11
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
rc can only be zero here, so that check is unnecssary. Also the () around the bounds check are also not needed.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
You already clean these up and clear them in init_vreg() function (as you should), so this loop is unnecessary, just return rc.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same comment here as in my v1 reviews regarding labels
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
From my v1 review:
Unnecessary (), applies elsewhere too, please make a pass
If I'm going to take the time to review an > 10k line review, could you please take the time to address the comments?
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 29 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +29
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Again, the enable_vreg function already cleans this up, so you don't have to here.
Quoted 1,110 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +485
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_power.h new file +51
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_reg.h new file +475
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Part of the diff is not shown here. View the raw message.
Re: [DPU PATCH v2 3/3] drm/msm/dp: add support for DP PLL driver
In reply to a message not in the archiveHello Sam,
Only DP core driver comments have been addressed in V2.
PLL driver comments in V1 and your comments in V2 version will be addressed in V3. Responded to your comments/queries below.
Quoted 11 lines · Sam Ravnborg
Hi Chandan
A few comments in the following.
Mostly nitpicks / style stuff, not a throughly review.Sam
drivers/gpu/drm/msm/Kconfig config DRM_MSM_DP · line 62
Quoted 2 lines
drivers/gpu/drm/msm/Kconfig +2
-0+config DRM_MSM_DP_PLL + bool "Enable DP PLL driver in MSM DRM"So
DRM_MSM_DP_PLLcannot be 'm'.
No, we don't have support for modular driver.
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/msm/Makefile +0
-0@@ -137,4 +137,10 @@ msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) +=
dsi/pll/dsi_pll_14nm.o
msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) +=dsi/pll/dsi_pll_10nm.oendif
Quoted 11 lines
drivers/gpu/drm/msm/Makefile msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o · line 144
Quoted 5 lines
drivers/gpu/drm/msm/Makefile +5
-0+ifeq ($(CONFIG_DRM_MSM_DP_PLL),y) +msm-y += dp/pll/dp_pll.o +msm-y += dp/pll/dp_pll_10nm.o +msm-y += dp/pll/dp_pll_10nm_util.o +endifPlease write this in the
Kbuildcaninical style like this:
msm-$(DRM_MSM_DP_PLL) +=dp/pll/dp_pll.omsm-$(DRM_MSM_DP_PLL) +=dp/pll/dp_pll_10nm.oetc.
Will fix this in V3.
Quoted 3 lines
Or even better - descend into msm/dp/pll to build it - this is normal kernel style.
I am following the existing format in drm/msm folder.
Quoted 20 lines
Quoted 20 lines
drivers/gpu/drm/msm/Makefile +19
-0+ if (!dp_parser) { + DRM_ERROR("Parser not initialized.\n"); + return -EINVAL; + } + + pll_node = of_parse_phandle(pdev->dev.of_node, "pll-node", 0); + if (!pll_node) { + DRM_DEV_ERROR(&pdev->dev, "cannot find pll device\n"); + return -ENXIO; + } + + pll_pdev = of_find_device_by_node(pll_node); + if (pll_pdev) + dp_parser->pll = platform_get_drvdata(pll_pdev); + + of_node_put(pll_node); + + if (!pll_pdev || !dp_parser->pll) { + DRM_DEV_ERROR(&pdev->dev, "%s: pll driver is not ready\n",
__func__);
Quoted 9 lines
drivers/gpu/drm/msm/Makefile
Quoted 2 lines
drivers/gpu/drm/msm/Makefile +2
-0+ return -EPROBE_DEFER; + }The use of DRM_*ERROR is inconsistent.
In one placeDRM_ERRORis used, and string ends with '.'
In one placeDRM_DEV_ERRORis used with a simple string.
In one placeDRM_DEV_ERRORis used where the__func__is added as parameter. When reading the code such inconsistencies makes it harder to follow the code.
Will address this in V3.
Quoted 14 lines
Quoted 14 lines
drivers/gpu/drm/msm/Makefile +6
-0+ + dp_parser->pll_dev = get_device(&pll_pdev->dev); + + return 0; +} + static irqreturn_t dp_display_irq(int irq, void *dev_id) { struct dp_display_private *dp = dev_id;@@ -114,6 +156,12 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; }
Quoted 6 lines
drivers/gpu/drm/msm/Makefile static int dp_display_bind(struct device *dev, · line 162
Quoted 3 lines
drivers/gpu/drm/msm/Makefile +3
-0+ rc = dp_get_pll(dp); + if (rc) { + DRM_ERROR(" DP get PLL instance failed\n");Any reason why the error is indented with a space? Also, is the DRM*ERROR in
dp_get_pll()not enough?
Will fix this in V3.
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.h +0
-0@@ -14,6 +14,7 @@* @init: initializes the regulators/core clocks/GPIOs/pinctrl * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_power.h line 20
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_power.h +1
-0* @clk_enable: enable/disable the DP clocks +* @set_link_clk_parent: set the parent of DP link clock * @set_pixel_clk_parent: set the parent of DP pixel clock */ struct dp_power {This chunk is unrelated - it just added some missing doc. Do it belong in another patch?
Will remove this in V3.
Quoted 47 lines
Quoted 18 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +3
-0@@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ */drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +7
-0+ +#include "dp_pll.h" + +int msm_dp_pll_util_parse_dt_clock (struct platform_device *pdev, +struct msm_dp_pll *pll) +{ +u32 i =0 , rc =0 ;drivers/gpu/drm/msm/dp/pll/dp_pll.c line 21
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+struct dss_module_power *mp = &pll->mp; +const char *clock_name; +u32 clock_rate; + + mp->num_clk =of_property_count_strings (pdev->dev.of_node, +"clock-names" ); +if (mp->num_clk <=0 ) { +DRM_ERROR ("clocks are not defined\n" ); + goto clk_err; + }You have a
pdev->dev, so useDRM_DEV_ERROR()Quoted 17 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +17
-0+ +struct msm_dp_pll *msm_dp_pll_init (struct platform_device *pdev, +enum msm_dp_pll_type type,int id) +{ +struct device *dev = &pdev->dev; +struct msm_dp_pll *pll; + +switch (type) { +case MSM_DP_PLL_10NM : + pll =msm_dp_pll_10nm_init (pdev, id); +break ; +default : + pll =ERR_PTR (-ENXIO ); +break ; + } + +if (IS_ERR (pll)) {
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 73
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +7
-0+DRM_DEV_ERROR (dev,"%s: failed to init DP PLL\n" , __func__); +return pll; + } + + pll->type = type; + +DBG ("DP:%d PLL registered" , id);Avoid rolling your own DEBUG macros.
Will fix this in V3.
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 83
Quoted 8 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +8
-0+} + +static const struct of_device_id dp_pll_dt_match[] = { +#ifdef CONFIG_DRM_MSM_DP_10NM_PLL + { .compatible ="qcom,dp-pll-10nm" }, +#endif + {} +};We only have one entry here.
Will remove the ifdefs in V3.
Quoted 10 lines
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+ +static int dp_pll_driver_probe (struct platform_device *pdev) +{ +struct msm_dp_pll *pll; +struct device *dev = &pdev->dev; +const struct of_device_id *match; +enum msm_dp_pll_type type; + + match =of_match_node (dp_pll_dt_match, dev->of_node); +if (!match)
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 99
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+return -ENODEV ; + +if (!strcmp (match->compatible,"qcom,dp-pll-10nm" )) + type =MSM_DP_PLL_10NM ; +else + type =MSM_DP_PLL_MAX ;So the if will always be true, because we can only match one compatible
- no?
Yes, you are right. Will remove this unnecessary check in v3.
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 105
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ + pll =msm_dp_pll_init (pdev, type,0 ); +if (IS_ERR_OR_NULL (pll)) { +dev_info (dev, +"%s: pll init failed: %ld, need separate pll clk driver\n" , + __func__,PTR_ERR (pll));
dev_info=>DRM_DEV_ERROR
Will fix this in V3.
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c line 119
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+static int dp_pll_driver_remove (struct platform_device *pdev) +{ +struct msm_dp_pll *pll =platform_get_drvdata (pdev); + +if (pll) { +//msm_dsi_pll_destroy(pll); Debug artifact?
Will fix this in V3.
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +3
-0+#define PLL_REG_W (base, offset, data) \ + writel_relaxed((data), (base) + (offset)) +#define PLL_REG_R (base, offset) readl_relaxed((base) + (offset))I recall you wrote in the commit message that the
_relaxedvariants was dropped?
Only DP core driver comments have been addressed in V2. PLL driver comments will be fixed in V3.
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ +struct msm_dp_pll *msm_dp_pll_init (struct platform_device *pdev, +enum msm_dp_pll_type type,int id); + +int msm_dp_pll_util_parse_dt_clock (struct platform_device *pdev, +struct msm_dp_pll *pll);Indent of sencond line with additional function arguments has inconsistent indent.
Follwo same style in all files, preferable the DRM style.
Will fix them in V3.
Quoted 64 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +3
-0+ +#ifdef CONFIG_DRM_MSM_DP_10NM_PLL +struct msm_dp_pll *msm_dp_pll_10nm_init(struct platform_device *pdev,int id);
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +2
-0+#else +struct msm_dp_pll *msm_dp_pll_10nm_init(struct platform_device *pdev,int id)
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +4
-0+{ +return ERR_PTR (-ENODEV ); +} +#endif I cannot see how this works if
CONFIG_DRM_MSM_DP_10NM_PLLis not defined. It looks like you have both a function in a header (no static inline?) and a function with the same name in a .c file.
Maybe this driver was not built without theCONFIG_DRM_MSM_DP_10NM_PLLset to y?Quoted 41 lines
+/*
+ * Display Port PLL driver block diagram for branch clocks
+ *
+ * +------------------------------++ * | DP_VCO_CLK | + * | | + * | +-------------------+ | + * | | (DP PLL/VCO) | | + * | +---------+---------+ | + * | v | + * | +----------+-----------+ | + * | | hsclk_divsel_clk_src | | + * | +----------+-----------+ |+ * +------------------------------+
+ * |
+ * +------------<---------v------------>----------+
+ * | |+ * +-----v------------+ | + * | dp_link_clk_src | | + * | divsel_ten | | + * +---------+--------+ | + * | | + * | | + * v v + * Input to DISPCC block | + * for link clk, crypto clk | + * and interface clock |+ * |
+ * |
+ * +--------<------------+-----------------+---<---+
+ * | | |+ * +-------v------+ +--------v-----+ +--------v------+ + * | vco_divided | | vco_divided | | vco_divided | + * | _clk_src | | _clk_src | | _clk_src | + * | | | | | | + * |divsel_six | | divsel_two | | divsel_four | + * +-------+------+ +-----+--------+ +--------+------++ * | | |
+ * v------->----------v-------------<------v
+ * |
+ * +----------+---------+Quoted 7 lines
+ * | vco_divided_clk | + * | _src_mux |+ * +---------+----------+
+ * |
+ * v
+ * Input to DISPCC block
+ * for DP pixel clock
Quoted 4 lines
Nice drawing!
Try to avoid mixing space and tabs in the above.
Will be addressed in V3.
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 8 lines
+ *
+ */drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +6
-0+ +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/regmap.h> +#include <linux/clk.h> Please sort in alphabetic order.
Will fix this in V3.
Quoted 3 lines
Quoted 1 line
+/* Op structures */
Op => Ops?
Will address this in V3.
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +7
-0+} + +static int clk_mux_determine_rate (struct clk_hw *hw, +struct clk_rate_request *req) +{ +int ret =0 ; +
Quoted 9 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +7
-0+ ret =__clk_mux_determine_rate_closest (hw, req); +if (ret) +return ret; + +/* Set the new parent of mux if there is a new valid parent */ +if (hw->clk && req->best_parent_hw->clk) +clk_set_parent (hw->clk, req->best_parent_hw->clk);Should you check error code here?
Will fix this in V3.
Quoted 26 lines
Quoted 14 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +14
-0+ +return 0 ; +} + +} + +static int dp_pll_10nm_register (struct dp_pll_10nm *pll_10nm) +{ +char clk_name[32 ], parent[32 ], vco_name[32 ]; +struct clk_init_data vco_init = { + .parent_names = (const char *[]){"bi_tcxo" }, + .num_parents =1 , + .name = vco_name, + .flags =CLK_IGNORE_UNUSED ,drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +10
-0+ .ops = &dp_10nm_vco_clk_ops, + }; +struct device *dev = &pll_10nm->pdev->dev; +struct clk_hw **hws = pll_10nm->hws; +struct clk_hw_onecell_data *hw_data; +struct clk_hw *hw; +int num =0 ; +int ret; + +DBG ("DP->id = %d" , pll_10nm->id);Avoid own DBG macros.
Quoted 3 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/pll/dp_pll.c new file +2
-0+ +DBG ("DP PLL%d" , id);Again.
Will replace DBG with DRM_DEBUG_DP in V3.
Thanks
Chandan
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno