Add support for DisplayPort driver on SnapDragon 845
Subsystems (5)
cover Add support for DisplayPort driver on SnapDragon 845
These patches add support for Display-Port driver on SnapDragon 845 hardware. It adds DP driver and DP PLL driver files along with the needed device-tree bindings.
The block diagram of DP driver is shown below:
+-------------+
|DRM FRAMEWORK|
+------+------+
|
+----v----+
| DP DRM |
+----+----+
|
+----v----+
+------------+| DP +----------++------+
+ +---+| DISPLAY |+---+ | |
| + +-+-----+-+ | | |
| | | | | | |
| | | | | | |
| | | | | | |
v v v v v v v
+------+ +------+ +---+ +----+ +----+ +---+ +-----+
| DP | | DP | |DP | | DP | | DP | |DP | | DP |
|PARSER| |EXTCON| |AUX| |LINK| |CTRL| |PHY| |POWER|
+--+---+ +---+--+ +---+ +----+ +--+-+ +-+-+ +-----+
| | | |
+--v---+ +---v-----+ +v-----v+
|DEVICE| |EXTCON | | DP |
| TREE | |INTERFACE| |CATALOG|
+------+ +---------+ +---+---+
|
+---v----+
|CTRL/PHY|
| HW |
+--------+These patches have dependency on clock driver changes mentioned below:
https://patchwork.kernel.org/patch/10632753/
https://patchwork.kernel.org/patch/10632757/
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 | 25 + drivers/gpu/drm/msm/Makefile | 21 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 +++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 +++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 ++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1476 +++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 + drivers/gpu/drm/msm/dp/dp_display.c | 1027 +++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 58 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 +++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 +++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 ++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 +++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 208 +++ drivers/gpu/drm/msm/dp/dp_power.c | 652 ++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 59 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 +++++ drivers/gpu/drm/msm/dp/pll/dp_pll.c | 153 ++ drivers/gpu/drm/msm/dp/pll/dp_pll.h | 64 + drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.c | 401 +++++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm.h | 94 ++ drivers/gpu/drm/msm/dp/pll/dp_pll_10nm_util.c | 531 +++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 37 files changed, 12525 insertions(+), 5 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_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.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 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
A message that is not in the archive (sent off-list or not yet received): 1539191759-14836-1-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
PATCH 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.
--- .../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 aux-channel select gpio. + + +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
A message that is not in the archive (sent off-list or not yet received): 1539191759-14836-2-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Re: [DPU PATCH 1/3] dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon 845
Quoted 3 lines · Chandan Uddaraju
Add bindings for Snapdragon 845 DisplayPort and
display-port PLL driver.
This won't get Rob Herring's review unless it's sent to the devicetree list.
Quoted 72 lines
Signed-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.
What about the AUX configuration are these configuring? What are the permissible values? If they're not describing the hardware, they probably don't belong here.
Quoted 20 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +20
-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
Documentation/devicetree/bindings/display/msm/dp.txt line 99
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ 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 aux-channel select gpio.
What does the select gpio do? Could you please describe it?
Quoted 193 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +150
-0+ + +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 · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
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 1/3] dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon 845
In reply to a message not in the archiveQuoting Chandan Uddaraju (2018-10-10 10:15:57)
Documentation/devicetree/bindings/display/msm/dp.txt line 7
Quoted 13 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +7
-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.
This is a lot of register regions! There are probably multiple devices in here.
Documentation/devicetree/bindings/display/msm/dp.txt line 12
Quoted 5 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +5
-0+ "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.
So a phy driver? Should be different binding and device than the DP controller?
Documentation/devicetree/bindings/display/msm/dp.txt line 14
Quoted 2 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +2
-0+ "dp_ln_tx0" - USB3 DP PHY combo TX-0 lane memory region. + "dp_ln_tx1" - USB3 DP PHY combo TX-1 lane memory region.
Presumably part of the phy device. Again, different binding?
Documentation/devicetree/bindings/display/msm/dp.txt line 15
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+ "dp_mmss_cc" - Display Clock Control memory region.
No. This shouldn't be reaching into the display clock controller region. That should be it's own node and device driver.
Documentation/devicetree/bindings/display/msm/dp.txt line 16
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+ "qfprom_physical" - QFPROM Phys memory region.
qfprom is accessed through nvmem framework, please use it instead of remapping it and reading random bits directly from your driver.
Documentation/devicetree/bindings/display/msm/dp.txt line 18
Quoted 2 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +2
-0+ "dp_pll" - USB3 DP combo PLL memory region. + "usb3_dp_com" - USB3 DP PHY combo memory region.
I guess this would go with the DP phy node?
Documentation/devicetree/bindings/display/msm/dp.txt line 19
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+ "hdcp_physical" - DP HDCP memory region.
Goes with the main DP device?
Please drop the full stop from all of these lines.
Documentation/devicetree/bindings/display/msm/dp.txt line 20
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+- interrupt-parent phandle to the interrupt parent device node.
We don't need this sort of duplicate information. If it's part of standard spec and not specific to this binding it can be left out.
Documentation/devicetree/bindings/display/msm/dp.txt line 26
Quoted 6 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +6
-0+- 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".
Please remove "_clk" from all your clock-names. It's redundant and makes things harder to read.
Documentation/devicetree/bindings/display/msm/dp.txt line 27
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+- pll-node: phandle to DP PLL node.
Huh?
Documentation/devicetree/bindings/display/msm/dp.txt line 29
Quoted 2 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +2
-0+- vdda-1p2-supply: phandle to vdda 1.2V regulator node. +- vdda-0p9-supply: phandle to vdda 0.9V regulator node.
Perhaps these have other names besides vdda? Maybe vdda-pll and vdda? I'd also drop the 1p2 and 0p9 from them and just describe that in freeform in the binding.
Quoted 30 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +30
-0+- 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.
Look like magic bits. Can they just be thrown into the driver? Or specified in some way that us mere mortals know what to put into these bits.
Documentation/devicetree/bindings/display/msm/dp.txt line 70
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+- qcom,max-pclk-frequency-khz: An integer specifying the maximum. pixel clock in KHz supported by Display Port.
Why is this in the binding? It isn't known based on the device compatible string?
Documentation/devicetree/bindings/display/msm/dp.txt line 71
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+- extcon: Phandle for the external connector class interface.
Is this for typec? Would be good to say what it's for.
Quoted 5 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +5
-0+- 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.
Documentation/devicetree/bindings/display/msm/dp.txt line 86
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ 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
All these properties should go away. min/max should be handled by board constraints. Sleep times should be handled by regulator framework for those particular regulators. Maybe the load would be important, but I'm still sort of lost how that wouldn't be expressed through some SoC compatible string for the device and then hardcoded into the driver.
Documentation/devicetree/bindings/display/msm/dp.txt line 91
Quoted 5 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +5
-0+- 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
This isn't needed in the binding. Or at least, I don't see where it's expressed in the example, so probably just noise?
Documentation/devicetree/bindings/display/msm/dp.txt line 99
Quoted 8 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +8
-0+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 aux-channel select gpio.
These should follow standard 'gpios' properties, like aux-enable-gpios and aux-select-gpios. I guess these would need pinctrl muxing too.
Documentation/devicetree/bindings/display/msm/dp.txt line 111
Quoted 12 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +12
-0+ + +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.
Why a gdsc_base? GDSCs should be handled by power domains?
Documentation/devicetree/bindings/display/msm/dp.txt line 112
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+- interrupt-parent phandle to the interrupt parent device node.
Again, drop this one.
Documentation/devicetree/bindings/display/msm/dp.txt line 116
Quoted 4 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +4
-0+- 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".
Again, drop "_clk" please.
Documentation/devicetree/bindings/display/msm/dp.txt line 118
Quoted 2 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +2
-0+- 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.
We have assigned-clock-rates for this. Can you use that?
Documentation/devicetree/bindings/display/msm/dp.txt line 126
Quoted 8 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +8
-0+ + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/graph.txt + +Example: + msm_dp: dp_display@ae90000{ + cell-index = <0>;
Is this needed?
Documentation/devicetree/bindings/display/msm/dp.txt line 132
Quoted 6 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +6
-0+ compatible = "qcom,dp-display"; + + reg = <0 0x90000 0x0dc>, + <0 0x90200 0x0c0>, + <0 0x90400 0x508>, + <0 0x90a00 0x094>,
Looks like one device with one reg property:
<0x90000 0x1000>
Documentation/devicetree/bindings/display/msm/dp.txt line 135
Quoted 3 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +3
-0+ <1 0xeaa00 0x200>, + <1 0xea200 0x200>, + <1 0xea600 0x200>,
Looks like another device with one reg property:
<0xea000 0x1000>;
Documentation/devicetree/bindings/display/msm/dp.txt line 138
Quoted 3 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +3
-0+ <2 0x02000 0x1a0>, + <3 0x00000 0x621c>, + <1 0xea000 0x180>,
This is part of the one above.
Documentation/devicetree/bindings/display/msm/dp.txt line 139
Quoted 1 line
Documentation/devicetree/bindings/display/msm/dp.txt new file +1
-0+ <1 0xe8000 0x20>,
Well maybe this is also part of the DP phy? Then it would start somewhere a little earlier I supposed.
Documentation/devicetree/bindings/display/msm/dp.txt line 147
Quoted 8 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +8
-0+ <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>;
Why is this interrupt-parent stuff being done?
Documentation/devicetree/bindings/display/msm/dp.txt line 154
Quoted 7 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +7
-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>,
It's really odd that this device needs USB phy clocks. Is it really necessary to do this?
Quoted 42 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +42
-0+ <&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>;
Documentation/devicetree/bindings/display/msm/dp.txt line 206
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-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>; + }; + };
NAK on the above two nodes.
Quoted 11 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +11
-0+ + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + };
Documentation/devicetree/bindings/display/msm/dp.txt line 227
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ + port@1 { + reg = <1>; + dp_out: endpoint { + }; + }; + }; + }; + + dp_pll: dp-pll@c011000 {
This doesn't even match reg property.
Documentation/devicetree/bindings/display/msm/dp.txt line 237
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ 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>;
Why 1 and 2? What's going on in this example.
Documentation/devicetree/bindings/display/msm/dp.txt line 239
Quoted 2 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +2
-0+ reg-names = "pll_base", "phy_base", "ln_tx0_base", + "ln_tx1_base", "gdsc_base";
Don't think we really need "_base" on these reg-names either. Seems redundant.
Documentation/devicetree/bindings/display/msm/dp.txt line 249
Quoted 10 lines
Documentation/devicetree/bindings/display/msm/dp.txt new file +10
-0+ + 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>; + + };
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 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.
--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 15 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 ++++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 +++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1475 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 ++ drivers/gpu/drm/msm/dp/dp_display.c | 977 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 55 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 ++++++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 ++++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 +++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 ++++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 205 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 599 +++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 57 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 ++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 30 files changed, 10887 insertions(+), 1 deletion(-) 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_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.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 +14 -1
@@ -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 \
@@ -93,7 +94,19 @@ msm-y := \ msm_submitqueue.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ - disp/dpu1/dpu_dbg.o + disp/dpu1/dpu_dbg.o \ + dp/dp_debug.o + +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_extcon.o \ + dp/dp_parser.o \ + dp/dp_power.o \ + dp/dp_catalog.o \ + dp/dp_aux.o \ + dp/dp_panel.o \ + dp/dp_link.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +206 -0
216 lines not on this page · raw message
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +44 -0
68 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_aux.c new file +570 -0
570 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_aux.h new file +44 -0
44 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1188 -0
1,188 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_catalog.h new file +144 -0
144 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1475 -0
728 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +50 -0
50 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_debug.c new file +507 -0
507 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_debug.h new file +81 -0
81 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_display.c new file +977 -0
977 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_display.h new file +55 -0
55 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_drm.c new file +542 -0
542 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_drm.h new file +52 -0
52 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_extcon.c new file +400 -0
400 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_extcon.h new file +111 -0
111 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_link.c new file +1549 -0
1,549 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_link.h new file +184 -0
184 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_panel.c new file +624 -0
624 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_panel.h new file +121 -0
121 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_parser.c new file +679 -0
679 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_parser.h new file +205 -0
205 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_power.c new file +599 -0
599 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_power.h new file +57 -0
57 lines not on this page · raw message
drivers/gpu/drm/msm/dp/dp_reg.h new file +357 -0
357 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.
A message that is not in the archive (sent off-list or not yet received): 1539191759-14836-3-git-send-email-chandanu-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Re: [DPU PATCH 2/3] drm/msm/dp: add displayPort driver support
Quoted 69 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.Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 15 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 ++++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 +++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1475 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 ++ drivers/gpu/drm/msm/dp/dp_display.c | 977 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 55 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 ++++++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 ++++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 +++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 ++++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 205 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 599 +++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 57 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 ++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 30 files changed, 10887 insertions(+), 1 deletion(-) 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_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.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 should be implied so you don't need to add it.
Quoted 86 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 +14
-1@@ -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 \@@ -93,7 +94,19 @@ msm-y := \ msm_submitqueue.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ - disp/dpu1/dpu_dbg.o + disp/dpu1/dpu_dbg.o \ + dp/dp_debug.o + +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_extcon.o \ + dp/dp_parser.o \ + dp/dp_power.o \ + dp/dp_catalog.o \ + dp/dp_aux.o \ + dp/dp_panel.o \ + dp/dp_link.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.odrivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +33
-0@@ -14,10 +14,216 @@#include <linux/clk.h> #include <linux/clk/clk-conf.h> #include <linux/err.h> +#include <linux/io.h> +#include <linux/regulator/consumer.h> #include <linux/delay.h> #include "dpu_io_util.h" +static struct resource *msm_dss_get_res_byname (struct platform_device *pdev, +unsigned int type, +const char *name) +{ +struct resource *res =NULL ; + + res =platform_get_resource_byname (pdev, type, name); +if (!res) +DEV_ERR ("%s: '%s' resource not found\n" , __func__, name); + +return res; +}/* msm_dss_get_res_byname */ + +int msm_dss_ioremap_byname (struct platform_device *pdev, +struct dss_io_data *io_data,const char *name) +{ +struct resource *res =NULL ; + +if (!pdev || !io_data) { +DEV_ERR ("%pS->%s: invalid input\n" , +__builtin_return_address (0 ), __func__); +return -EINVAL ; + } + + res =msm_dss_get_res_byname (pdev,IORESOURCE_MEM , name); +if (!res) { +DEV_ERR ("%pS->%s: '%s' msm_dss_get_res_byname failed\n" , +__builtin_return_address (0 ), __func__, name); +return -ENODEV ; + } +
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 63
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+ io_data->len = (u32 )resource_size (res); + io_data->base =ioremap (res->start, io_data->len); +if (!io_data->base) { +DEV_ERR ("%pS->%s: '%s' ioremap failed\n" , +__builtin_return_address (0 ), __func__, name); +return -EIO ; + } + +return 0 ; +}/* msm_dss_ioremap_byname */
We already have a function called msm_ioremap() that you can use instead of this. Bonus, it uses devm_ so you don't need to worry about unmap.
Quoted 6 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +6
-0+ +void msm_dss_iounmap (struct dss_io_data *io_data) +{ +if (!io_data) { +DEV_ERR ("%pS->%s: invalid input\n" , +__builtin_return_address (0 ), __func__);
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +9
-0+return ; + } + +if (io_data->base) { +iounmap (io_data->base); + io_data->base =NULL ; + } + io_data->len =0 ; +}/* msm_dss_iounmap */
if you use the function above you shouldn't need this one anymore.
Quoted 7 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +7
-0+int msm_dss_config_vreg (struct device *dev,struct dss_vreg *in_vreg, +int num_vreg,int config) +{ +int i =0 , rc =0 ; +struct dss_vreg *curr_vreg =NULL ; +enum dss_vreg_type type; +
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 96
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+if (!in_vreg || !num_vreg) +return rc; + +if (config) { +for (i =0 ; i < num_vreg; i++) { + curr_vreg = &in_vreg[i]; + curr_vreg->vreg =regulator_get (dev, + curr_vreg->vreg_name); + rc =PTR_RET (curr_vreg->vreg); +if (rc) {
This should be IS_ERR(rc)) and then use PTR_ERR() to take it apart if you need it for your return value or error message. PTR_RET() has been deprecated.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 99
Quoted 3 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +3
-0+DEV_ERR ("%pS->%s: %s get failed. rc=%d\n" , +__builtin_return_address (0 ), __func__, + curr_vreg->vreg_name, rc);
If you care about the stack here then consider using WARN instead of __builtin_return_address(0) and __func__. It will give you what you need in a standard way.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 111
Quoted 12 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +12
-0+ curr_vreg->vreg =NULL ; + goto vreg_get_fail; + } + type = (regulator_count_voltages (curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; +if (type ==DSS_REG_LDO ) { + rc =regulator_set_voltage ( + curr_vreg->vreg, + curr_vreg->min_voltage, + curr_vreg->max_voltage); +if (rc <0 ) { + DEV_ERR("%pS->%s: %s set vltg fail\n",
Same as above - use WARN if you can. Try not to use abbreviations in log messages - 'voltage' isn't much bigger and it is a lot more understandable especially for non native speakers.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 119
Quoted 8 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +8
-0+__builtin_return_address (0 ), + __func__, + curr_vreg->vreg_name); + goto vreg_set_voltage_fail; + } + } + } + }else {
This clause shares nothing with the rest of the function and proves there is no reason to not have separate functions for setting up and taking down instead of using the boolean flag.
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+for (i = num_vreg-1 ; i >=0 ; i--) { + curr_vreg = &in_vreg[i]; +if (curr_vreg->vreg) { + type = (regulator_count_voltages ( + curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; +if (type ==DSS_REG_LDO ) { +regulator_set_voltage (curr_vreg->vreg, +0 , curr_vreg->max_voltage); + }
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 139
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+regulator_put (curr_vreg->vreg); + curr_vreg->vreg =NULL ; + } + } + } +return 0 ; + +vreg_unconfig: +if (type ==DSS_REG_LDO ) +regulator_set_load (curr_vreg->vreg,0 );
Both paths above use regulator_set_voltage(), so I'm not sure if regulator_set_load() is what you intend here.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 150
Quoted 11 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +11
-0+ +vreg_set_voltage_fail: +regulator_put (curr_vreg->vreg); + curr_vreg->vreg =NULL ; + +vreg_get_fail: +for (i--; i >=0 ; i--) { + curr_vreg = &in_vreg[i]; + type = (regulator_count_voltages (curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; + goto vreg_unconfig;
Oh my - jumping back out of a loop with goto is not okay. This entire block is basically just trying to take the place of the takedown clause above so if you use a separate function to put away the regulators you can just call that instead.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 153
Quoted 3 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +3
-0+ } +return rc; +}/* msm_dss_config_vreg */
Maybe a nit, but we all know how to read C code. We don't need a comment to let us know when a bracket closes out a function.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 166
Quoted 13 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +13
-0+ +int msm_dss_enable_vreg (struct dss_vreg *in_vreg,int num_vreg,int enable) +{ +int i =0 , rc =0 ; +bool need_sleep; + +if (enable) { +for (i =0 ; i < num_vreg; i++) { + rc =PTR_RET (in_vreg[i].vreg); +if (rc) { +DEV_ERR ("%pS->%s: %s regulator error. rc=%d\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name, rc);
As above - use WARN if you can.
Quoted 16 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +16
-0+ goto vreg_set_opt_mode_fail; + } + need_sleep = !regulator_is_enabled (in_vreg[i].vreg); +if (in_vreg[i].pre_on_sleep && need_sleep) +usleep_range (in_vreg[i].pre_on_sleep *1000 , + in_vreg[i].pre_on_sleep *1000 ); + rc =regulator_set_load (in_vreg[i].vreg, + in_vreg[i].enable_load); +if (rc <0 ) { +DEV_ERR ("%pS->%s: %s set opt m fail\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name); + goto vreg_set_opt_mode_fail; + } + rc =regulator_enable (in_vreg[i].vreg); +if (in_vreg[i].post_on_sleep && need_sleep)
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 192
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+usleep_range (in_vreg[i].post_on_sleep *1000 , + in_vreg[i].post_on_sleep *1000 ); +if (rc <0 ) { +DEV_ERR ("%pS->%s: %s enable failed\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name); + goto disable_vreg; + } + } + }else {
Also as above - this entire clause can stand alone in its own function.
Quoted 20 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +20
-0+for (i = num_vreg-1 ; i >=0 ; i--) { +if (in_vreg[i].pre_off_sleep) +usleep_range (in_vreg[i].pre_off_sleep *1000 , + in_vreg[i].pre_off_sleep *1000 ); +regulator_set_load (in_vreg[i].vreg, + in_vreg[i].disable_load); +regulator_disable (in_vreg[i].vreg); +if (in_vreg[i].post_off_sleep) +usleep_range (in_vreg[i].post_off_sleep *1000 , + in_vreg[i].post_off_sleep *1000 ); + } + } +return rc; + +disable_vreg: +regulator_set_load (in_vreg[i].vreg, in_vreg[i].disable_load); + +vreg_set_opt_mode_fail: +for (i--; i >=0 ; i--) { +if (in_vreg[i].pre_off_sleep)
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +9
-0+usleep_range (in_vreg[i].pre_off_sleep *1000 , + in_vreg[i].pre_off_sleep *1000 ); +regulator_set_load (in_vreg[i].vreg, + in_vreg[i].disable_load); +regulator_disable (in_vreg[i].vreg); +if (in_vreg[i].post_off_sleep) +usleep_range (in_vreg[i].post_off_sleep *1000 , + in_vreg[i].post_off_sleep *1000 ); + }
This is essentially a recreation of the code above - you can just use the standalone function for teardown.
Quoted 20 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +4
-0+return rc; +}/* msm_dss_enable_vreg */ + +void msm_dss_put_clk (struct dss_clk *clk_arry,int num_clk) {int i;drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +1
-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)
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 24
Quoted 2 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +0
-0@@ -22,6 +23,39 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args)
This isn't part of this patch but I would love to see these guys turn into standard functions.
Quoted 68 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +43
-0+struct dss_io_data { +u32 len; +void __iomem *base; +}; + +/* +void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug); +u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug); +void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug); + +#define DSS_REG_W_ND(io, offset, val) dss_reg_w(io, offset, val, false) +#define DSS_REG_W(io, offset, val) dss_reg_w(io, offset, val, true) +#define DSS_REG_R_ND(io, offset) dss_reg_r(io, offset, false) +#define DSS_REG_R(io, offset) dss_reg_r(io, offset, true) +*/ +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,12 +76,22 @@ 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;struct dss_clk *clk_config; }; +int msm_dss_ioremap_byname (struct platform_device *pdev, +struct dss_io_data *io_data,const char *name); +void msm_dss_iounmap (struct dss_io_data *io_data); + +int msm_dss_config_vreg (struct device *dev,struct dss_vreg *in_vreg, +int num_vreg,int config); +int msm_dss_enable_vreg (struct dss_vreg *in_vreg,int num_vreg,int enable); +int msm_dss_get_clk (struct device *dev,struct dss_clk *clk_arry,int num_clk);void msm_dss_put_clk (struct dss_clk *clk_arry,int num_clk);int msm_dss_clk_set_rate (struct dss_clk *clk_arry,int num_clk);drivers/gpu/drm/msm/dp/dp_aux.c new file +3
-0@@ -0,0 +1,570 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_aux.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
Please use SPDX headers.
drivers/gpu/drm/msm/dp/dp_aux.c line 21
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +7
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h> + +#include "dp_aux.h" + +#define DP_AUX_ENUM_STR (x) #x
You should use this #define closer to where it is used.
drivers/gpu/drm/msm/dp/dp_aux.c line 25
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +4
-0+ +enum { +DP_AUX_DATA_INDEX_WRITE =BIT (31 ), +};
This enum of one is not needed - this could as easily be a #define or BIT(31) used inline.
Quoted 38 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +38
-0+struct dp_aux_private { +struct device *dev; +struct dp_aux dp_aux; +struct dp_catalog_aux *catalog; +struct dp_aux_cfg *cfg; + +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 :
drivers/gpu/drm/msm/dp/dp_aux.c line 74
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+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 ;
This isn't useful since it is only used oncex, and constant values like 128 can be safely used inline when it is needed.
drivers/gpu/drm/msm/dp/dp_aux.c line 87
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +13
-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) { +pr_err ("buf len error\n" );
I'm not sure if its possible, but if we could get to dev_err for these that would be fantastic (but don't go overboard if it is hard to get the dev pointer all the way down here).
That said, this error message should be more informative - it should at least say what the offending length is.
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +36
-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; + aux->catalog->write_data (aux->catalog); + } + + aux->catalog->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;
drivers/gpu/drm/msm/dp/dp_aux.c line 133
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ aux->catalog->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 ;
As above. Generally I don't like const variables on the stack and especially if they are as simple as this. This forces the reviewer to look at the line where it is used, and then back at the initialization to see what the value is.
drivers/gpu/drm/msm/dp/dp_aux.c line 139
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +6
-0+ +reinit_completion (&aux->comp); + + len =dp_aux_write (aux, msg); +if (len ==0 ) { +pr_err ("DP AUX write failed\n" );
There is only one way len can be zero and you already print an error message for it. You don't need another one.
drivers/gpu/drm/msm/dp/dp_aux.c line 143
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +4
-0+return -EINVAL ; + } + + timeout =wait_for_completion_timeout (&aux->comp, aux_timeout_ms);
This can easily be HZ/4 for the timeout
Quoted 89 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +89
-0+if (!timeout) { +pr_err ("aux %s timeout\n" , (aux->read ?"read" :"write" )); +return -ETIMEDOUT ; + } + +if (aux->aux_error_num ==DP_AUX_ERR_NONE ) { + ret = len; + }else { +pr_err_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; + + aux->catalog->clear_trans (aux->catalog, true); + + data =0 ; + data |=DP_AUX_DATA_INDEX_WRITE ;/* INDEX_WRITE */ + data |=BIT (0 );/* read */ + + aux->catalog->data = data; + aux->catalog->write_data (aux->catalog); + + dp = msg->buffer; + +/* discard first byte */ + data = aux->catalog->read_data (aux->catalog); + +for (i =0 ; i < len; i++) { + data = aux->catalog->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);
drivers/gpu/drm/msm/dp/dp_aux.c line 242
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+} + +static void dp_aux_isr (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +pr_err ("invalid input\n" ); +return ; + }
I'm not 100% if this is possible or not but consider replacing this with
if (WARN_ON(!dp_aux))
return;
To avoid the custom error message yet still handle the possibility of a NULL pointer. Of course, if it isn't possible then it should just be removed entirely.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +11
-0+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->catalog->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);
drivers/gpu/drm/msm/dp/dp_aux.c line 264
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+} + +static void dp_aux_reconfig (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +pr_err ("invalid input\n" ); +return ; + }
As above - WARN_ON can be useful here.
drivers/gpu/drm/msm/dp/dp_aux.c line 277
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +12
-0+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->catalog->update_aux_cfg (aux->catalog, + aux->cfg,PHY_AUX_CFG1 ); + aux->catalog->reset (aux->catalog); +} + +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 ;
Prefer if you didn't use const variables on the stack. They seem to be popular in this code so I won't point them out every time.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +15
-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; +}
<snip>
drivers/gpu/drm/msm/dp/dp_aux.c line 453
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +8
-0+static 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) { +pr_err ("invalid input\n" ); +return ; + }
Prefer to use WARN_ON here instead of a custom error message.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +7
-0+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + +dp_aux_reset_phy_config_indices (aux_cfg); + aux->catalog->setup (aux->catalog, aux_cfg); + aux->catalog->reset (aux->catalog); + aux->catalog->enable (aux->catalog, true); + aux->retry_cnt =0 ;
drivers/gpu/drm/msm/dp/dp_aux.c line 471
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+} + +static void dp_aux_deinit (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +pr_err ("invalid input\n" ); +return ; + }
Pefer WARN_ON.
drivers/gpu/drm/msm/dp/dp_aux.c line 484
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +12
-0+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->catalog->enable (aux->catalog, false); +} + +static int dp_aux_register (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; +int ret =0 ; + +if (!dp_aux) { +pr_err ("invalid input\n" );
Prefer WARN_ON.
drivers/gpu/drm/msm/dp/dp_aux.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+ ret = -EINVAL ;
You can just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_aux.c line 496
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +11
-0+ 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) { +pr_err ("%s: failed to register drm aux: %d\n" , __func__, ret);
Don't forget that your pr_fmt already prints __func__. You don't need to dobule it up.
drivers/gpu/drm/msm/dp/dp_aux.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+ goto exit;
This can be return ret;
drivers/gpu/drm/msm/dp/dp_aux.c line 500
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +3
-0+ } + dp_aux->drm_aux = &aux->drm_aux; +exit:
Label not needed.
drivers/gpu/drm/msm/dp/dp_aux.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+return ret;
This can be return 0;
drivers/gpu/drm/msm/dp/dp_aux.c line 511
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+} + +static void dp_aux_deregister (struct dp_aux *dp_aux) +{ +struct dp_aux_private *aux; + +if (!dp_aux) { +pr_err ("invalid input\n" ); +return ; + }
Prefer WARN_ON
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +6
-0+ 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)
drivers/gpu/drm/msm/dp/dp_aux.c line 528
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+{ +int rc =0 ; +struct dp_aux_private *aux; +struct dp_aux *dp_aux; + +if (!catalog || !aux_cfg) { +pr_err ("invalid input\n" ); + rc = -ENODEV ; + goto error; + }
This appears to only be called once with a known good value for catalog and aux_cfg, so this check does not appear to be needed. It also implies that the NULL checks (or WARN_ON) suggested for the functions above are not needed since all of them are to be called with known good pointers.
In fact, even if you keep this check (with a WARN_ON instead of a custom message of course) you can still remove the checks in dp_aux_isr, dp_aux_init, dp_aux_deinit, dp_aux_register, dp_aux_deregister and dp_aux_reconfig because you've already vetted the pointers.
drivers/gpu/drm/msm/dp/dp_aux.c line 531
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +2
-0+ aux =devm_kzalloc (dev,sizeof (*aux),GFP_KERNEL ); +if (!aux) {
This can just be return ERR_PTR(-ENOMEM);
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +14
-0+ rc = -ENOMEM ; + goto error; + } + +init_completion (&aux->comp); + aux->cmd_busy = false; +mutex_init (&aux->mutex); + + aux->dev = dev; + aux->catalog = catalog; + aux->cfg = aux_cfg; + dp_aux = &aux->dp_aux; + aux->retry_cnt =0 ; +
drivers/gpu/drm/msm/dp/dp_aux.c line 555
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +10
-0+ dp_aux->isr = dp_aux_isr; + dp_aux->init = dp_aux_init; + dp_aux->deinit = dp_aux_deinit; + dp_aux->drm_aux_register = dp_aux_register; + dp_aux->drm_aux_deregister = dp_aux_deregister; + dp_aux->reconfig = dp_aux_reconfig; + +return dp_aux; +error: +return ERR_PTR (rc);
This label should not be needed.
drivers/gpu/drm/msm/dp/dp_aux.c line 567
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);
Mutex_destroy isn't needed for memory that will no longer be used.
drivers/gpu/drm/msm/dp/dp_aux.c line 569
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +2
-0+ +devm_kfree (aux->dev, aux);
If you are using devm_ you don't need to call devm_kfree. If you don't expect to use the devm_ infrastructure to your advantage then just use kzalloc() in the init function and make sure you always free it but it seems to me you can just get rid of dp_aux_put() and be happy.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_aux.h new file +3
-0@@ -0,0 +1,44 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_aux.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_aux.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX header please.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_aux.h new file +31
-0+ +#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; +int (*drm_aux_register)(struct dp_aux *aux); +void (*drm_aux_deregister)(struct dp_aux *aux); +void (*isr)(struct dp_aux *aux); +void (*init)(struct dp_aux *aux,struct dp_aux_cfg *aux_cfg); +void (*deinit)(struct dp_aux *aux); +void (*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 +3
-0@@ -0,0 +1,1188 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_catalog.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX header please.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h>
drivers/gpu/drm/msm/dp/dp_catalog.c line 27
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+#include <drm/drm_dp_helper.h> + +#include "dp_catalog.h" +#include "dp_reg.h" + +#define DP_GET_MSB (x) (x >> 8) +#define DP_GET_LSB (x) (x & 0xff) + +#define dp_read (offset) readl_relaxed((offset)) +#define dp_write (offset, data) writel_relaxed((data), (offset))
These macros do not serve any purpose
drivers/gpu/drm/msm/dp/dp_catalog.c line 34
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +6
-0+#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 would work better as a static inline function - it wouldn't be as ugly and you get free typechecking.
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +39
-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_INTR_MASK1 (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_INTR_MASK2 (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 */ +}; + +/* audio related catalog functions */ +struct dp_catalog_private { +struct device *dev; +struct dp_io *io; + +u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX ]; +struct dp_catalog dp_catalog; +}; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 84
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+/* aux related catalog functions */ +static u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + goto end; + }
Not sure if this check is needed (I'm assuming I'll figure it as we go) but as above, replacing this with a handy
if (WARN_ON(!aux))
return 0;
Is preferred over a custom log message
drivers/gpu/drm/msm/dp/dp_catalog.c line 84
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+ +dp_catalog_get_priv (aux);
Function like macros that set an implicit variable are so very dangerous - please use a static inline as I suggsted above.
drivers/gpu/drm/msm/dp/dp_catalog.c line 90
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ base = catalog->io->dp_aux.base; + +return dp_read (base +DP_AUX_DATA ); +end:
This shouldn't be needed if you return immediately above.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+return 0 ; +} + +static int dp_catalog_aux_write_data (struct dp_catalog_aux *aux)
drivers/gpu/drm/msm/dp/dp_catalog.c line 104
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+{ +int rc =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + }
Same as above
drivers/gpu/drm/msm/dp/dp_catalog.c line 111
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +6
-0+dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +dp_write (base +DP_AUX_DATA , aux->data); +end: +return rc;
Same as above
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +11
-0+} + +static int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux) +{ +int rc =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ;
drivers/gpu/drm/msm/dp/dp_catalog.c line 132
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ goto end; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +dp_write (base +DP_AUX_TRANS_CTRL , aux->data); +end: +return rc; +}
dp_catalog_aux_write_data and dp_catalog_aux_write_trans are basically the same function except the register offset. There must be some conslidation that can be done.
drivers/gpu/drm/msm/dp/dp_catalog.c line 145
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+static int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read) +{ +int rc =0 ; +u32 data =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + }
Use WARN_ON() here and throughout for all these dp catalog function hooks.
Quoted 41 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +41
-0+dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +if (read) { + data =dp_read (base +DP_AUX_TRANS_CTRL ); + data &= ~BIT (9 ); +dp_write (base +DP_AUX_TRANS_CTRL , data); + }else { +dp_write (base +DP_AUX_TRANS_CTRL ,0 ); + } +end: +return rc; +} + +static void dp_catalog_aux_reset (struct dp_catalog_aux *aux) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + + aux_ctrl =dp_read (base +DP_AUX_CTRL ); + + aux_ctrl |=BIT (1 ); +dp_write (base +DP_AUX_CTRL , aux_ctrl); +usleep_range (1000 ,1010 );/* h/w recommended delay */ + + aux_ctrl &= ~BIT (1 ); +dp_write (base +DP_AUX_CTRL , aux_ctrl); +wmb (); +} + +static void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable) +{
drivers/gpu/drm/msm/dp/dp_catalog.c line 198
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+u32 aux_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); +return ; + } +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base;
Even at the very worse a common function to derive the base would save lines of code given how much it gets used.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +13
-0+ + aux_ctrl =dp_read (base +DP_AUX_CTRL ); + +if (enable) { +dp_write (base +DP_TIMEOUT_COUNT ,0xffff ); +dp_write (base +DP_AUX_LIMITS ,0xffff ); + aux_ctrl |=BIT (0 ); + }else { + aux_ctrl &= ~BIT (0 ); + } + +dp_write (base +DP_AUX_CTRL , aux_ctrl); +}
<snip>
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +39
-0+static void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +dp_write (base +DP_STATE_CTRL , state); +} + +static void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 cfg) +{ +struct dp_catalog_private *catalog; +void __iomem *link_base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + link_base = catalog->io->dp_link.base; + +pr_debug ("DP_CONFIGURATION_CTRL=0x%x\n" , cfg); + +dp_write (link_base +DP_CONFIGURATION_CTRL , cfg); +} + +static void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 358
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +dp_write (base +DP_LOGICAL2PHYSICAL_LANE_MAPPING ,0xe4 ); +}
Consolidation of dp_link write could also be done among these three.
Quoted 55 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +55
-0+static void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +u32 mainlink_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +if (enable) { +dp_write (base +DP_MAINLINK_CTRL ,0x02000000 ); +wmb ();/* make sure mainlink is turned off before reset */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000002 ); +wmb ();/* make sure mainlink entered reset */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000000 ); +wmb ();/* make sure mainlink reset done */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000001 ); +wmb ();/* make sure mainlink turned on */ + }else { + mainlink_ctrl =dp_read (base +DP_MAINLINK_CTRL ); + mainlink_ctrl &= ~BIT (0 ); +dp_write (base +DP_MAINLINK_CTRL , mainlink_ctrl); + } +} + +static void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl, +u32 cc,u32 tb) +{ +u32 misc_val; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + + misc_val =dp_read (base +DP_MISC1_MISC0 ); + misc_val |= cc; + misc_val |= (tb <<5 ); + misc_val |=BIT (0 );/* Configure clock to synchronous mode */ + +pr_debug ("misc settings = 0x%x\n" , misc_val); +dp_write (base +DP_MISC1_MISC0 , misc_val); +} +
drivers/gpu/drm/msm/dp/dp_catalog.c line 424
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+static 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 ;
Put these constants inline rather than using a const on the stack.
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+struct dp_catalog_private *catalog; +void __iomem *base_cc, *base_ctrl; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); +if (fixed_nvid) { +pr_debug ("use fixed NVID=0x%x\n" , nvid_fixed); + nvid = nvid_fixed;
drivers/gpu/drm/msm/dp/dp_catalog.c line 445
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +9
-0+ +pr_debug ("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;
You set a const variable, then you ste a normal variable and you only use it once - you could cut out all the middlemen by just hardcoding 0x8000 here.
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +31
-0+ 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 { + base_cc = catalog->io->dp_cc_io.base; + + pixel_m =dp_read (base_cc +MMSS_DP_PIXEL_M ); + pixel_n =dp_read (base_cc +MMSS_DP_PIXEL_N ); +pr_debug ("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 ); + +pr_debug ("rate = %d\n" , rate); + +if (link_rate_hbr2 == rate) + nvid *=2 ; + +if (link_rate_hbr3 == rate) + nvid *=3 ; + } + + base_ctrl = catalog->io->dp_link.base; +pr_debug ("mvid=0x%x, nvid=0x%x\n" , mvid, nvid); +dp_write (base_ctrl +DP_SOFTWARE_MVID , mvid); +dp_write (base_ctrl +DP_SOFTWARE_NVID , nvid); +}
<snip>
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +7
-0+static void dp_catalog_audio_get_header (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX ]; +void __iomem *base; +enum dp_catalog_audio_sdp_type sdp; +enum dp_catalog_audio_header_type header;
drivers/gpu/drm/msm/dp/dp_catalog.c line 1006
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +if (!audio) +return ; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + sdp_map = catalog->audio_map; + sdp = audio->sdp_type; + header = audio->sdp_header;
I'm assuming that whoever sets up the catalog in the first place is verifying that sdp and header are both in bounds for the audio_map array?
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+ audio->data =dp_read (base + sdp_map[sdp][header]); +} + +static void dp_catalog_audio_set_header (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX ]; +void __iomem *base; +enum dp_catalog_audio_sdp_type sdp; +enum dp_catalog_audio_header_type header; +u32 data; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 1029
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!audio) +return ; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + sdp_map = catalog->audio_map; + sdp = audio->sdp_type; + header = audio->sdp_header; + data = audio->data;
Same question.
Quoted 115 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +115
-0+ +dp_write (base + sdp_map[sdp][header], data); +} + +static void dp_catalog_audio_config_acr (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +u32 acr_ctrl, select; + +dp_catalog_get_priv (audio); + + select = audio->data; + base = catalog->io->dp_link.base; + + acr_ctrl = select <<4 |BIT (31 ) |BIT (8 ) |BIT (14 ); + +pr_debug ("select = 0x%x, acr_ctrl = 0x%x\n" , select, acr_ctrl); + +dp_write (base +MMSS_DP_AUDIO_ACR_CTRL , acr_ctrl); +} + +static void dp_catalog_audio_safe_to_exit_level (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +u32 mainlink_levels, safe_to_exit_level; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + safe_to_exit_level = audio->data; + + mainlink_levels =dp_read (base +DP_MAINLINK_LEVELS ); + mainlink_levels &=0xFE0 ; + mainlink_levels |= safe_to_exit_level; + +pr_debug ("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n" , + mainlink_levels, safe_to_exit_level); + +dp_write (base +DP_MAINLINK_LEVELS , mainlink_levels); +} + +static void dp_catalog_audio_enable (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +bool enable; +u32 audio_ctrl; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + enable = !!audio->data; + + audio_ctrl =dp_read (base +MMSS_DP_AUDIO_CFG ); + +if (enable) + audio_ctrl |=BIT (0 ); +else + audio_ctrl &= ~BIT (0 ); + +pr_debug ("dp_audio_cfg = 0x%x\n" , audio_ctrl); +dp_write (base +MMSS_DP_AUDIO_CFG , audio_ctrl); + +/* make sure audio engine is disabled */ +wmb (); +} + +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; +struct dp_catalog_aux aux = { + .read_data = dp_catalog_aux_read_data, + .write_data = dp_catalog_aux_write_data, + .write_trans = dp_catalog_aux_write_trans, + .clear_trans = dp_catalog_aux_clear_trans, + .reset = dp_catalog_aux_reset, + .update_aux_cfg = dp_catalog_aux_update_cfg, + .enable = dp_catalog_aux_enable, + .setup = dp_catalog_aux_setup, + .get_irq = dp_catalog_aux_get_irq, + }; +struct dp_catalog_ctrl ctrl = { + .state_ctrl = dp_catalog_ctrl_state_ctrl, + .config_ctrl = dp_catalog_ctrl_config_ctrl, + .lane_mapping = dp_catalog_ctrl_lane_mapping, + .mainlink_ctrl = dp_catalog_ctrl_mainlink_ctrl, + .config_misc = dp_catalog_ctrl_config_misc, + .config_msa = dp_catalog_ctrl_config_msa, + .set_pattern = dp_catalog_ctrl_set_pattern, + .reset = dp_catalog_ctrl_reset, + .usb_reset = dp_catalog_ctrl_usb_reset, + .mainlink_ready = dp_catalog_ctrl_mainlink_ready, + .enable_irq = dp_catalog_ctrl_enable_irq, + .hpd_config = dp_catalog_ctrl_hpd_config, + .phy_reset = dp_catalog_ctrl_phy_reset, + .phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg, + .update_vx_px = dp_catalog_ctrl_update_vx_px, + .get_interrupt = dp_catalog_ctrl_get_interrupt, + .update_transfer_unit = dp_catalog_ctrl_update_transfer_unit, + .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern, + .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern, + }; +struct dp_catalog_audio audio = { + .init = dp_catalog_audio_init, + .config_acr = dp_catalog_audio_config_acr, + .enable = dp_catalog_audio_enable, + .config_sdp = dp_catalog_audio_config_sdp, + .set_header = dp_catalog_audio_set_header, + .get_header = dp_catalog_audio_get_header, + .safe_to_exit_level = dp_catalog_audio_safe_to_exit_level, + };
drivers/gpu/drm/msm/dp/dp_catalog.c line 1154
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_panel panel = { + .timing_cfg = dp_catalog_panel_timing_cfg, + .tpg_config = dp_catalog_panel_tpg_cfg, + }; + +if (!io) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
It doesn't appear that io can be NULL here.
drivers/gpu/drm/msm/dp/dp_catalog.c line 1157
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +3
-0+ + catalog =devm_kzalloc (dev,sizeof (*catalog),GFP_KERNEL ); +if (!catalog) {
You can just return ERR_PTR(-ENOMEM) here
drivers/gpu/drm/msm/dp/dp_catalog.c line 1170
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +13
-0+ rc = -ENOMEM ; + goto error; + } + + catalog->dev = dev; + catalog->io = io; + + dp_catalog = &catalog->dp_catalog; + + dp_catalog->aux = aux; + dp_catalog->ctrl = ctrl; + dp_catalog->audio = audio; + dp_catalog->panel = panel;
I'll use this as an example because it is the shortest, but it should apply to all these members. You can set the value of dp_catalog->panel directly without an intermediate variable:
dp_catalog->panel = {
.timing_cfg = dp_catalog_panel_timing_cfg, .tpg_config = dp_catalog_panel_tpg_cfg,
};
Its a small change but it makes it easier to understand what is going on in this function.
drivers/gpu/drm/msm/dp/dp_catalog.c line 1174
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ +return dp_catalog; +error: +return ERR_PTR (rc);
This shouldn't be needed anymore.
drivers/gpu/drm/msm/dp/dp_catalog.c line 1187
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);
You don't need to devm_kfree managed memory - just let it go.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_catalog.h new file +3
-0@@ -0,0 +1,144 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_catalog.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 139 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +130
-0+#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; + +u32 (*read_data)(struct dp_catalog_aux *aux); +int (*write_data)(struct dp_catalog_aux *aux); +int (*write_trans)(struct dp_catalog_aux *aux); +int (*clear_trans)(struct dp_catalog_aux *aux,bool read); +void (*reset)(struct dp_catalog_aux *aux); +void (*enable)(struct dp_catalog_aux *aux,bool enable); +void (*update_aux_cfg)(struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg,enum dp_phy_aux_config_type type); +void (*setup)(struct dp_catalog_aux *aux, +struct dp_aux_cfg *aux_cfg); +void (*get_irq)(struct dp_catalog_aux *aux,bool cmd_busy); +}; + +struct dp_catalog_ctrl { +u32 dp_tu; +u32 valid_boundary; +u32 valid_boundary2; +u32 isr; + +void (*state_ctrl)(struct dp_catalog_ctrl *ctrl,u32 state); +void (*config_ctrl)(struct dp_catalog_ctrl *ctrl,u32 config); +void (*lane_mapping)(struct dp_catalog_ctrl *ctrl); +void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl,bool enable); +void (*config_misc)(struct dp_catalog_ctrl *ctrl,u32 cc,u32 tb); +void (*config_msa)(struct dp_catalog_ctrl *ctrl,u32 rate, +u32 stream_rate_khz,bool fixed_nvid); +void (*set_pattern)(struct dp_catalog_ctrl *ctrl,u32 pattern); +void (*reset)(struct dp_catalog_ctrl *ctrl); +void (*usb_reset)(struct dp_catalog_ctrl *ctrl,bool flip); +bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl); +void (*enable_irq)(struct dp_catalog_ctrl *ctrl,bool enable); +void (*hpd_config)(struct dp_catalog_ctrl *ctrl,bool enable); +void (*phy_reset)(struct dp_catalog_ctrl *ctrl); +void (*phy_lane_cfg)(struct dp_catalog_ctrl *ctrl,bool flipped, +u8 lane_cnt); +void (*update_vx_px)(struct dp_catalog_ctrl *ctrl,u8 v_level, +u8 p_level); +void (*get_interrupt)(struct dp_catalog_ctrl *ctrl); +void (*update_transfer_unit)(struct dp_catalog_ctrl *ctrl); +void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl, +u32 pattern); +u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl); +}; + +enum dp_catalog_audio_sdp_type { +DP_AUDIO_SDP_STREAM , +DP_AUDIO_SDP_TIMESTAMP , +DP_AUDIO_SDP_INFOFRAME , +DP_AUDIO_SDP_COPYMANAGEMENT , +DP_AUDIO_SDP_ISRC , +DP_AUDIO_SDP_MAX , +}; + +enum dp_catalog_audio_header_type { +DP_AUDIO_SDP_HEADER_1 , +DP_AUDIO_SDP_HEADER_2 , +DP_AUDIO_SDP_HEADER_3 , +DP_AUDIO_SDP_HEADER_MAX , +}; + +struct dp_catalog_audio { +enum dp_catalog_audio_sdp_type sdp_type; +enum dp_catalog_audio_header_type sdp_header; +u32 data; + +void (*init)(struct dp_catalog_audio *audio); +void (*enable)(struct dp_catalog_audio *audio); +void (*config_acr)(struct dp_catalog_audio *audio); +void (*config_sdp)(struct dp_catalog_audio *audio); +void (*set_header)(struct dp_catalog_audio *audio); +void (*get_header)(struct dp_catalog_audio *audio); +void (*safe_to_exit_level)(struct dp_catalog_audio *audio); +}; + +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; + +int (*timing_cfg)(struct dp_catalog_panel *panel); +void (*tpg_config)(struct dp_catalog_panel *panel,bool enable); +}; + +struct dp_catalog { +struct dp_catalog_aux aux; +struct dp_catalog_ctrl ctrl; +struct dp_catalog_audio audio; +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 +3
-0@@ -0,0 +1,1475 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_ctrl.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 82 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +82
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/types.h> +#include <linux/completion.h> +#include <linux/delay.h> + +#include "dp_ctrl.h" + +#define DP_KHZ_TO_HZ 1000 + +#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) +#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) + +/* dp state ctrl */ +#define ST_TRAIN_PATTERN_1 BIT(0) +#define ST_TRAIN_PATTERN_2 BIT(1) +#define ST_TRAIN_PATTERN_3 BIT(2) +#define ST_TRAIN_PATTERN_4 BIT(3) +#define ST_SYMBOL_ERR_RATE_MEASUREMENT BIT(4) +#define ST_PRBS7 BIT(5) +#define ST_CUSTOM_80_BIT_PATTERN BIT(6) +#define ST_SEND_VIDEO BIT(7) +#define ST_PUSH_IDLE BIT(8) + +#define MR_LINK_TRAINING1 0x8 +#define MR_LINK_SYMBOL_ERM 0x80 +#define MR_LINK_PRBS7 0x100 +#define MR_LINK_CUSTOM80 0x200 + +struct dp_vc_tu_mapping_table { +u32 vic; +u8 lanes; +u8 lrate;/* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */ +u8 bpp; +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 completion video_comp; + +bool orientation; +atomic_t aborted; + +u32 pixel_rate; +u32 vic; +}; + +enum notification_status { +NOTIFY_UNKNOWN , +NOTIFY_CONNECT , +NOTIFY_DISCONNECT , +NOTIFY_CONNECT_IRQ_HPD , +NOTIFY_DISCONNECT_IRQ_HPD , +}; + +static void dp_ctrl_idle_patterns_sent (struct dp_ctrl_private *ctrl) +{ +pr_debug ("idle_patterns_sent\n" ); +complete (&ctrl->idle_comp); +} + +static void dp_ctrl_video_ready (struct dp_ctrl_private *ctrl) +{ +pr_debug ("dp_video_ready\n" ); +complete (&ctrl->video_comp);
drivers/gpu/drm/msm/dp/dp_ctrl.c line 106
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+} + +static void dp_ctrl_abort (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + +if (!dp_ctrl) { +pr_err ("Invalid input data\n" ); +return ; + }
Common theme - please try to use WARN_ON instead of a custom error message.
Quoted 114 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +114
-0+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +atomic_set (&ctrl->aborted,1 ); +} + +static void dp_ctrl_state_ctrl (struct dp_ctrl_private *ctrl,u32 state) +{ + ctrl->catalog->state_ctrl (ctrl->catalog, state); +} + +static void dp_ctrl_push_idle (struct dp_ctrl *dp_ctrl) +{ +int const idle_pattern_completion_timeout_ms =3 *HZ /100 ; +struct dp_ctrl_private *ctrl; + +if (!dp_ctrl) { +pr_err ("Invalid input data\n" ); +return ; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +reinit_completion (&ctrl->idle_comp); +dp_ctrl_state_ctrl (ctrl,ST_PUSH_IDLE ); + +if (!wait_for_completion_timeout (&ctrl->idle_comp, + idle_pattern_completion_timeout_ms)) +pr_warn ("PUSH_IDLE pattern timedout\n" ); + +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; + + config |= (2 <<13 );/* Default-> LSCLK DIV: 1/4 LCLK */ + config |= (0 <<11 );/* RGB */ + +/* Scrambler reset enable */ +if (dpcd[DP_EDP_CONFIGURATION_CAP ] &DP_ALTERNATE_SCRAMBLER_RESET_CAP ) + config |= (1 <<10 ); + + tbd = ctrl->link->get_test_bits_depth (ctrl->link, + ctrl->panel->pinfo.bpp); + +if (tbd ==DP_TEST_BIT_DEPTH_UNKNOWN ) + tbd =DP_TEST_BIT_DEPTH_8 ; + + config |= tbd <<8 ; + +/* Num of Lanes */ + config |= ((ctrl->link->link_params.lane_count -1 ) <<4 ); + +if (drm_dp_enhanced_frame_cap (dpcd)) + config |=0x40 ; + + config |=0x04 ;/* progressive video */ + + config |=0x03 ;/* sycn clock & static Mvid */ + + ctrl->catalog->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; + + ctrl->catalog->lane_mapping (ctrl->catalog); + ctrl->catalog->mainlink_ctrl (ctrl->catalog, true); + +dp_ctrl_config_ctrl (ctrl); + + tb = ctrl->link->get_test_bits_depth (ctrl->link, + ctrl->panel->pinfo.bpp); + cc = ctrl->link->get_colorimetry_config (ctrl->link); + ctrl->catalog->config_misc (ctrl->catalog, cc, tb); + ctrl->panel->timing_cfg (ctrl->panel); +} + +static void dp_ctrl_get_extra_req_bytes (u64 result_valid, +int valid_bdary_link, +u64 value1,u64 value2, +bool *negative,u64 *result, +u64 compare) +{ + *negative = false; +if (result_valid >= compare) { +if (valid_bdary_link + >= compare) + *result = value1 + value2; +else { +if (value1 < value2) + *negative = true; + *result = (value1 >= value2) ? + (value1 - value2) : (value2 - value1); + } + }else { +if (valid_bdary_link + >= compare) { +if (value1 >= value2) + *negative = true; + *result = (value1 >= value2) ? + (value1 - value2) : (value2 - value1); + }else { + *result = value1 + value2;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 231
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ *negative = true; + } + } +} + +static u64 roundup_u64 (u64 x,u64 y) +{ + x += (y -1 ); +return (div64_ul (x, y) * y); +}
Does roundup() not work for u64?
drivers/gpu/drm/msm/dp/dp_ctrl.c line 239
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0+ +static u64 rounddown_u64 (u64 x,u64 y) +{ +u64 rem; + +div64_u64_rem (x, y, &rem); +return (x - rem); +}
Same question
<snip>
drivers/gpu/drm/msm/dp/dp_ctrl.c line 729
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0+static int dp_ctrl_wait4video_ready (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + + ret =wait_for_completion_timeout (&ctrl->video_comp,HZ /2 ); +if (ret <=0 ) { +pr_err ("Link Train timedout\n" ); + ret = -EINVAL ;
On timeout it would be helpful to return -ETIMEDOUT but if ret < 0 you should return the value that you got from wait_for_completion_timeout in case the caller wants to know about interrupted calls.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +4
-0+ } + +return ret; +}
<snip>
Quoted 18 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +18
-0+static int dp_ctrl_link_train (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; +u8 encoding =0x1 ; +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); + + link_info.num_lanes = ctrl->link->link_params.lane_count; + link_info.rate =drm_dp_bw_code_to_link_rate ( + ctrl->link->link_params.bw_code); + link_info.capabilities = ctrl->panel->link_info.capabilities; + +drm_dp_link_configure (ctrl->aux->drm_aux, &link_info); + drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
drivers/gpu/drm/msm/dp/dp_ctrl.c line 967
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ &encoding, 1); + + ret =dp_ctrl_link_train_1 (ctrl); +if (ret) { +pr_err ("link training #1 failed\n" ); + goto end; + } + +/* print success info as this is a result of user initiated action */ +pr_info ("link training #1 successful\n" );
These seem like maybe they belong at pr_debug() level - they are interested while getting going but probably not in a commercial setting.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 976
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0+ ret =dp_ctrl_link_training_2 (ctrl); +if (ret) { +pr_err ("link training #2 failed\n" ); + goto end; + } + +/* print success info as this is a result of user initiated action */ +pr_info ("link training #2 successful\n" );
Same.
Quoted 61 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +61
-0+ +end: +dp_ctrl_state_ctrl (ctrl,0 ); +/* Make sure to clear the current pattern before starting a new one */ +wmb (); + +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 ; + + ctrl->catalog->mainlink_ctrl (ctrl->catalog, true); + + ret = ctrl->link->psm_config (ctrl->link, + &ctrl->panel->link_info, false); +if (ret) + goto end; + +if (ctrl->link->sink_request &DP_TEST_LINK_PHY_TEST_PATTERN ) + goto end; + +if (!train) + goto send_video; + +/* +* As part of previous calls, DP controller state might have +* transitioned to PUSH_IDLE. In order to start transmitting a link +* training pattern, we have to first to a DP software reset. +*/ + ctrl->catalog->reset (ctrl->catalog); + + ret =dp_ctrl_link_train (ctrl); +if (ret) + goto end; + +send_video: +/* +* Set up transfer unit values and set controller state to send +* video. +*/ +dp_ctrl_setup_tr_unit (ctrl); + ctrl->catalog->state_ctrl (ctrl->catalog,ST_SEND_VIDEO ); + +dp_ctrl_wait4video_ready (ctrl); + mainlink_ready = ctrl->catalog->mainlink_ready (ctrl->catalog); +pr_debug ("mainlink %s\n" , mainlink_ready ?"READY" :"NOT READY" ); +end: +return ret; +} + +static void dp_ctrl_set_clock_rate (struct dp_ctrl_private *ctrl, +char *name,u32 rate) +{ +u32 num = ctrl->parser->mp[DP_CTRL_PM ].num_clk; +struct dss_clk *cfg = ctrl->parser->mp[DP_CTRL_PM ].clk_config; + +while (num &&strcmp (cfg->clk_name, name)) {
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1047
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ num--; + cfg++; + } + +pr_debug ("setting rate=%d on clk=%s\n" , rate, name); + +if (num) + cfg->rate = rate; +else +pr_err ("%s clock could not be set with rate %d\n" , name, rate);
More accurately, the clock name isn't found in the list.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0+} + +static int dp_ctrl_enable_mainlink_clocks (struct dp_ctrl_private *ctrl) +{ +int ret =0 ; + + ctrl->power->set_pixel_clk_parent (ctrl->power);
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1064
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ +dp_ctrl_set_clock_rate (ctrl,"ctrl_link_clk" , +drm_dp_bw_code_to_link_rate (ctrl->link->link_params.bw_code)); + +dp_ctrl_set_clock_rate (ctrl,"ctrl_pixel_clk" , ctrl->pixel_rate); + + ret = ctrl->power->clk_enable (ctrl->power,DP_CTRL_PM , true); +if (ret) { +pr_err ("Unabled to start link clocks\n" ); + ret = -EINVAL ;
You should use the return value from ctrl->power->clk_enable instead of reclassifying it.
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +9
-0+ } + +return ret; +} + +static int dp_ctrl_disable_mainlink_clocks (struct dp_ctrl_private *ctrl) +{ +return ctrl->power->clk_enable (ctrl->power,DP_CTRL_PM , false); +}
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1083
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ +static int dp_ctrl_host_init (struct dp_ctrl *dp_ctrl,bool flip) +{ +struct dp_ctrl_private *ctrl; +struct dp_catalog_ctrl *catalog; + +if (!dp_ctrl) { +pr_err ("Invalid input data\n" ); +return -EINVAL ; + }
Use the WARN_ON to avoid the custom error message. Throughout.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +11
-0+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + ctrl->orientation = flip; + catalog = ctrl->catalog; + + catalog->usb_reset (ctrl->catalog, flip); + catalog->phy_reset (ctrl->catalog); + catalog->enable_irq (ctrl->catalog, true); + +return 0 ; +}
<snip>
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1427
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +12
-0+struct dp_ctrl *dp_ctrl_get (struct dp_ctrl_in *in) +{ +int rc =0 ; +struct dp_ctrl_private *ctrl; +struct dp_ctrl *dp_ctrl; + +if (!in->dev || !in->panel || !in->aux || + !in->link || !in->catalog) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
None of these will be NULL from the single call to this function.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1430
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +2
-0+ ctrl =devm_kzalloc (in->dev,sizeof (*ctrl),GFP_KERNEL ); +if (!ctrl) {
You can jsut return ERR_PTR(-ENOMEM) here
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +22
-0+ rc = -ENOMEM ; + goto error; + } + +init_completion (&ctrl->idle_comp); +init_completion (&ctrl->video_comp); + +/* in parameters */ + ctrl->parser = in->parser; + ctrl->panel = in->panel; + ctrl->power = in->power; + ctrl->aux = in->aux; + ctrl->link = in->link; + ctrl->catalog = in->catalog; + ctrl->dev = in->dev; + + dp_ctrl = &ctrl->dp_ctrl; + +/* out parameters */ + dp_ctrl->init = dp_ctrl_host_init; + dp_ctrl->deinit = dp_ctrl_host_deinit; + dp_ctrl->on = dp_ctrl_on;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1462
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ dp_ctrl->off = dp_ctrl_off; + dp_ctrl->push_idle = dp_ctrl_push_idle; + dp_ctrl->abort = dp_ctrl_abort; + dp_ctrl->isr = dp_ctrl_isr; + dp_ctrl->reset = dp_ctrl_reset; + dp_ctrl->handle_sink_request = dp_ctrl_handle_sink_request; + +return dp_ctrl; +error: +return ERR_PTR (rc);
This shouldn't be needed.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 1474
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +12
-0+} + +void dp_ctrl_put (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + +if (!dp_ctrl) +return ; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +devm_kfree (ctrl->dev, ctrl);
Not needed if you are using devm_
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_ctrl.h new file +3
-0@@ -0,0 +1,50 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_ctrl.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +26
-0+#ifndef _DP_CTRL_H_ +#define _DP_CTRL_H_ + +#include "dp_aux.h" +#include "dp_panel.h" +#include "dp_link.h" +#include "dp_parser.h" +#include "dp_power.h" +#include "dp_catalog.h" + +struct dp_ctrl { + int (*init)(struct dp_ctrl *dp_ctrl, bool flip); + void (*deinit)(struct dp_ctrl *dp_ctrl); + int (*on)(struct dp_ctrl *dp_ctrl); + void (*off)(struct dp_ctrl *dp_ctrl); + void (*reset)(struct dp_ctrl *dp_ctrl); + void (*push_idle)(struct dp_ctrl *dp_ctrl); + void (*abort)(struct dp_ctrl *dp_ctrl); + void (*isr)(struct dp_ctrl *dp_ctrl); + void (*handle_sink_request)(struct dp_ctrl *dp_ctrl); +}; + +struct dp_ctrl_in { + struct device *dev; + struct dp_panel *panel; + struct dp_aux *aux;
drivers/gpu/drm/msm/dp/dp_ctrl.h line 50
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +10
-0+struct dp_link *link; +struct dp_parser *parser; +struct dp_power *power; + struct dp_catalog_ctrl *catalog; +}; + +struct dp_ctrl *dp_ctrl_get (struct dp_ctrl_in *in); +void dp_ctrl_put (struct dp_ctrl *dp_ctrl); + +#endif /* _DP_CTRL_H_ */
This seems like a good ending spot for now. I'll do the rest later.
Jordan
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
Re: [DPU PATCH 2/3] drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveQuoted 55 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.Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 15 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 ++++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 +++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1475 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 ++ drivers/gpu/drm/msm/dp/dp_display.c | 977 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 55 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 ++++++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 ++++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 +++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 ++++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 205 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 599 +++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 57 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 ++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 30 files changed, 10887 insertions(+), 1 deletion(-) 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_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.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
Quoted 8 lines
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
<snip to dp_debug.c>
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +3
-0@@ -0,0 +1,507 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_debug.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +27
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/debugfs.h> +#include <drm/drm_connector.h> + +#include "dp_parser.h" +#include "dp_power.h" +#include "dp_catalog.h" +#include "dp_aux.h" +#include "dp_ctrl.h" +#include "dp_debug.h" +#include "dp_display.h" + +#define DEBUG_NAME "drm_dp" + +struct dp_debug_private { +struct dentry *root; + +struct dp_usbpd *usbpd; +struct dp_link *link; +struct dp_panel *panel; +struct drm_connector **connector; +struct device *dev; + +struct dp_debug dp_debug; +}; +
drivers/gpu/drm/msm/dp/dp_debug.c line 51
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+static ssize_t dp_debug_write_hpd (struct file *file, +const char __user *user_buff,size_t count,loff_t *ppos) +{ +struct dp_debug_private *debug = file->private_data; +char buf[SZ_8 ]; +size_t len =0 ; +int hpd; + +if (!debug) +return -ENODEV ;
debug will not be NULL here.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +4
-0+ +if (*ppos) +return 0 ; +
drivers/gpu/drm/msm/dp/dp_debug.c line 65
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+/* Leave room for termination char */ + len =min_t (size_t, count,SZ_8 -1 ); +if (copy_from_user (buf, user_buff, len)) + goto end; + + buf[len] ='\0' ; + +if (kstrtoint (buf,10 , &hpd) !=0 ) + goto end; +
All of this can be replaced by kstrtoint_from_user().
drivers/gpu/drm/msm/dp/dp_debug.c line 70
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+if (debug->usbpd && debug->usbpd->connect) + debug->usbpd->connect (debug->usbpd, hpd); + +end: +return -len;
On error you should return a real error code or the number of bytes consumed (count) on success.
drivers/gpu/drm/msm/dp/dp_debug.c line 77
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +7
-0+} + +static ssize_t dp_debug_write_edid_modes (struct file *file, +const char __user *user_buff,size_t count,loff_t *ppos) +{ +struct dp_debug_private *debug = file->private_data; +char buf[SZ_32 ];
Just use 32.
drivers/gpu/drm/msm/dp/dp_debug.c line 82
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+size_t len =0 ; +int hdisplay =0 , vdisplay =0 , vrefresh =0 ; + +if (!debug) +return -ENODEV ;
Debug can't be NULL here.
drivers/gpu/drm/msm/dp/dp_debug.c line 88
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+if (*ppos) + goto end; + +/* Leave room for termination char */ + len =min_t (size_t, count,SZ_32 -1 );
instead of SZ_23 - 1, use sizeof(buf) - 1
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +11
-0+if (copy_from_user (buf, user_buff, len)) + goto clear; + + buf[len] ='\0' ; + +if (sscanf (buf,"%d %d %d" , &hdisplay, &vdisplay, &vrefresh) !=3 ) + goto clear; + +if (!hdisplay || !vdisplay || !vrefresh) + goto clear; +
drivers/gpu/drm/msm/dp/dp_debug.c line 109
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+ debug->dp_debug.debug_en = true; + debug->dp_debug.hdisplay = hdisplay; + debug->dp_debug.vdisplay = vdisplay; + debug->dp_debug.vrefresh = vrefresh; + goto end; +clear: +pr_debug ("clearing debug modes\n" ); + debug->dp_debug.debug_en = false; +end: +return len;
This should be 'count'
drivers/gpu/drm/msm/dp/dp_debug.c line 120
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +11
-0+} + +static ssize_t dp_debug_read_connected (struct file *file, +char __user *user_buff,size_t count,loff_t *ppos) +{ +struct dp_debug_private *debug = file->private_data; +char buf[SZ_8 ]; +u32 len =0 ; + +if (!debug) +return -ENODEV ;
Debug can't be NULL
drivers/gpu/drm/msm/dp/dp_debug.c line 128
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +7
-0+if (*ppos) +return 0 ; + +if (!debug->usbpd) +return -ENODEV ; + + len +=snprintf (buf,SZ_8 ,"%d\n" , debug->usbpd->hpd_high);
You should always use scnprintf instead of snprintf in these situations.
And use sizeof(buf) instead of a constant.
And you can set len = snprintf(...). you don't need to do a += and depend on the initialization.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +13
-0+ +if (copy_to_user (user_buff, buf, len)) +return -EFAULT ; + + *ppos += len; +return len; +} + +static ssize_t dp_debug_read_edid_modes (struct file *file, +char __user *user_buff,size_t count,loff_t *ppos) +{ +struct dp_debug_private *debug = file->private_data; +char *buf;
drivers/gpu/drm/msm/dp/dp_debug.c line 151
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+u32 len =0 ; +int rc =0 ; +struct drm_connector *connector; +struct drm_display_mode *mode; + +if (!debug) { +pr_err ("invalid data\n" ); + rc = -ENODEV ; + goto error; + }
Debug cannot be NULL here.
drivers/gpu/drm/msm/dp/dp_debug.c line 153
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +2
-0+ + connector = *debug->connector;
Why are you dereferencing debug?
drivers/gpu/drm/msm/dp/dp_debug.c line 158
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+ +if (!connector) { +pr_err ("connector is NULL\n" ); + rc = -EINVAL ; + goto error;
Just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_debug.c line 156
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_debug.c new file +1
-0+ }
I'm not sure if this can be an error or not, but perhaps consider skipping the print message.
drivers/gpu/drm/msm/dp/dp_debug.c line 150
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +3
-0+ +if (*ppos) + goto error;
Just return 0;
drivers/gpu/drm/msm/dp/dp_debug.c line 167
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+ + buf =kzalloc (SZ_4K ,GFP_KERNEL ); +if (!buf) { + rc = -ENOMEM ; + goto error;
Just return -ENOMEM;
drivers/gpu/drm/msm/dp/dp_debug.c line 171
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +4
-0+ } + +list_for_each_entry (mode, &connector->modes, head) { + len += snprintf(buf + len, SZ_4K - len,
Definitely use scnprintf() - this is a disaster waiting to happen/
drivers/gpu/drm/msm/dp/dp_debug.c line 180
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+"%s %d %d %d %d %d %d %d %d %d 0x%x\n" , + mode->name, mode->vrefresh, mode->hdisplay, + mode->hsync_start, mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, mode->vsync_end, + mode->vtotal, mode->flags); + } + +if (copy_to_user (user_buff, buf, len)) { +kfree (buf);
Just return -EFAULT here
drivers/gpu/drm/msm/dp/dp_debug.c line 190
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+ rc = -EFAULT ; + goto error; + } + + *ppos += len; +kfree (buf); + +return len; +error: +return rc;
This label isn't needed with the above changes.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +15
-0+} + +static int dp_debug_check_buffer_overflow (int rc,int *max_size,int *len) +{ +if (rc >= *max_size) { +pr_err ("buffer overflow\n" ); +return -EINVAL ; + } + *len += rc; + *max_size =SZ_4K - *len; + +return 0 ; +} + +static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff,
drivers/gpu/drm/msm/dp/dp_debug.c line 215
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+ size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; +char *buf; +u32 len =0 , rc =0 ; +u64 lclk =0 ; +u32 max_size =SZ_4K ; + +if (!debug) +return -ENODEV ;
Debug cannot be 0.
drivers/gpu/drm/msm/dp/dp_debug.c line 224
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+ +if (*ppos) +return 0 ; + + buf =kzalloc (SZ_4K ,GFP_KERNEL ); +if (!buf) +return -ENOMEM ; + + rc =snprintf (buf + len, max_size,"\tname = %s\n" ,DEBUG_NAME );
Use scnprintf()
drivers/gpu/drm/msm/dp/dp_debug.c line 223
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +2
-0+if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error;
This function is very odd - if you use scnprintf() you can safely just do
len = scnprintf(buf + len, SZ_4K - len, "\ttname = %s\n", DEBUG_NAME); len += scnprintf(buf + len, SZ_4K - len, ....)
But this whole thing seems like a really good fit for seq_file and then you don't have to worry about anything else.
Quoted 149 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +149
-0+ rc =snprintf (buf + len, max_size, +"\tdp_panel\n\t\tmax_pclk_khz = %d\n" , + debug->panel->max_pclk_khz); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\tdrm_dp_link\n\t\trate = %u\n" , + debug->panel->link_info.rate); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tnum_lanes = %u\n" , + debug->panel->link_info.num_lanes); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tcapabilities = %lu\n" , + debug->panel->link_info.capabilities); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\tdp_panel_info:\n\t\tactive = %dx%d\n" , + debug->panel->pinfo.h_active, + debug->panel->pinfo.v_active); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tback_porch = %dx%d\n" , + debug->panel->pinfo.h_back_porch, + debug->panel->pinfo.v_back_porch); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tfront_porch = %dx%d\n" , + debug->panel->pinfo.h_front_porch, + debug->panel->pinfo.v_front_porch); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tsync_width = %dx%d\n" , + debug->panel->pinfo.h_sync_width, + debug->panel->pinfo.v_sync_width); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tactive_low = %dx%d\n" , + debug->panel->pinfo.h_active_low, + debug->panel->pinfo.v_active_low); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\th_skew = %d\n" , + debug->panel->pinfo.h_skew); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\trefresh rate = %d\n" , + debug->panel->pinfo.refresh_rate); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tpixel clock khz = %d\n" , + debug->panel->pinfo.pixel_clk_khz); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tbpp = %d\n" , + debug->panel->pinfo.bpp); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + +/* Link Information */ + rc =snprintf (buf + len, max_size, +"\tdp_link:\n\t\ttest_requested = %d\n" , + debug->link->sink_request); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tlane_count = %d\n" , debug->link->link_params.lane_count); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tbw_code = %d\n" , debug->link->link_params.bw_code); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + lclk =drm_dp_bw_code_to_link_rate ( + debug->link->link_params.bw_code) *1000 ; + rc =snprintf (buf + len, max_size, +"\t\tlclk = %lld\n" , lclk); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tv_level = %d\n" , debug->link->phy_params.v_level); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + + rc =snprintf (buf + len, max_size, +"\t\tp_level = %d\n" , debug->link->phy_params.p_level); +if (dp_debug_check_buffer_overflow (rc, &max_size, &len)) + goto error; + +if (copy_to_user (user_buff, buf, len)) + goto error; + + *ppos += len; + +kfree (buf); +return len; +error: +kfree (buf); +return -EINVAL ; +} + +static const struct file_operations dp_debug_fops = { + .open = simple_open, + .read = dp_debug_read_info, +}; + +static const struct file_operations edid_modes_fops = { + .open = simple_open, + .read = dp_debug_read_edid_modes, + .write = dp_debug_write_edid_modes, +}; + +static const struct file_operations hpd_fops = { + .open = simple_open, + .write = dp_debug_write_hpd, +}; + +static const struct file_operations connected_fops = { + .open = simple_open, + .read = dp_debug_read_connected, +};
drivers/gpu/drm/msm/dp/dp_debug.c line 386
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+ +static int dp_debug_init (struct dp_debug *dp_debug) +{ +int rc =0 ; +struct dp_debug_private *debug =container_of (dp_debug, + struct dp_debug_private, dp_debug); +struct dentry *dir, *file, *edid_modes; +struct dentry *hpd, *connected; + + dir =debugfs_create_dir (DEBUG_NAME ,NULL );
You don't want to be putting the debugbfs in the root dir - you'll want it nicely nestled in with the rest of the driver. See the GPU or DPU debugfs files for clues on how to do that.
drivers/gpu/drm/msm/dp/dp_debug.c line 387
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_debug.c new file +1
-0+if (IS_ERR_OR_NULL (dir)) {
debugfs_create_dir only returns NULL on error. Getting the PTR_ERR will just return 0 in that case.
drivers/gpu/drm/msm/dp/dp_debug.c line 390
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +3
-0+ rc =PTR_ERR (dir); +pr_err ("[%s] debugfs create dir failed, rc = %d\n" , +DEBUG_NAME , rc);
You don't need DEBUG_NAME in the string - you already have it in the pr_fmt.
drivers/gpu/drm/msm/dp/dp_debug.c line 396
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +6
-0+ goto error; + } + + file =debugfs_create_file ("dp_debug" ,0444 , dir, + debug, &dp_debug_fops); +if (IS_ERR_OR_NULL (file)) {
As above.
drivers/gpu/drm/msm/dp/dp_debug.c line 405
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+ rc =PTR_ERR (file); +pr_err ("[%s] debugfs create file failed, rc=%d\n" , +DEBUG_NAME , rc); + goto error_remove_dir; + } + + edid_modes =debugfs_create_file ("edid_modes" ,0644 , dir, + debug, &edid_modes_fops); +if (IS_ERR_OR_NULL (edid_modes)) {
As above.
drivers/gpu/drm/msm/dp/dp_debug.c line 414
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+ rc =PTR_ERR (edid_modes); +pr_err ("[%s] debugfs create edid_modes failed, rc=%d\n" , +DEBUG_NAME , rc); + goto error_remove_dir; + } + + hpd =debugfs_create_file ("hpd" ,0644 , dir, + debug, &hpd_fops); +if (IS_ERR_OR_NULL (hpd)) {
As above.
drivers/gpu/drm/msm/dp/dp_debug.c line 423
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+ rc =PTR_ERR (hpd); +pr_err ("[%s] debugfs hpd failed, rc=%d\n" , +DEBUG_NAME , rc); + goto error_remove_dir; + } + + connected =debugfs_create_file ("connected" ,0444 , dir, + debug, &connected_fops); +if (IS_ERR_OR_NULL (connected)) {
As above.
drivers/gpu/drm/msm/dp/dp_debug.c line 435
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +12
-0+ rc =PTR_ERR (connected); +pr_err ("[%s] debugfs connected failed, rc=%d\n" , +DEBUG_NAME , rc); + goto error_remove_dir; + } + + debug->root = dir; +return rc; +error_remove_dir: +debugfs_remove (dir); +error: +return rc;
Note that rc will have to be assigned by some value by you on error because you won't be getting it from the api functions.
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +5
-0+} + +struct dp_debug *dp_debug_get (struct device *dev,struct dp_panel *panel, +struct dp_usbpd *usbpd,struct dp_link *link, +struct drm_connector **connector)
drivers/gpu/drm/msm/dp/dp_debug.c line 450
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+{ +int rc =0 ; +struct dp_debug_private *debug; +struct dp_debug *dp_debug; + +if (!dev || !panel || !usbpd || !link) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
I don't think any of these checks are needed - they should all be non-NULL from the caller.
drivers/gpu/drm/msm/dp/dp_debug.c line 453
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +2
-0+ debug =devm_kzalloc (dev,sizeof (*debug),GFP_KERNEL ); +if (!debug) {
just return ERR_PTR(-ENOMEM);
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +9
-0+ rc = -ENOMEM ; + goto error; + } + + debug->dp_debug.debug_en = false; + debug->usbpd = usbpd; + debug->link = link; + debug->panel = panel; + debug->dev = dev;
drivers/gpu/drm/msm/dp/dp_debug.c line 472
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+ debug->connector = connector; + + dp_debug = &debug->dp_debug; + dp_debug->vdisplay =0 ; + dp_debug->hdisplay =0 ; + dp_debug->vrefresh =0 ; + + rc =dp_debug_init (dp_debug); +if (rc) { +devm_kfree (dev, debug);
just return ERR_PTR(rc);
drivers/gpu/drm/msm/dp/dp_debug.c line 478
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +6
-0+ goto error; + } + +return dp_debug; +error: +return ERR_PTR (rc);
THis isn't needed
drivers/gpu/drm/msm/dp/dp_debug.c line 481
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +3
-0+} + +static int dp_debug_deinit (struct dp_debug *dp_debug)
This function doesn't need to return anything - the "error" is uninteresting.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +13
-0+{ +struct dp_debug_private *debug; + +if (!dp_debug) +return -EINVAL ; + + debug = container_of(dp_debug, struct dp_debug_private, dp_debug); + +debugfs_remove_recursive (debug->root); + +return 0 ; +} +
drivers/gpu/drm/msm/dp/dp_debug.c line 504
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +10
-0+void dp_debug_put (struct dp_debug *dp_debug) +{ +struct dp_debug_private *debug; + +if (!dp_debug) +return ; + + debug = container_of(dp_debug, struct dp_debug_private, dp_debug); + +dp_debug_deinit (dp_debug);
In fact, dp_debug_deinit doesn't need to exist - you can keep it all inline and bonus - you don't have to do an unneeded container_of for no reason.
drivers/gpu/drm/msm/dp/dp_debug.c line 506
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_debug.c new file +1
-0+devm_kfree (debug->dev, debug);
If you are using devm_ you don't need to free here.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_debug.h new file +3
-0@@ -0,0 +1,81 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_debug.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_debug.h new file +17
-0+#ifndef _DP_DEBUG_H_ +#define _DP_DEBUG_H_ + +#include "dp_panel.h" +#include "dp_link.h" +#include "dp_extcon.h" + +/** + * struct dp_debug + * @debug_en: specifies whether debug mode enabled + * @vdisplay: used to filter out vdisplay value + * @hdisplay: used to filter out hdisplay value + * @vrefresh: used to filter out vrefresh value + * @tpg_state: specifies whether tpg feature is enabled + */ +struct dp_debug { + bool debug_en;
drivers/gpu/drm/msm/dp/dp_debug.h line 41
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_debug.h new file +10
-0+int aspect_ratio; +int vdisplay; +int hdisplay; +int vrefresh; +}; + +#if defined(CONFIG_DEBUG_FS ) + +/** +* dp_debug_get() - configure and get the DisplayPlot debug module data
DisplayPlot? DisplayPort perhaps?
Quoted 49 lines
drivers/gpu/drm/msm/dp/dp_debug.h new file +40
-0+* +* @dev: device instance of the caller +* @panel: instance of panel module +* @usbpd: instance of usbpd module +* @link: instance of link module +* @connector: double pointer to display connector +* return: pointer to allocated debug module data +* +* This function sets up the debug module and provides a way +* for debugfs input to be communicated with existing modules +*/ +struct dp_debug *dp_debug_get (struct device *dev,struct dp_panel *panel, +struct dp_usbpd *usbpd,struct dp_link *link, +struct drm_connector **connector); +/** +* dp_debug_put() +* +* Cleans up dp_debug instance +* +* @dp_debug: instance of dp_debug +*/ +void dp_debug_put (struct dp_debug *dp_debug); + +#else + +static inline +struct dp_debug *dp_debug_get (struct device *dev,struct dp_panel *panel, +struct dp_usbpd *usbpd,struct dp_link *link, +struct drm_connector **connector) +{ +return ERR_PTR (-EINVAL ); +} + +static inline void dp_debug_put (struct dp_debug *dp_debug) +{ +} + +#endif /* defined(CONFIG_DEBUG_FS) */ + +#endif /* _DP_DEBUG_H_ */ drivers/gpu/drm/msm/dp/dp_display.c new file +3
-0@@ -0,0 +1,977 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_display.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX of course.
Quoted 48 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +48
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/debugfs.h> +#include <linux/component.h> +#include <linux/of_irq.h> + +#include "msm_drv.h" +#include "dp_extcon.h" +#include "dp_parser.h" +#include "dp_power.h" +#include "dp_catalog.h" +#include "dp_aux.h" +#include "dp_link.h" +#include "dp_panel.h" +#include "dp_ctrl.h" +#include "dp_display.h" +#include "dp_drm.h" +#include "dp_debug.h" + +static struct msm_dp *g_dp_display; +#define HPD_STRING_SIZE 30 + +struct dp_display_private { +char *name; +int irq; + +/* state variables */ +bool core_initialized; +bool power_on; +bool hpd_irq_on; +bool audio_supported; + +struct platform_device *pdev; +struct dentry *root; +struct completion notification_comp; + +struct dp_usbpd *usbpd; +struct dp_parser *parser; +struct dp_power *power; +struct dp_catalog *catalog; +struct dp_aux *aux; +struct dp_link *link; +struct dp_panel *panel; +struct dp_ctrl *ctrl; +struct dp_debug *debug;
drivers/gpu/drm/msm/dp/dp_display.c line 72
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ +struct dp_usbpd_cb usbpd_cb; +struct dp_display_mode mode; +struct msm_dp dp_display; + +}; + +static const struct of_device_id dp_dt_match[] = { + {.compatible ="qcom,dp-display" }, + {}
We like to have a comma after the closing {} for consistency.
drivers/gpu/drm/msm/dp/dp_display.c line 82
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+}; + +static irqreturn_t dp_display_irq (int irq,void *dev_id) +{ +struct dp_display_private *dp = dev_id; + +if (!dp) { +pr_err ("invalid data\n" ); +return IRQ_NONE ; + }
dp will never be NULL here
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0+/* DP controller isr */ + dp->ctrl->isr (dp->ctrl); + +/* DP aux isr */ + dp->aux->isr (dp->aux); + +return IRQ_HANDLED ; +} + +static int dp_display_bind (struct device *dev,struct device *master, +void *data) +{ +int rc =0 ; +struct dp_display_private *dp;
drivers/gpu/drm/msm/dp/dp_display.c line 107
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+struct drm_device *drm; +struct msm_drm_private *priv; +struct platform_device *pdev =to_platform_device (dev); + +if (!dev || !pdev || !master) { +pr_err ("invalid param(s), dev %pK, pdev %pK, master %pK\n" , + dev, pdev, master); + rc = -EINVAL ; + goto end; + }
These will never be NULL coming out of a component bind.
+
drivers/gpu/drm/msm/dp/dp_display.c line 116
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +8
-0+ drm =dev_get_drvdata (master); + dp =platform_get_drvdata (pdev); +if (!drm || !dp) { +pr_err ("invalid param(s), drm %pK, dp %pK\n" , + drm, dp); + rc = -EINVAL ; + goto end; + }
These are also very unlikely to be NULL.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0+ + dp->dp_display.drm_dev = drm; + priv = drm->dev_private; + priv->dp = &(dp->dp_display); + + rc = dp->parser->parse (dp->parser); +if (rc) { +pr_err ("device tree parsing failed\n" ); + goto end; + } +
drivers/gpu/drm/msm/dp/dp_display.c line 137
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ rc = dp->aux->drm_aux_register (dp->aux); +if (rc) { +pr_err ("DRM DP AUX register failed\n" ); + goto end; + } + + rc = dp->power->power_client_init (dp->power); +if (rc) { +pr_err ("Power client create failed\n" ); + goto end;
You don't need this goto here, you can just drop out.
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0+ } + +end: +return rc; +} + +static void dp_display_unbind (struct device *dev,struct device *master, +void *data) +{ +struct dp_display_private *dp; +struct platform_device *pdev =to_platform_device (dev); +struct drm_device *drm =dev_get_drvdata (master); +struct msm_drm_private *priv = drm->dev_private; +
drivers/gpu/drm/msm/dp/dp_display.c line 161
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+if (!dev || !pdev) { +pr_err ("invalid param(s)\n" ); +return ; + } + + dp =platform_get_drvdata (pdev); +if (!dp) { +pr_err ("Invalid params\n" ); +return ; + }
Both these checks are not likely to be NULL.
drivers/gpu/drm/msm/dp/dp_display.c line 164
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +3
-0+ + (void )dp->power->power_client_deinit (dp->power); + (void )dp->aux->drm_aux_deregister (dp->aux);
If you don't care about the value of either of these then consider changing them so they don't return a value.
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +19
-0+ priv->dp =NULL ; +} + +static const struct component_ops dp_display_comp_ops = { + .bind = dp_display_bind, + .unbind = dp_display_unbind, +}; + +static bool dp_display_is_ds_bridge (struct dp_panel *panel) +{ +return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT ] & +DP_DWN_STRM_PORT_PRESENT ); +} + +static bool dp_display_is_sink_count_zero (struct dp_display_private *dp) +{ +return dp_display_is_ds_bridge (dp->panel) && + (dp->link->sink_count.count ==0 ); +}
drivers/gpu/drm/msm/dp/dp_display.c line 193
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ +static void dp_display_send_hpd_event (struct msm_dp *dp_display) +{ +struct dp_display_private *dp; +struct drm_connector *connector; + +if (!dp_display) { +pr_err ("invalid input\n" ); +return ; + }
It looks unlkely this will be NULL, so you can safely remove this or use WARN_ON.
drivers/gpu/drm/msm/dp/dp_display.c line 199
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +5
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); +if (!dp) { +pr_err ("invalid params\n" ); +return ; + }
The result of a container_of() will NEVER be NULL at least not without a lot of trouble.
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0+ connector = dp->dp_display.connector; +drm_helper_hpd_irq_event (connector->dev); +} + +static int dp_display_send_hpd_notification (struct dp_display_private *dp, +bool hpd) +{ +if ((hpd && dp->dp_display.is_connected) || + (!hpd && !dp->dp_display.is_connected)) { +pr_info ("HPD already %s\n" , (hpd ?"on" :"off" )); +return 0 ; + } + +/* reset video pattern flag on disconnect */
drivers/gpu/drm/msm/dp/dp_display.c line 224
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+if (!hpd) + dp->panel->video_test = false; + + dp->dp_display.is_connected = hpd; +reinit_completion (&dp->notification_comp); +dp_display_send_hpd_event (&dp->dp_display); + +if (!wait_for_completion_timeout (&dp->notification_comp,HZ *2 )) { +pr_warn ("%s timeout\n" , hpd ?"connect" :"disconnect" ); +return -EINVAL ;
Returning -ETIMEDOUT would be more informative.
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +14
-0+ } + +return 0 ; +} + +static int dp_display_process_hpd_high (struct dp_display_private *dp) +{ +int rc =0 ; +struct edid *edid; + + dp->aux->init (dp->aux, dp->parser->aux_cfg); + +if (dp->link->psm_enabled) + goto notify;
drivers/gpu/drm/msm/dp/dp_display.c line 248
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ + rc = dp->panel->read_sink_caps (dp->panel, dp->dp_display.connector); +if (rc) + goto notify; + + dp->link->process_request (dp->link); + +if (dp_display_is_sink_count_zero (dp)) { +pr_debug ("no downstream devices connected\n" ); + rc = -EINVAL ;
You can just return -EINVAL here.
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +5
-0+ goto end; + } + + edid = dp->panel->edid; +
drivers/gpu/drm/msm/dp/dp_display.c line 263
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ dp->audio_supported =drm_detect_monitor_audio (edid); + + dp->panel->handle_sink_request (dp->panel); + + dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; +notify: +dp_display_send_hpd_notification (dp, true); + +end: +return rc;
Not needed.
Quoted 44 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +43
-0+} + +static void dp_display_host_init (struct dp_display_private *dp) +{ +bool flip = false; + +if (dp->core_initialized) { +pr_debug ("DP core already initialized\n" ); +return ; + } + +if (dp->usbpd->orientation ==ORIENTATION_CC2 ) + flip = true; + + dp->power->init (dp->power, flip); + dp->ctrl->init (dp->ctrl, flip); +enable_irq (dp->irq); + dp->core_initialized = true; +} + +static void dp_display_host_deinit (struct dp_display_private *dp) +{ +if (!dp->core_initialized) { +pr_debug ("DP core already off\n" ); +return ; + } + + dp->ctrl->deinit (dp->ctrl); + dp->power->deinit (dp->power); +disable_irq (dp->irq); + dp->core_initialized = false; +} + +static void dp_display_process_hpd_low (struct dp_display_private *dp) +{ +/* cancel any pending request */ + dp->ctrl->abort (dp->ctrl); + +dp_display_send_hpd_notification (dp, false); + + dp->aux->deinit (dp->aux); +} +
drivers/gpu/drm/msm/dp/dp_display.c line 316
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+static int dp_display_usbpd_configure_cb (struct device *dev) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dev) { +pr_err ("invalid dev\n" ); + rc = -EINVAL ; + goto end; + }
I'm not sure if this ever be true (I suspect it can't) but if so you can use the WARN_ON method.
drivers/gpu/drm/msm/dp/dp_display.c line 323
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0+ dp =dev_get_drvdata (dev); +if (!dp) { +pr_err ("no driver data found\n" ); + rc = -ENODEV ; + goto end; + }
I'm reasonably sure that if dev is valid, this will be valid.
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +21
-0+dp_display_host_init (dp); + +if (dp->usbpd->hpd_high) +dp_display_process_hpd_high (dp); +end: +return rc; +} + +static void dp_display_clean (struct dp_display_private *dp) +{ + dp->ctrl->push_idle (dp->ctrl); + dp->ctrl->off (dp->ctrl); +} + +static int dp_display_usbpd_disconnect_cb (struct device *dev) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dev) { +pr_err ("invalid dev\n" );
drivers/gpu/drm/msm/dp/dp_display.c line 355
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ rc = -EINVAL ; + goto end; + } + + dp =dev_get_drvdata (dev); +if (!dp) { +pr_err ("no driver data found\n" ); + rc = -ENODEV ; + goto end; + }
As above
Quoted 53 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +53
-0+/* cancel any pending request */ + dp->ctrl->abort (dp->ctrl); + + rc =dp_display_send_hpd_notification (dp, false); + +/* if cable is disconnected, reset psm_enabled flag */ +if (!dp->usbpd->alt_mode_cfg_done) + dp->link->psm_enabled = false; + +if ((rc <0 ) && dp->power_on) +dp_display_clean (dp); + +dp_display_host_deinit (dp); +end: +return rc; +} + +static void dp_display_handle_video_request (struct dp_display_private *dp) +{ +if (dp->link->sink_request &DP_TEST_LINK_VIDEO_PATTERN ) { +/* force disconnect followed by connect */ + dp->usbpd->connect (dp->usbpd, false); + dp->panel->video_test = true; + dp->usbpd->connect (dp->usbpd, true); + dp->link->send_test_response (dp->link); + } +} + +static int dp_display_handle_hpd_irq (struct dp_display_private *dp) +{ +if (dp->link->sink_request &DS_PORT_STATUS_CHANGED ) { +dp_display_send_hpd_notification (dp, false); + +if (dp_display_is_sink_count_zero (dp)) { +pr_debug ("sink count is zero, nothing to do\n" ); +return 0 ; + } + +return dp_display_process_hpd_high (dp); + } + + dp->ctrl->handle_sink_request (dp->ctrl); + +dp_display_handle_video_request (dp); + +return 0 ; +} + +static int dp_display_usbpd_attention_cb (struct device *dev) +{ +int rc =0 ; +struct dp_display_private *dp; +
drivers/gpu/drm/msm/dp/dp_display.c line 419
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+if (!dev) { +pr_err ("invalid dev\n" ); +return -EINVAL ; + } + + dp =dev_get_drvdata (dev); +if (!dp) { +pr_err ("no driver data found\n" ); +return -ENODEV ; + }
As above.
drivers/gpu/drm/msm/dp/dp_display.c line 429
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +9
-0+if (dp->usbpd->hpd_irq) { + dp->hpd_irq_on = true; + + rc = dp->link->process_request (dp->link); +/* check for any test request issued by sink */ +if (!rc) +dp_display_handle_hpd_irq (dp); + + dp->hpd_irq_on = false;
Just return rc;
drivers/gpu/drm/msm/dp/dp_display.c line 435
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0+ goto end; + } + +if (!dp->usbpd->hpd_high) { +dp_display_process_hpd_low (dp); + goto end;
Just return rc;
drivers/gpu/drm/msm/dp/dp_display.c line 441
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0+ } + +if (dp->usbpd->alt_mode_cfg_done) +dp_display_process_hpd_high (dp); +end: +return rc;
return 0;
Quoted 93 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +93
-0+} + +static void dp_display_deinit_sub_modules (struct dp_display_private *dp) +{ +dp_ctrl_put (dp->ctrl); +dp_link_put (dp->link); +dp_panel_put (dp->panel); +dp_aux_put (dp->aux); +dp_power_put (dp->power); +dp_catalog_put (dp->catalog); +dp_parser_put (dp->parser); +dp_debug_put (dp->debug); +} + +static int dp_init_sub_modules (struct dp_display_private *dp) +{ +int rc =0 ; +struct device *dev = &dp->pdev->dev; +struct dp_usbpd_cb *cb = &dp->usbpd_cb; +struct dp_ctrl_in ctrl_in = { + .dev = dev, + }; +struct dp_panel_in panel_in = { + .dev = dev, + }; + +/* Callback APIs used for cable status change event */ + cb->configure = dp_display_usbpd_configure_cb; + cb->disconnect = dp_display_usbpd_disconnect_cb; + cb->attention = dp_display_usbpd_attention_cb; + + dp->parser =dp_parser_get (dp->pdev); +if (IS_ERR (dp->parser)) { + rc =PTR_ERR (dp->parser); +pr_err ("failed to initialize parser, rc = %d\n" , rc); + dp->parser =NULL ; + goto error_parser; + } + + dp->catalog =dp_catalog_get (dev, &dp->parser->io); +if (IS_ERR (dp->catalog)) { + rc =PTR_ERR (dp->catalog); +pr_err ("failed to initialize catalog, rc = %d\n" , rc); + dp->catalog =NULL ; + goto error_catalog; + } + + dp->power =dp_power_get (dp->parser); +if (IS_ERR (dp->power)) { + rc =PTR_ERR (dp->power); +pr_err ("failed to initialize power, rc = %d\n" , rc); + dp->power =NULL ; + goto error_power; + } + + dp->aux =dp_aux_get (dev, &dp->catalog->aux, dp->parser->aux_cfg); +if (IS_ERR (dp->aux)) { + rc =PTR_ERR (dp->aux); +pr_err ("failed to initialize aux, rc = %d\n" , rc); + dp->aux =NULL ; + goto error_aux; + } + + dp->link =dp_link_get (dev, dp->aux); +if (IS_ERR (dp->link)) { + rc =PTR_ERR (dp->link); +pr_err ("failed to initialize link, rc = %d\n" , rc); + dp->link =NULL ; + goto error_link; + } + + panel_in.aux = dp->aux; + panel_in.catalog = &dp->catalog->panel; + panel_in.link = dp->link; + + dp->panel =dp_panel_get (&panel_in); +if (IS_ERR (dp->panel)) { + rc =PTR_ERR (dp->panel); +pr_err ("failed to initialize panel, rc = %d\n" , rc); + dp->panel =NULL ; + goto error_panel; + } + + ctrl_in.link = dp->link; + ctrl_in.panel = dp->panel; + ctrl_in.aux = dp->aux; + ctrl_in.power = dp->power; + ctrl_in.catalog = &dp->catalog->ctrl; + ctrl_in.parser = dp->parser; + + dp->ctrl =dp_ctrl_get (&ctrl_in); +if (IS_ERR (dp->ctrl)) { + rc =PTR_ERR (dp->ctrl);
drivers/gpu/drm/msm/dp/dp_display.c line 544
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+pr_err ("failed to initialize ctrl, rc = %d\n" , rc); + dp->ctrl =NULL ; + goto error_ctrl; + } + + dp->debug =dp_debug_get (dev, dp->panel, dp->usbpd, + dp->link, &dp->dp_display.connector); +if (IS_ERR (dp->debug)) { + rc =PTR_ERR (dp->debug); +pr_err ("failed to initialize debug, rc = %d\n" , rc);
dp_debug_get() prints all the interesting error messsages - you don't need to add on.
In fact, I think this is probably true for the rest of the dp_ calls above - in general, try to keep the number of log messages per error down to 1.
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +24
-0+ dp->debug =NULL ; + goto error_debug; + } + +return rc; +error_debug: +dp_ctrl_put (dp->ctrl); +error_ctrl: +dp_panel_put (dp->panel); +error_panel: +dp_link_put (dp->link); +error_link: +dp_aux_put (dp->aux); +error_aux: +dp_power_put (dp->power); +error_power: +dp_catalog_put (dp->catalog); +error_catalog: +dp_parser_put (dp->parser); +error_parser: +return rc; +} + +static int dp_display_set_mode(struct msm_dp *dp_display,
drivers/gpu/drm/msm/dp/dp_display.c line 578
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ struct dp_display_mode *mode) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
I'm betting this can't be NULL;
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +13
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp->panel->pinfo = mode->timing; + dp->panel->init_info (dp->panel); +error: +return rc; +} + +static int dp_display_prepare (struct msm_dp *dp) +{ +return 0 ; +} +
drivers/gpu/drm/msm/dp/dp_display.c line 601
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+static int dp_display_enable (struct msm_dp *dp_display) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
I am guessing this can't be NULL.
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +16
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + +if (dp->power_on) { +pr_debug ("Link already setup, return\n" ); +return 0 ; + } + + dp->aux->init (dp->aux, dp->parser->aux_cfg); + + rc = dp->ctrl->on (dp->ctrl); +if (!rc) + dp->power_on = true; +error: +return rc; +} +
drivers/gpu/drm/msm/dp/dp_display.c line 628
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+static int dp_display_post_enable (struct msm_dp *dp_display) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + }
As above.
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +9
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + +complete_all (&dp->notification_comp); + +end: +return rc; +} + +static int dp_display_pre_disable (struct msm_dp *dp_display)
drivers/gpu/drm/msm/dp/dp_display.c line 648
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + } +
as above.
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + +if (dp->usbpd->alt_mode_cfg_done && (dp->usbpd->hpd_high || + dp->usbpd->forced_disconnect)) + dp->link->psm_config (dp->link, &dp->panel->link_info, true); + + dp->ctrl->push_idle (dp->ctrl); +error: +return rc; +} +
drivers/gpu/drm/msm/dp/dp_display.c line 669
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+static int dp_display_disable (struct msm_dp *dp_display) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
As above.
drivers/gpu/drm/msm/dp/dp_display.c line 674
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +4
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + +if (!dp->power_on || !dp->core_initialized) + goto error;
goto error is deceptive here. You can just return 0. In fact, if you get rid of the uneeded NULL check you don't have to return anything from this function.
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +9
-0+ + dp->ctrl->off (dp->ctrl); + + dp->power_on = false; + +complete_all (&dp->notification_comp); +error: +return rc; +}
drivers/gpu/drm/msm/dp/dp_display.c line 693
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ +static int dp_request_irq (struct msm_dp *dp_display) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); +return -EINVAL ; + }
Likely not needed.
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +19
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp->irq =irq_of_parse_and_map (dp->pdev->dev.of_node,0 ); +if (dp->irq <0 ) { + rc = dp->irq; +pr_err ("failed to get irq: %d\n" , rc); +return rc; + } + + rc =devm_request_irq (&dp->pdev->dev, dp->irq, dp_display_irq, +IRQF_TRIGGER_HIGH ,"dp_display_isr" , dp); +if (rc <0 ) { +pr_err ("failed to request IRQ%u: %d\n" , + dp->irq, rc); +return rc; + } +disable_irq (dp->irq); + +return 0 ;
drivers/gpu/drm/msm/dp/dp_display.c line 723
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+} + +static struct dp_debug *dp_get_debug (struct msm_dp *dp_display) +{ +struct dp_display_private *dp; + +if (!dp_display) { +pr_err ("invalid input\n" ); +return ERR_PTR (-EINVAL ); + }
Likely not needed.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0+ dp = container_of(dp_display, struct dp_display_private, dp_display); + +return dp->debug; +} + +static int dp_display_unprepare (struct msm_dp *dp) +{ +return 0 ; +} + +static int dp_display_validate_mode (struct msm_dp *dp,u32 mode_pclk_khz)
drivers/gpu/drm/msm/dp/dp_display.c line 745
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+{ +const u32 num_components =3 , default_bpp =24 ; +struct dp_display_private *dp_display; +struct drm_dp_link *link_info; +u32 mode_rate_khz =0 , supported_rate_khz =0 , mode_bpp =0 ; + +if (!dp || !mode_pclk_khz || !dp->connector) { +pr_err ("invalid params\n" ); +return -EINVAL ; + }
Same as above.
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +19
-0+ dp_display = container_of(dp, struct dp_display_private, dp_display); + link_info = &dp_display->panel->link_info; + + mode_bpp = dp->connector->display_info.bpc * num_components; +if (!mode_bpp) + mode_bpp = default_bpp; + + mode_bpp = dp_display->panel->get_mode_bpp (dp_display->panel, + mode_bpp, mode_pclk_khz); + + mode_rate_khz = mode_pclk_khz * mode_bpp; + supported_rate_khz = link_info->num_lanes * link_info->rate *8 ; + +if (mode_rate_khz > supported_rate_khz) +return MODE_BAD ; + +return MODE_OK ; +} +
drivers/gpu/drm/msm/dp/dp_display.c line 775
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+static int dp_display_get_modes (struct msm_dp *dp, +struct dp_display_mode *dp_mode) +{ +struct dp_display_private *dp_display; +int ret =0 ; + +if (!dp) { +pr_err ("invalid params\n" ); +return 0 ; + }
Likely not needed.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +7
-0+ dp_display = container_of(dp, struct dp_display_private, dp_display); + + ret = dp_display->panel->get_modes (dp_display->panel, + dp->connector, dp_mode); +if (dp_mode->timing.pixel_clk_khz) + dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz; +return ret;
drivers/gpu/drm/msm/dp/dp_display.c line 793
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+} + +static bool dp_display_check_video_test (struct msm_dp *dp) +{ +struct dp_display_private *dp_display; + +if (!dp) { +pr_err ("invalid params\n" ); +return false; + }
Likely not needed
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0+ dp_display = container_of(dp, struct dp_display_private, dp_display); + +if (dp_display->panel->video_test) +return true; + +return false;
drivers/gpu/drm/msm/dp/dp_display.c line 810
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+} + +static int dp_display_get_test_bpp (struct msm_dp *dp) +{ +struct dp_display_private *dp_display; + +if (!dp) { +pr_err ("invalid params\n" ); +return 0 ; + }
Likely not needed.
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +5
-0+ dp_display = container_of(dp, struct dp_display_private, dp_display); + +return dp_link_bit_depth_to_bpp ( + dp_display->link->test_video.test_bit_depth); +}
drivers/gpu/drm/msm/dp/dp_display.c line 826
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ +static int dp_display_probe (struct platform_device *pdev) +{ +int rc =0 ; +struct dp_display_private *dp; + +if (!pdev || !pdev->dev.of_node) { +pr_err ("pdev not found\n" ); +return -ENODEV ; + }
Both of these will always be true in a probe function that you reach from a compatible match.
drivers/gpu/drm/msm/dp/dp_display.c line 839
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +12
-0+ dp =devm_kzalloc (&pdev->dev,sizeof (*dp),GFP_KERNEL ); +if (!dp) +return -ENOMEM ; + +init_completion (&dp->notification_comp); + + dp->pdev = pdev; + dp->name ="drm_dp" ; + + rc =dp_init_sub_modules (dp); +if (rc) { +pr_err ("init sub module failed\n" );
I'm guessing that this log message will always be superfluous.
drivers/gpu/drm/msm/dp/dp_display.c line 841
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +2
-0+devm_kfree (&pdev->dev, dp); +return -EPROBE_DEFER ;
Always return -EPROBE_DEFER regardless of the error? It seems that at a certain point many of these errors you point out would be fatal to the device regardless of the order of initialization.
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +36
-0+ } + +platform_set_drvdata (pdev, dp); + + g_dp_display = &dp->dp_display; + + g_dp_display->enable = dp_display_enable; + g_dp_display->post_enable = dp_display_post_enable; + g_dp_display->pre_disable = dp_display_pre_disable; + g_dp_display->disable = dp_display_disable; + g_dp_display->set_mode = dp_display_set_mode; + g_dp_display->validate_mode = dp_display_validate_mode; + g_dp_display->get_modes = dp_display_get_modes; + g_dp_display->prepare = dp_display_prepare; + g_dp_display->unprepare = dp_display_unprepare; + g_dp_display->request_irq = dp_request_irq; + g_dp_display->get_debug = dp_get_debug; + g_dp_display->send_hpd_event = dp_display_send_hpd_event; + g_dp_display->is_video_test = dp_display_check_video_test; + g_dp_display->get_test_bpp = dp_display_get_test_bpp; + + rc =component_add (&pdev->dev, &dp_display_comp_ops); +if (rc) { +pr_err ("component add failed, rc=%d\n" , rc); +dp_display_deinit_sub_modules (dp); +devm_kfree (&pdev->dev, dp); + } + +return rc; +} + +int dp_display_get_displays (void **displays,int count) +{ +if (!displays) { +pr_err ("invalid data\n" ); +return -EINVAL ;
drivers/gpu/drm/msm/dp/dp_display.c line 887
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ } + +if (count !=1 ) { +pr_err ("invalid number of displays\n" ); +return -EINVAL ; + } + + displays[0 ] = g_dp_display; +return count; +}
This isn't used in this patch so I don't see how it is used but based on everything it seems like you could just as easily get away with
struct msm_dp *dp_display_get_display(void)
{
return g_dp_display;
}Even if you are planning for the future, you can make the changes to support multiple displays then and save yourself the effort now.
drivers/gpu/drm/msm/dp/dp_display.c line 899
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0+int dp_display_get_num_of_displays (void ) +{ +return 1 ; +} + +static int dp_display_remove (struct platform_device *pdev) +{ +struct dp_display_private *dp; + +if (!pdev) +return -EINVAL ;
pdev will never be NULL here.
drivers/gpu/drm/msm/dp/dp_display.c line 906
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +7
-0+ + dp =platform_get_drvdata (pdev); + +dp_display_deinit_sub_modules (dp); + +platform_set_drvdata (pdev,NULL ); +devm_kfree (&pdev->dev, dp);
You don't need to devm_kfree() in a remove function here.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +11
-0+ +return 0 ; +} + +static struct platform_driver dp_display_driver = { + .probe = dp_display_probe, + .remove = dp_display_remove, + .driver = { + .name ="msm-dp-display" , + .of_match_table = dp_dt_match, + },
drivers/gpu/drm/msm/dp/dp_display.c line 927
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+}; + +int __init msm_dp_register (void ) +{ +int ret; + + ret =platform_driver_register (&dp_display_driver); +if (ret) { +pr_err ("driver register failed" ); +return ret;
You don't need this return ret - you can just drop out to the bottom.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +8
-0+ } + +return ret; +} + +void __exit msm_dp_unregister(void) +{ +platform_driver_unregister (&dp_display_driver);
drivers/gpu/drm/msm/dp/dp_display.c line 945
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+} + +int msm_dp_modeset_init (struct msm_dp *dp_display,struct drm_device *dev, +struct drm_encoder *encoder) +{ +struct msm_drm_private *priv; +int ret; + +if (WARN_ON (!encoder) ||WARN_ON (!dp_display) ||WARN_ON (!dev)) +return -EINVAL ;
Thats what I like to see - but you could also do
if (WARN_ON(!encoder || !dp_display || !dev))
drivers/gpu/drm/msm/dp/dp_display.c line 952
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +6
-0+ priv = dev->dev_private; + dp_display->drm_dev = dev; + + ret =dp_drm_bridge_init (dp_display, encoder); +if (ret) { +dev_err (dev->dev,"failed to create dp bridge: %d\n" , ret);
Just double check to see how redundant this error message is.
drivers/gpu/drm/msm/dp/dp_display.c line 962
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +10
-0+ dp_display->bridge =NULL ; +return ret; + } + dp_display->encoder = encoder; + + dp_display->connector =dp_drm_connector_init (dp_display); +if (IS_ERR (dp_display->connector)) { + ret =PTR_ERR (dp_display->connector); +dev_err (dev->dev, +"failed to create dp connector: %d\n" , ret);
Same.
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +15
-0+ dp_display->connector =NULL ; + goto conn_fail; + } + + priv->bridges[priv->num_bridges++] = dp_display->bridge; + priv->connectors[priv->num_connectors++] = dp_display->connector; +return 0 ; + +conn_fail: +if (dp_display->bridge) { +dp_drm_bridge_deinit (dp_display); + dp_display->bridge =NULL ; + } +return ret; +}drivers/gpu/drm/msm/dp/dp_display.h new file +3
-0@@ -0,0 +1,55 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_display.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_display.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 50 lines
drivers/gpu/drm/msm/dp/dp_display.h new file +41
-0+#ifndef _DP_DISPLAY_H_ +#define _DP_DISPLAY_H_ + +#include <drm/drmP.h> + +#include "dp_panel.h" + +struct msm_dp { +struct drm_device *drm_dev; +struct dp_bridge *dp_bridge; +struct drm_connector *connector; +struct drm_bridge *bridge; + +/* the encoder we are hooked to (outside of dsi block) */ +struct drm_encoder *encoder; +bool is_connected; +u32 max_pclk_khz; + +int (*enable)(struct msm_dp *dp_display); +int (*post_enable)(struct msm_dp *dp_display); + +int (*pre_disable)(struct msm_dp *dp_display); +int (*disable)(struct msm_dp *dp_display); + +int (*set_mode)(struct msm_dp *dp_display, +struct dp_display_mode *mode); +int (*validate_mode)(struct msm_dp *dp_display,u32 mode_pclk_khz); +int (*get_modes)(struct msm_dp *dp_display, +struct dp_display_mode *dp_mode); +int (*prepare)(struct msm_dp *dp_display); +int (*unprepare)(struct msm_dp *dp_display); +int (*request_irq)(struct msm_dp *dp_display); +struct dp_debug *(*get_debug)(struct msm_dp *dp_display); +void (*send_hpd_event)(struct msm_dp *dp_display); +bool (*is_video_test)(struct msm_dp *dp_display); +int (*get_test_bpp)(struct msm_dp *dp_display); +}; + +int dp_display_get_num_of_displays (void ); +int dp_display_get_displays (void **displays,int count); +#endif /* _DP_DISPLAY_H_ */ drivers/gpu/drm/msm/dp/dp_drm.c new file +3
-0@@ -0,0 +1,542 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_drm.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX
drivers/gpu/drm/msm/dp/dp_drm.c line 23
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +9
-0+#define pr_fmt (fmt) "[drm-dp]: %s: " fmt, __func__ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic.h> +#include <drm/drm_crtc.h> + +#include "msm_drv.h" +#include "msm_kms.h" +//#include "dpu_connector.h"
If this isn't needed just get rid of it
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +4
-0+#include "dp_drm.h" +#include "dp_debug.h" + +struct dp_connector {
drivers/gpu/drm/msm/dp/dp_drm.c line 37
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+struct drm_connector base; +struct msm_dp *dp_display; +}; +#define to_dp_connector (x) container_of(x, struct dp_connector, base) +#define to_dp_bridge (x) container_of((x), struct dp_bridge, base) + +static void convert_to_dp_mode (const struct drm_display_mode *drm_mode, +struct dp_display_mode *dp_mode,struct msm_dp *dp) +{ +const u32 num_components =3 ;
I prefer to use just the constants inline, especially since you are only using once.
Quoted 80 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +80
-0+ +memset (dp_mode,0 ,sizeof (*dp_mode)); + + dp_mode->timing.h_active = drm_mode->hdisplay; + dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end; + dp_mode->timing.h_sync_width = drm_mode->htotal - + (drm_mode->hsync_start + dp_mode->timing.h_back_porch); + dp_mode->timing.h_front_porch = drm_mode->hsync_start - + drm_mode->hdisplay; + dp_mode->timing.h_skew = drm_mode->hskew; + + dp_mode->timing.v_active = drm_mode->vdisplay; + dp_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end; + dp_mode->timing.v_sync_width = drm_mode->vtotal - + (drm_mode->vsync_start + dp_mode->timing.v_back_porch); + + dp_mode->timing.v_front_porch = drm_mode->vsync_start - + drm_mode->vdisplay; + +if (dp->is_video_test (dp)) + dp_mode->timing.bpp = dp->get_test_bpp (dp); +else + dp_mode->timing.bpp = dp->connector->display_info.bpc * + num_components; + +if (!dp_mode->timing.bpp) + dp_mode->timing.bpp =24 ; + + dp_mode->timing.refresh_rate = drm_mode->vrefresh; + + dp_mode->timing.pixel_clk_khz = drm_mode->clock; + + dp_mode->timing.v_active_low = + !!(drm_mode->flags &DRM_MODE_FLAG_NVSYNC ); + + dp_mode->timing.h_active_low = + !!(drm_mode->flags &DRM_MODE_FLAG_NHSYNC ); +} + +static void convert_to_drm_mode (const struct dp_display_mode *dp_mode, +struct drm_display_mode *drm_mode) +{ +u32 flags =0 ; + +memset (drm_mode,0 ,sizeof (*drm_mode)); + + drm_mode->hdisplay = dp_mode->timing.h_active; + drm_mode->hsync_start = drm_mode->hdisplay + + dp_mode->timing.h_front_porch; + drm_mode->hsync_end = drm_mode->hsync_start + + dp_mode->timing.h_sync_width; + drm_mode->htotal = drm_mode->hsync_end + dp_mode->timing.h_back_porch; + drm_mode->hskew = dp_mode->timing.h_skew; + + drm_mode->vdisplay = dp_mode->timing.v_active; + drm_mode->vsync_start = drm_mode->vdisplay + + dp_mode->timing.v_front_porch; + drm_mode->vsync_end = drm_mode->vsync_start + + dp_mode->timing.v_sync_width; + drm_mode->vtotal = drm_mode->vsync_end + dp_mode->timing.v_back_porch; + + drm_mode->vrefresh = dp_mode->timing.refresh_rate; + drm_mode->clock = dp_mode->timing.pixel_clk_khz; + +if (dp_mode->timing.h_active_low) + flags |=DRM_MODE_FLAG_NHSYNC ; +else + flags |=DRM_MODE_FLAG_PHSYNC ; + +if (dp_mode->timing.v_active_low) + flags |=DRM_MODE_FLAG_NVSYNC ; +else + flags |=DRM_MODE_FLAG_PVSYNC ; + + drm_mode->flags = flags; + + drm_mode->type =0x48 ; +drm_mode_set_name (drm_mode); +} +
drivers/gpu/drm/msm/dp/dp_drm.c line 127
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+static void dp_bridge_pre_enable (struct drm_bridge *drm_bridge) +{ +int rc =0 ; +struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge) { +pr_err ("Invalid params\n" ); +return ; + }
bridge will always be valid.
drivers/gpu/drm/msm/dp/dp_drm.c line 128
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +2
-0+ bridge =to_dp_bridge (drm_bridge); + dp = bridge->display;
You can move these two up to the declaration and save yourself two more lines per function here and throughout.
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +24
-0+ +/* By this point mode should have been validated through mode_fixup */ + rc = dp->set_mode (dp, &bridge->dp_mode); +if (rc) { +pr_err ("[%d] failed to perform a mode set, rc=%d\n" , + bridge->id, rc); +return ; + } + + rc = dp->prepare (dp); +if (rc) { +pr_err ("[%d] DP display prepare failed, rc=%d\n" , + bridge->id, rc); +return ; + } + + rc = dp->enable (dp); +if (rc) { +pr_err ("[%d] DP display enable failed, rc=%d\n" , + bridge->id, rc); + dp->unprepare (dp); + } +} +
drivers/gpu/drm/msm/dp/dp_drm.c line 164
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+static void dp_bridge_enable (struct drm_bridge *drm_bridge) +{ +int rc =0 ; +struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge) { +pr_err ("Invalid params\n" ); +return ; + }
bridge will always be valid.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+ + bridge =to_dp_bridge (drm_bridge); + dp = bridge->display; + + rc = dp->post_enable (dp); +if (rc) +pr_err ("[%d] DP display post enable failed, rc=%d\n" , + bridge->id, rc); +} +
drivers/gpu/drm/msm/dp/dp_drm.c line 184
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+static void dp_bridge_disable (struct drm_bridge *drm_bridge) +{ +int rc =0 ; +struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge) { +pr_err ("Invalid params\n" ); +return ; + }
bridge will always be valid.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+ bridge =to_dp_bridge (drm_bridge); + dp = bridge->display; + + rc = dp->pre_disable (dp); +if (rc) { +pr_err ("[%d] DP display pre disable failed, rc=%d\n" , + bridge->id, rc); + } +} +
drivers/gpu/drm/msm/dp/dp_drm.c line 205
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+static void dp_bridge_post_disable (struct drm_bridge *drm_bridge) +{ +int rc =0 ; +struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge) { +pr_err ("Invalid params\n" ); +return ; + }
bridge will always be valid.
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +19
-0+ bridge =to_dp_bridge (drm_bridge); + dp = bridge->display; + + rc = dp->disable (dp); +if (rc) { +pr_err ("[%d] DP display disable failed, rc=%d\n" , + bridge->id, rc); +return ; + } + + rc = dp->unprepare (dp); +if (rc) { +pr_err ("[%d] DP display unprepare failed, rc=%d\n" , + bridge->id, rc); +return ; + } +} + +static void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
drivers/gpu/drm/msm/dp/dp_drm.c line 235
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge || !mode || !adjusted_mode) { +pr_err ("Invalid params\n" ); +return ; + }
bridge will always be valid. Not sure about mode or adjusted_mode, maybe you should use WARN_ON for those.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +12
-0+ + bridge =to_dp_bridge (drm_bridge); + dp = bridge->display; + +memset (&bridge->dp_mode,0x0 ,sizeof (struct dp_display_mode )); +convert_to_dp_mode (adjusted_mode, &bridge->dp_mode, dp); +} + +static bool dp_bridge_mode_fixup (struct drm_bridge *drm_bridge, +const struct drm_display_mode *mode, +struct drm_display_mode *adjusted_mode) +{
drivers/gpu/drm/msm/dp/dp_drm.c line 257
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+bool ret = true; +struct dp_display_mode dp_mode; +struct dp_bridge *bridge; +struct msm_dp *dp; + +if (!drm_bridge || !mode || !adjusted_mode) { +pr_err ("Invalid params\n" ); + ret = false; + goto end; + }
drm_bridge will always be valid, not positive about the other two.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +40
-0+ bridge =to_dp_bridge (drm_bridge); + dp = bridge->display; + +convert_to_dp_mode (mode, &dp_mode, dp); +convert_to_drm_mode (&dp_mode, adjusted_mode); +end: +return ret; +} + +static const struct drm_bridge_funcs dp_bridge_ops = { + .mode_fixup = dp_bridge_mode_fixup, + .pre_enable = dp_bridge_pre_enable, + .enable = dp_bridge_enable, + .disable = dp_bridge_disable, + .post_disable = dp_bridge_post_disable, + .mode_set = dp_bridge_mode_set, +}; + +int dp_connector_post_init (struct drm_connector *connector,void *display) +{ +struct msm_dp *dp_display = display; + +if (!dp_display) +return -EINVAL ; + + dp_display->connector = connector; +return 0 ; +} + +/** +* dp_connector_detect - callback to determine if connector is connected +* @connector: Pointer to drm connector structure +* @force: Force detect setting from drm framework +* Returns: Connector 'is connected' status +*/ +static enum drm_connector_status dp_connector_detect (struct drm_connector *conn, +bool force) +{ +enum drm_connector_status status = connector_status_unknown; +static enum drm_connector_status current_status = connector_status_unknown;
drivers/gpu/drm/msm/dp/dp_drm.c line 308
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+struct msm_dp *dp; +struct dp_connector *dp_conn; +struct msm_drm_private *priv = conn->dev->dev_private; +struct msm_kms *kms = priv->kms; + + dp_conn =to_dp_connector (conn); + dp = dp_conn->dp_display; + +pr_err ("is_connected = %s\n" , + (dp->is_connected) ?"true" :"false" );
Oops, this looks like a debug message.
drivers/gpu/drm/msm/dp/dp_drm.c line 318
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+ + status = (dp->is_connected) ? connector_status_connected : + connector_status_disconnected; + +if (dp->is_connected && dp->bridge->encoder + && (current_status != status) + && kms->funcs->set_encoder_mode) { + kms->funcs->set_encoder_mode (kms, + dp->bridge->encoder, false); +pr_err ("call set_encoder_mode\n" );
This too.
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +12
-0+ } + current_status = status; +return status; +} + +static void dp_connector_destroy (struct drm_connector *connector) +{ +struct dp_connector *dp_conn =to_dp_connector (connector); + +DBG ("" ); + +drm_connector_cleanup (connector);
drivers/gpu/drm/msm/dp/dp_drm.c line 340
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+ +kfree (dp_conn); +} + +void dp_connector_send_hpd_event (void *display) +{ +struct msm_dp *dp; + +if (!display) { +pr_err ("invalid input\n" );
Even if this is invalid, you don't need a error message. A WARN_ON if you must.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +14
-0+return ; + } + + dp = display; + +if (dp->send_hpd_event) + dp->send_hpd_event (dp); +} + +/** +* dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add() +* @connector: Pointer to drm connector structure +* Returns: Number of modes added +*/
drivers/gpu/drm/msm/dp/dp_drm.c line 364
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+static int dp_connector_get_modes (struct drm_connector *connector) +{ +int rc =0 ; +struct msm_dp *dp; +struct dp_display_mode *dp_mode =NULL ; +struct drm_display_mode *m, drm_mode; +struct dp_connector *dp_conn; + +if (!connector) +return 0 ;
Connector can never be NULL here.
+
drivers/gpu/drm/msm/dp/dp_drm.c line 367
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +2
-0+ dp_conn =to_dp_connector (connector); + dp = dp_conn->dp_display;
You can move these to the declaration.
drivers/gpu/drm/msm/dp/dp_drm.c line 371
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +3
-0+ dp_mode =kzalloc (sizeof (*dp_mode),GFP_KERNEL ); +if (!dp_mode) +return 0 ;
Return 0 on -ENOMEM?
drivers/gpu/drm/msm/dp/dp_drm.c line 378
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +7
-0+ +/* pluggable case assumes EDID is read when HPD */ +if (dp->is_connected) { + rc = dp->get_modes (dp, dp_mode); +if (!rc) +pr_err ("failed to get DP sink modes, rc=%d\n" , rc); +
Do you wnat to keep going here even if the get_modes failed?
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +9
-0+if (dp_mode->timing.pixel_clk_khz) {/* valid DP mode */ +memset (&drm_mode,0x0 ,sizeof (drm_mode)); +convert_to_drm_mode (dp_mode, &drm_mode); + m =drm_mode_duplicate (connector->dev, &drm_mode); +if (!m) { +pr_err ("failed to add mode %ux%u\n" , + drm_mode.hdisplay, + drm_mode.vdisplay); +kfree (dp_mode);
drivers/gpu/drm/msm/dp/dp_drm.c line 397
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+return 0 ; + } + m->width_mm = connector->display_info.width_mm; + m->height_mm = connector->display_info.height_mm; +drm_mode_probed_add (connector, m); + } + }else { +pr_err ("No sink connected\n" ); + } +kfree (dp_mode);
How big is dp_mode? You can't put it on the stack?
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +5
-0+ +return rc; +} + +int dp_drm_bridge_init (void *data,struct drm_encoder *encoder)
drivers/gpu/drm/msm/dp/dp_drm.c line 412
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+{ +int rc =0 ; +struct dp_bridge *dp_bridge; +struct drm_device *dev; +struct msm_dp *dp_display = data; +struct msm_drm_private *priv =NULL ; + + dp_bridge =kzalloc (sizeof (*dp_bridge),GFP_KERNEL ); +if (!dp_bridge) { + rc = -ENOMEM ;
Just return -ENOMEM;
Quoted 52 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +51
-0+ goto error; + } + + dev = dp_display->drm_dev; + dp_bridge->display = dp_display; + dp_bridge->base.funcs = &dp_bridge_ops; + dp_bridge->base.encoder = encoder; + + priv = dev->dev_private; + + rc =drm_bridge_attach (encoder, &dp_bridge->base,NULL ); +if (rc) { +pr_err ("failed to attach bridge, rc=%d\n" , rc); + goto error_free_bridge; + } + + rc = dp_display->request_irq (dp_display); +if (rc) { +pr_err ("request_irq failed, rc=%d\n" , rc); + goto error_free_bridge; + } + + encoder->bridge = &dp_bridge->base; + dp_display->dp_bridge = dp_bridge; + dp_display->bridge = &dp_bridge->base; + +return 0 ; +error_free_bridge: +kfree (dp_bridge); +error: +return rc; +} + +void dp_drm_bridge_deinit (void *data) +{ +struct msm_dp *display = data; +struct dp_bridge *bridge = display->dp_bridge; + +if (bridge && bridge->base.encoder) + bridge->base.encoder->bridge =NULL ; + +kfree (bridge); +} + +/** +* dp_connector_mode_valid - callback to determine if specified mode is valid +* @connector: Pointer to drm connector structure +* @mode: Pointer to drm mode structure +* Returns: Validity status for specified mode +*/ +static enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
drivers/gpu/drm/msm/dp/dp_drm.c line 473
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+ struct drm_display_mode *mode) +{ +struct msm_dp *dp_disp; +struct dp_debug *debug; +struct dp_connector *dp_conn; + +if (!mode || !connector) { +pr_err ("invalid params\n" ); +return MODE_ERROR ; + }
I'm sure connector will always be valid, not sure about mode.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +40
-0+ dp_conn =to_dp_connector (connector); + dp_disp = dp_conn->dp_display; + debug = dp_disp->get_debug (dp_disp); + + mode->vrefresh =drm_mode_vrefresh (mode); + +if (mode->clock > dp_disp->max_pclk_khz) +return MODE_BAD ; + +if (debug->debug_en && (mode->hdisplay != debug->hdisplay || + mode->vdisplay != debug->vdisplay || + mode->vrefresh != debug->vrefresh || + mode->picture_aspect_ratio != debug->aspect_ratio)) +return MODE_BAD ; + +return dp_disp->validate_mode (dp_disp, mode->clock); +} + +static const struct drm_connector_funcs dp_connector_funcs = { + .detect = dp_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = dp_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static const struct drm_connector_helper_funcs dp_connector_helper_funcs = { + .get_modes = dp_connector_get_modes, + .mode_valid = dp_connector_mode_valid, +}; + +/* connector initialization */ +struct drm_connector *dp_drm_connector_init (struct msm_dp *dp_display) +{ +struct drm_connector *connector =NULL ; +struct dp_connector *dp_connector; +int ret; + + dp_connector =kzalloc (sizeof (*dp_connector),GFP_KERNEL );
drivers/gpu/drm/msm/dp/dp_drm.c line 524
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +10
-0+if (!dp_connector) +return ERR_PTR (-ENOMEM ); + + dp_connector->dp_display = dp_display; + + connector = &dp_connector->base; + + ret =drm_connector_init (dp_display->drm_dev, connector, &dp_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); +if (ret)
You are missing a kfree here.
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +18
-0+return ERR_PTR (ret); + +drm_connector_helper_add (connector, &dp_connector_helper_funcs); + +/* +* Enable HPD to let hpd event is handled +* when cable is attached to the host. +*/ + connector->polled =DRM_CONNECTOR_POLL_HPD ; + +/* Display driver doesn't support interlace now. */ + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + +drm_connector_attach_encoder (connector, dp_display->encoder); + +return connector; +}drivers/gpu/drm/msm/dp/dp_drm.h new file +3
-0@@ -0,0 +1,52 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_drm.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_drm.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 269 lines
drivers/gpu/drm/msm/dp/dp_drm.h new file +38
-0+#ifndef _DP_DRM_H_ +#define _DP_DRM_H_ + +#include <linux/types.h> +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> + +#include "msm_drv.h" +#include "dp_display.h" + +struct dp_bridge { +struct drm_bridge base; +u32 id; + +struct msm_dp *display; +struct dp_display_mode dp_mode; +}; + +/** +* dp_connector_post_init - callback to perform additional initialization steps +* @connector: Pointer to drm connector structure +* @display: Pointer to private display handle +* Returns: Zero on success +*/ +int dp_connector_post_init (struct drm_connector *connector,void *display); + +void dp_connector_send_hpd_event (void *display); + +int dp_drm_bridge_init (void *display, +struct drm_encoder *encoder); + +void dp_drm_bridge_deinit (void *display); + +struct drm_connector *dp_drm_connector_init (struct msm_dp *dp_display); + +#endif /* _DP_DRM_H_ */ +drivers/gpu/drm/msm/dp/dp_extcon.c new file +225
-0@@ -0,0 +1,400 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/extcon.h> + +#include "dp_extcon.h" + +/* DP specific VDM commands */ +#define DP_USBPD_VDM_STATUS 0x10 +#define DP_USBPD_VDM_CONFIGURE 0x11 + +/* USBPD-TypeC specific Macros */ +#define VDM_VERSION 0x0 +#define USB_C_DP_SID 0xFF01 + +enum dp_usbpd_pin_assignment { +DP_USBPD_PIN_A , +DP_USBPD_PIN_B , +DP_USBPD_PIN_C , +DP_USBPD_PIN_D , +DP_USBPD_PIN_E , +DP_USBPD_PIN_F , +DP_USBPD_PIN_MAX , +}; + +struct dp_usbpd_capabilities { +enum dp_usbpd_port port; +bool receptacle_state; +u8 ulink_pin_config; +u8 dlink_pin_config; +}; + +struct dp_extcon_private { +u32 vdo; +struct device *dev; +struct notifier_block extcon_nb; +struct extcon_dev *extcon; +struct workqueue_struct *extcon_wq; +struct work_struct event_work; +struct usbpd *pd; +struct dp_usbpd_cb *dp_cb; +struct dp_usbpd_capabilities cap; +struct dp_usbpd dp_usbpd; +}; + +static const char *dp_usbpd_pin_name (u8 pin) +{ +switch (pin) { +case DP_USBPD_PIN_A :return "DP_USBPD_PIN_ASSIGNMENT_A" ; +case DP_USBPD_PIN_B :return "DP_USBPD_PIN_ASSIGNMENT_B" ; +case DP_USBPD_PIN_C :return "DP_USBPD_PIN_ASSIGNMENT_C" ; +case DP_USBPD_PIN_D :return "DP_USBPD_PIN_ASSIGNMENT_D" ; +case DP_USBPD_PIN_E :return "DP_USBPD_PIN_ASSIGNMENT_E" ; +case DP_USBPD_PIN_F :return "DP_USBPD_PIN_ASSIGNMENT_F" ; +default :return "UNKNOWN" ; + } +} + +static const char *dp_usbpd_port_name (enum dp_usbpd_port port) +{ +switch (port) { +case DP_USBPD_PORT_NONE :return "DP_USBPD_PORT_NONE" ; +case DP_USBPD_PORT_UFP_D :return "DP_USBPD_PORT_UFP_D" ; +case DP_USBPD_PORT_DFP_D :return "DP_USBPD_PORT_DFP_D" ; +case DP_USBPD_PORT_D_UFP_D :return "DP_USBPD_PORT_D_UFP_D" ; +default :return "DP_USBPD_PORT_NONE" ; + } +} + +static void dp_usbpd_init_port (enum dp_usbpd_port *port,u32 in_port) +{ +switch (in_port) { +case 0 : + *port =DP_USBPD_PORT_NONE ; +break ; +case 1 : + *port =DP_USBPD_PORT_UFP_D ; +break ; +case 2 : + *port =DP_USBPD_PORT_DFP_D ; +break ; +case 3 : + *port =DP_USBPD_PORT_D_UFP_D ; +break ; +default : + *port =DP_USBPD_PORT_NONE ; + } +pr_debug ("port:%s\n" ,dp_usbpd_port_name (*port)); +} + +void dp_usbpd_get_capabilities (struct dp_extcon_private *pd) +{ +struct dp_usbpd_capabilities *cap = &pd->cap; +u32 buf = pd->vdo; +int port = buf &0x3 ; + + cap->receptacle_state = (buf &BIT (6 )) ? true : false; + cap->dlink_pin_config = (buf >>8 ) &0xff ; + cap->ulink_pin_config = (buf >>16 ) &0xff ; + +dp_usbpd_init_port (&cap->port, port); +} + +void dp_usbpd_get_status (struct dp_extcon_private *pd) +{ +struct dp_usbpd *status = &pd->dp_usbpd; +u32 buf = pd->vdo; +int port = buf &0x3 ; + + status->low_pow_st = (buf &BIT (2 )) ? true : false; + status->adaptor_dp_en = (buf &BIT (3 )) ? true : false; + status->multi_func = (buf &BIT (4 )) ? true : false; + status->usb_config_req = (buf &BIT (5 )) ? true : false; + status->exit_dp_mode = (buf &BIT (6 )) ? true : false; + status->hpd_high = (buf &BIT (7 )) ? true : false; + status->hpd_irq = (buf &BIT (8 )) ? true : false; + +pr_debug ("low_pow_st = %d, adaptor_dp_en = %d, multi_func = %d\n" , + status->low_pow_st, status->adaptor_dp_en, + status->multi_func); +pr_debug ("usb_config_req = %d, exit_dp_mode = %d, hpd_high =%d\n" , + status->usb_config_req, + status->exit_dp_mode, status->hpd_high); +pr_debug ("hpd_irq = %d\n" , status->hpd_irq); + +dp_usbpd_init_port (&status->port, port); +} + +u32 dp_usbpd_gen_config_pkt (struct dp_extcon_private *pd) +{ +u8 pin_cfg, pin; +u32 config =0 ; +const u32 ufp_d_config =0x2 , dp_ver =0x1 ; + +if (pd->cap.receptacle_state) + pin_cfg = pd->cap.ulink_pin_config; +else + pin_cfg = pd->cap.dlink_pin_config; + +for (pin =DP_USBPD_PIN_A ; pin <DP_USBPD_PIN_MAX ; pin++) { +if (pin_cfg &BIT (pin)) { +if (pd->dp_usbpd.multi_func) { +if (pin ==DP_USBPD_PIN_D ) +break ; + }else { +break ; + } + } + } + +if (pin ==DP_USBPD_PIN_MAX ) + pin =DP_USBPD_PIN_C ; + +pr_debug ("pin assignment: %s\n" ,dp_usbpd_pin_name (pin)); + + config |=BIT (pin) <<8 ; + + config |= (dp_ver <<2 ); + config |= ufp_d_config; + +pr_debug ("config = 0x%x\n" , config); +return config; +} + +static int dp_extcon_connect (struct dp_usbpd *dp_usbpd,bool hpd) +{ +int rc =0 ; +struct dp_extcon_private *extcon; + +if (!dp_usbpd) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + } + + extcon = container_of(dp_usbpd, struct dp_extcon_private, dp_usbpd); + + dp_usbpd->hpd_high = hpd; + dp_usbpd->forced_disconnect = !hpd; + +if (hpd) + extcon->dp_cb->configure (extcon->dev); +else + extcon->dp_cb->disconnect (extcon->dev); + +error: +return rc; +} + +static int dp_extcon_get_lanes (struct dp_extcon_private *extcon_priv) +{ +union extcon_property_value property; +u8 lanes; + +if (!extcon_priv || !extcon_priv->extcon) { +pr_err ("Invalid input arguments\n" ); +return 0 ; + } + +extcon_get_property (extcon_priv->extcon, +EXTCON_DISP_DP , +EXTCON_PROP_USB_SS , + &property); + lanes = ((property.intval) ?2 :4 ); + +return lanes; +} + + +static void dp_extcon_event_work (struct work_struct *work)
drivers/gpu/drm/msm/dp/dp_extcon.c line 235
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +10
-0+{ +struct dp_extcon_private *extcon_priv; +int dp_state, ret; +int lanes; +union extcon_property_value property; + + extcon_priv =container_of (work, + struct dp_extcon_private, event_work); + +if (!extcon_priv || !extcon_priv->extcon) {
The result of container_of can never be NULL.
Quoted 58 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +58
-0+pr_err ("Invalid extcon device handler\n" ); +return ; + } + + dp_state =extcon_get_state (extcon_priv->extcon, +EXTCON_DISP_DP ); + +if (dp_state >0 ) { + ret =extcon_get_property (extcon_priv->extcon, +EXTCON_DISP_DP , +EXTCON_PROP_USB_TYPEC_POLARITY , + &property); +if (ret) { +pr_err ("Get Polarity property failed\n" ); +return ; + } + extcon_priv->dp_usbpd.orientation = + ((property.intval) ? +ORIENTATION_CC2 :ORIENTATION_CC1 ); + + lanes =dp_extcon_get_lanes (extcon_priv); +if (!lanes) +return ; + extcon_priv->dp_usbpd.multi_func = + ((lanes ==2 ) ? false : true); + +if (extcon_priv->dp_cb && extcon_priv->dp_cb->configure) +dp_extcon_connect (&extcon_priv->dp_usbpd, true); + }else { +if (extcon_priv->dp_cb && extcon_priv->dp_cb->disconnect) +dp_extcon_connect (&extcon_priv->dp_usbpd, false); + } +} + +static int dp_extcon_create_workqueue (struct dp_extcon_private *extcon_priv) +{ + extcon_priv->extcon_wq =create_singlethread_workqueue ("drm_dp_extcon" ); +if (IS_ERR_OR_NULL (extcon_priv->extcon_wq)) { +pr_err ("Error creating extcon wq\n" ); +return -EPERM ; + } + +INIT_WORK (&extcon_priv->event_work, dp_extcon_event_work); + +return 0 ; +} + +static int dp_extcon_event_notify (struct notifier_block *nb, +unsigned long event,void *priv) +{ +struct dp_extcon_private *extcon_priv; + + extcon_priv = container_of(nb, struct dp_extcon_private, + extcon_nb); + +queue_work (extcon_priv->extcon_wq, &extcon_priv->event_work); +return NOTIFY_DONE ; +}
drivers/gpu/drm/msm/dp/dp_extcon.c line 303
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +10
-0+ +int dp_extcon_register (struct dp_usbpd *dp_usbpd) +{ +struct dp_extcon_private *extcon_priv; +int ret =0 ; + +if (!dp_usbpd) +return -EINVAL ; + +pr_err ("Start++++" );
Debug message snuck through.
drivers/gpu/drm/msm/dp/dp_extcon.c line 312
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +9
-0+ extcon_priv = container_of(dp_usbpd, struct dp_extcon_private, dp_usbpd); + + extcon_priv->extcon_nb.notifier_call = dp_extcon_event_notify; + ret =devm_extcon_register_notifier (extcon_priv->dev, extcon_priv->extcon, +EXTCON_DISP_DP , + &extcon_priv->extcon_nb); +if (ret) { +dev_err (extcon_priv->dev, +"register EXTCON_DISP_DP notifier err\n" );
Prefer that you don't abbreviate err here.
drivers/gpu/drm/msm/dp/dp_extcon.c line 313
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_extcon.c new file +1
-0+ ret = -EINVAL ;
You set ret, but you don't do anything with it - you continue on.
drivers/gpu/drm/msm/dp/dp_extcon.c line 322
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +9
-0+ } + + ret =dp_extcon_create_workqueue (extcon_priv); +if (ret) { +pr_err ("Failed to create workqueue\n" ); +dp_extcon_unregister (dp_usbpd); + } + +pr_err ("End----" );
Also debug message.
drivers/gpu/drm/msm/dp/dp_extcon.c line 331
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +9
-0+return ret; +} + +void dp_extcon_unregister (struct dp_usbpd *dp_usbpd) +{ +struct dp_extcon_private *extcon_priv; + +if (!dp_usbpd) { +pr_err ("Invalid input\n" );
Doesn't seem that the error message will do you much good here.
drivers/gpu/drm/msm/dp/dp_extcon.c line 303
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +4
-0+return ; + } + +pr_err ("Start++++" );
Debug log message
drivers/gpu/drm/msm/dp/dp_extcon.c line 345
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +10
-0+ extcon_priv = container_of(dp_usbpd, struct dp_extcon_private, dp_usbpd); + +devm_extcon_unregister_notifier (extcon_priv->dev, extcon_priv->extcon, +EXTCON_DISP_DP , + &extcon_priv->extcon_nb); + +if (extcon_priv->extcon_wq) +destroy_workqueue (extcon_priv->extcon_wq); + +pr_err ("End----" );
Debug log message
drivers/gpu/drm/msm/dp/dp_extcon.c line 356
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +11
-0+return ; +} + +struct dp_usbpd *dp_extcon_get (struct device *dev,struct dp_usbpd_cb *cb) +{ +int rc =0 ; +struct dp_extcon_private *dp_extcon; +struct dp_usbpd *dp_usbpd; + +if (!cb) { +pr_err ("invalid cb data\n" );
Log message isn't useful, just return ERR_PTR(-EINVAL);
drivers/gpu/drm/msm/dp/dp_extcon.c line 361
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +5
-0+ rc = -EINVAL ; + goto error; + } + +pr_err ("%s: Start" , __func__);
Debug message.
drivers/gpu/drm/msm/dp/dp_extcon.c line 363
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +2
-0+ dp_extcon =devm_kzalloc (dev,sizeof (*dp_extcon),GFP_KERNEL ); +if (!dp_extcon) {
return ERR_PTR(-ENOMEM);
drivers/gpu/drm/msm/dp/dp_extcon.c line 372
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +9
-0+ rc = -ENOMEM ; + goto error; + } + + dp_extcon->extcon =extcon_get_edev_by_phandle (dev,0 ); +if (!dp_extcon->extcon) { +pr_err ("invalid extcon data\n" ); + rc = -EINVAL ; +devm_kfree (dev, dp_extcon);
Just return ERR_PTR(-EINVAL);
drivers/gpu/drm/msm/dp/dp_extcon.c line 382
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +10
-0+ goto error; + } + + dp_extcon->dev = dev; + dp_extcon->dp_cb = cb; + + dp_extcon->dp_usbpd.connect = dp_extcon_connect; + dp_usbpd = &dp_extcon->dp_usbpd; + +pr_err ("%s: end" , __func__);
Debug message
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +5
-0+return dp_usbpd; +error: +return ERR_PTR (rc); +} +
drivers/gpu/drm/msm/dp/dp_extcon.c line 397
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +10
-0+void dp_extcon_put (struct dp_usbpd *dp_usbpd) +{ +struct dp_extcon_private *extcon; + +if (!dp_usbpd) +return ; + + extcon = container_of(dp_usbpd, struct dp_extcon_private, dp_usbpd); + +devm_kfree (extcon->dev, extcon);
You don't need to do this for managed memory. This whole function doesn't need to exist.
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +3
-0+ +pr_err ("%s: end" , __func__); +}drivers/gpu/drm/msm/dp/dp_extcon.h new file +3
-0@@ -0,0 +1,111 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_extcon.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please
Quoted 106 lines
drivers/gpu/drm/msm/dp/dp_extcon.h new file +97
-0+#ifndef _DP_EXTCON_H_ +#define _DP_EXTCON_H_ + +//#include <linux/usb/usbpd.h> + +#include <linux/types.h> +#include <linux/device.h> + +/** +* enum dp_usbpd_port - usb/dp port type +* @DP_USBPD_PORT_NONE: port not configured +* @DP_USBPD_PORT_UFP_D: Upstream Facing Port - DisplayPort +* @DP_USBPD_PORT_DFP_D: Downstream Facing Port - DisplayPort +* @DP_USBPD_PORT_D_UFP_D: Both UFP & DFP - DisplayPort +*/ + +enum dp_usbpd_port { +DP_USBPD_PORT_NONE , +DP_USBPD_PORT_UFP_D , +DP_USBPD_PORT_DFP_D , +DP_USBPD_PORT_D_UFP_D , +}; + +enum plug_orientation { +ORIENTATION_NONE , +ORIENTATION_CC1 , +ORIENTATION_CC2 , +}; + +/** +* struct dp_usbpd - DisplayPort status +* +* @port: port configured +* orientation: plug orientation configuration +* @low_pow_st: low power state +* @adaptor_dp_en: adaptor functionality enabled +* @multi_func: multi-function preferred +* @usb_config_req: request to switch to usb +* @exit_dp_mode: request exit from displayport mode +* @hpd_high: Hot Plug Detect signal is high. +* @hpd_irq: Change in the status since last message +* @alt_mode_cfg_done: bool to specify alt mode status +* @debug_en: bool to specify debug mode +* @connect: simulate disconnect or connect for debug mode +*/ +struct dp_usbpd { +enum dp_usbpd_port port; +enum plug_orientation orientation; +bool low_pow_st; +bool adaptor_dp_en; +bool multi_func; +bool usb_config_req; +bool exit_dp_mode; +bool hpd_high; +bool hpd_irq; +bool alt_mode_cfg_done; +bool debug_en; +bool forced_disconnect; + +int (*connect)(struct dp_usbpd *dp_usbpd,bool hpd); +}; + +/** +* struct dp_usbpd_cb - callback functions provided by the client +* +* @configure: called by usbpd module when PD communication has +* been completed and the usb peripheral has been configured on +* dp mode. +* @disconnect: notify the cable disconnect issued by usb. +* @attention: notify any attention message issued by usb. +*/ +struct dp_usbpd_cb { +int (*configure)(struct device *dev); +int (*disconnect)(struct device *dev); +int (*attention)(struct device *dev); +}; + +/** +* dp_extcon_get() - setup usbpd module +* +* @dev: device instance of the caller +* @cb: struct containing callback function pointers. +* +* This function allows the client to initialize the usbpd +* module. The module will communicate with usb driver and +* handles the power delivery (PD) communication with the +* sink/usb device. This module will notify the client using +* the callback functions about the connection and status. +*/ +struct dp_usbpd *dp_extcon_get (struct device *dev,struct dp_usbpd_cb *cb); + +void dp_extcon_put (struct dp_usbpd *pd); + +int dp_extcon_register (struct dp_usbpd *dp_usbpd); +void dp_extcon_unregister (struct dp_usbpd *dp_usbpd); + +#endif /* _DP_EXTCON_H_ */ drivers/gpu/drm/msm/dp/dp_link.c new file +3
-0@@ -0,0 +1,1549 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_link.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 104 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +104
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include "dp_link.h" +#include "dp_panel.h" + +enum dynamic_range { +DP_DYNAMIC_RANGE_RGB_VESA =0x00 , +DP_DYNAMIC_RANGE_RGB_CEA =0x01 , +DP_DYNAMIC_RANGE_UNKNOWN =0xFFFFFFFF , +}; + +enum audio_sample_rate { +AUDIO_SAMPLE_RATE_32_KHZ =0x00 , +AUDIO_SAMPLE_RATE_44_1_KHZ =0x01 , +AUDIO_SAMPLE_RATE_48_KHZ =0x02 , +AUDIO_SAMPLE_RATE_88_2_KHZ =0x03 , +AUDIO_SAMPLE_RATE_96_KHZ =0x04 , +AUDIO_SAMPLE_RATE_176_4_KHZ =0x05 , +AUDIO_SAMPLE_RATE_192_KHZ =0x06 , +}; + +enum audio_pattern_type { +AUDIO_TEST_PATTERN_OPERATOR_DEFINED =0x00 , +AUDIO_TEST_PATTERN_SAWTOOTH =0x01 , +}; + +struct dp_link_request { +u32 test_requested; +u32 test_link_rate; +u32 test_lane_count; +}; + +struct dp_link_private { +u32 prev_sink_count; +struct device *dev; +struct dp_aux *aux; +struct dp_link dp_link; + +struct dp_link_request request; +u8 link_status[DP_LINK_STATUS_SIZE ]; +}; + +static char *dp_link_get_audio_test_pattern (u32 pattern) +{ +switch (pattern) { +case AUDIO_TEST_PATTERN_OPERATOR_DEFINED : +return DP_LINK_ENUM_STR (AUDIO_TEST_PATTERN_OPERATOR_DEFINED ); +case AUDIO_TEST_PATTERN_SAWTOOTH : +return DP_LINK_ENUM_STR (AUDIO_TEST_PATTERN_SAWTOOTH ); +default : +return "unknown" ; + } +} + +static char *dp_link_get_audio_sample_rate (u32 rate) +{ +switch (rate) { +case AUDIO_SAMPLE_RATE_32_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_32_KHZ ); +case AUDIO_SAMPLE_RATE_44_1_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_44_1_KHZ ); +case AUDIO_SAMPLE_RATE_48_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_48_KHZ ); +case AUDIO_SAMPLE_RATE_88_2_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_88_2_KHZ ); +case AUDIO_SAMPLE_RATE_96_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_96_KHZ ); +case AUDIO_SAMPLE_RATE_176_4_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_176_4_KHZ ); +case AUDIO_SAMPLE_RATE_192_KHZ : +return DP_LINK_ENUM_STR (AUDIO_SAMPLE_RATE_192_KHZ ); +default : +return "unknown" ; + } +} + +static int dp_link_get_period (struct dp_link_private *link,int const addr) +{ +int ret =0 ; +u8 bp; +u8 data; +u32 const param_len =0x1 ; +u32 const max_audio_period =0xA ; + +/* TEST_AUDIO_PERIOD_CH_XX */ +if (drm_dp_dpcd_read (link->aux->drm_aux, addr, &bp, + param_len) < param_len) { +pr_err ("failed to read test_audio_period (0x%x)\n" , addr); + ret = -EINVAL ; + goto exit; + } + + data = bp; + +/* Period - Bits 3:0 */ + data = data &0xF ; +if ((int )data > max_audio_period) { +pr_err ("invalid test_audio_period_ch_1 = 0x%x\n" , data); + ret = -EINVAL ; + goto exit; + } + + ret = data; +exit:
drivers/gpu/drm/msm/dp/dp_link.c line 128
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+return ret; +} + +static int dp_link_parse_audio_channel_period (struct dp_link_private *link) +{ +int ret =0 ; +struct dp_link_test_audio *req = &link->dp_link.test_audio; + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH1 ); +if (ret == -EINVAL )
You don't need the label for any of these.
Quoted 46 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +46
-0+ goto exit; + + req->test_audio_period_ch_1 = ret; +pr_debug ("test_audio_period_ch_1 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH2 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_2 = ret; +pr_debug ("test_audio_period_ch_2 = 0x%x\n" , ret); + +/* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */ + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH3 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_3 = ret; +pr_debug ("test_audio_period_ch_3 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH4 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_4 = ret; +pr_debug ("test_audio_period_ch_4 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH5 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_5 = ret; +pr_debug ("test_audio_period_ch_5 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH6 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_6 = ret; +pr_debug ("test_audio_period_ch_6 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH7 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_7 = ret;
drivers/gpu/drm/msm/dp/dp_link.c line 184
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+pr_debug ("test_audio_period_ch_7 = 0x%x\n" , ret); + + ret =dp_link_get_period (link,DP_TEST_AUDIO_PERIOD_CH8 ); +if (ret == -EINVAL ) + goto exit; + + req->test_audio_period_ch_8 = ret; +pr_debug ("test_audio_period_ch_8 = 0x%x\n" , ret); +exit: +return ret;
This isn't my area of expertise but I can't shake the feeling that this code could be consolidated - like why are there individual members for req->test_audio_period_ch_N and not an array. Like I said, not my area, just feel like there is code that could be saved.
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +5
-0+} + +static int dp_link_parse_audio_pattern_type (struct dp_link_private *link) +{ +int ret =0 ;
drivers/gpu/drm/msm/dp/dp_link.c line 199
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+u8 bp; +u8 data; +int rlen; +int const param_len =0x1 ; +int const max_audio_pattern_type =0x1 ; + + rlen =drm_dp_dpcd_read (link->aux->drm_aux, +DP_TEST_AUDIO_PATTERN_TYPE , &bp, param_len); +if (rlen < param_len) { +pr_err ("failed to read link audio mode data\n" );
just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_link.c line 208
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +9
-0+ ret = -EINVAL ; + goto exit; + } + data = bp; + +/* Audio Pattern Type - Bits 7:0 */ +if ((int )data > max_audio_pattern_type) { +pr_err ("invalid audio pattern type = 0x%x\n" , data); + ret = -EINVAL ;
just return -EINVAL;
drivers/gpu/drm/msm/dp/dp_link.c line 216
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +8
-0+ goto exit; + } + + link->dp_link.test_audio.test_audio_pattern_type = data; +pr_debug ("audio pattern type = %s\n" , +dp_link_get_audio_test_pattern (data)); +exit: +return ret;
return 0;
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +9
-0+} + +static int dp_link_parse_audio_mode (struct dp_link_private *link) +{ +int ret =0 ; +u8 bp; +u8 data; +int rlen; +int const param_len =0x1 ;
drivers/gpu/drm/msm/dp/dp_link.c line 235
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+int const max_audio_sampling_rate =0x6 ; +int const max_audio_channel_count =0x8 ; +int sampling_rate =0x0 ; +int channel_count =0x0 ; + + rlen =drm_dp_dpcd_read (link->aux->drm_aux,DP_TEST_AUDIO_MODE , + &bp, param_len); +if (rlen < param_len) { +pr_err ("failed to read link audio mode data\n" ); + ret = -EINVAL ;
Same as above - you should almost never have a just a return after a label. Same is true for much of this file.
Quoted 29 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +29
-0+ goto exit; + } + data = bp; + +/* Sampling Rate - Bits 3:0 */ + sampling_rate = data &0xF ; +if (sampling_rate > max_audio_sampling_rate) { +pr_err ("sampling rate (0x%x) greater than max (0x%x)\n" , + sampling_rate, max_audio_sampling_rate); + ret = -EINVAL ; + goto exit; + } + +/* Channel Count - Bits 7:4 */ + channel_count = ((data &0xF0 ) >>4 ) +1 ; +if (channel_count > max_audio_channel_count) { +pr_err ("channel_count (0x%x) greater than max (0x%x)\n" , + channel_count, max_audio_channel_count); + ret = -EINVAL ; + goto exit; + } + + link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate; + link->dp_link.test_audio.test_audio_channel_count = channel_count; +pr_debug ("sampling_rate = %s, channel_count = 0x%x\n" , +dp_link_get_audio_sample_rate (sampling_rate), channel_count); +exit: +return ret; +}
<snip>
drivers/gpu/drm/msm/dp/dp_link.c line 961
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +9
-0+static void dp_link_send_test_response (struct dp_link *dp_link) +{ +struct dp_link_private *link =NULL ; +u32 const response_len =0x1 ; + +if (!dp_link) { +pr_err ("invalid input\n" ); +return ; + }
It doesn't look to me like dp_link can be NULL here.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +6
-0+ link = container_of(dp_link, struct dp_link_private, dp_link); + +drm_dp_dpcd_write (link->aux->drm_aux,DP_TEST_RESPONSE , + &dp_link->test_response, response_len); +} +
drivers/gpu/drm/msm/dp/dp_link.c line 978
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +10
-0+static int dp_link_psm_config (struct dp_link *dp_link, +struct drm_dp_link *link_info,bool enable) +{ +struct dp_link_private *link =NULL ; +int ret =0 ; + +if (!dp_link) { +pr_err ("invalid params\n" ); +return -EINVAL ; + }
Same. It seems that all of these function pointers have a verified valid dp_link before calling.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +15
-0+ link = container_of(dp_link, struct dp_link_private, dp_link); + +if (enable) + ret =drm_dp_link_power_down (link->aux->drm_aux, link_info); +else + ret =drm_dp_link_power_up (link->aux->drm_aux, link_info); + +if (ret) +pr_err ("Failed to %s low power mode\n" , + (enable ?"enter" :"exit" )); +else + dp_link->psm_enabled = enable; + +return ret; +}
<snip>
drivers/gpu/drm/msm/dp/dp_link.c line 1467
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +12
-0+static int dp_link_send_psm_request (struct dp_link *dp_link,bool req) +{ +struct dp_link_private *link; + +if (!dp_link) { +pr_err ("invalid input\n" ); +return -EINVAL ; + } + + link = container_of(dp_link, struct dp_link_private, dp_link);Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This function looks like it doesn't do anything of value.
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.
Dev and aux both appear to be non NULL from the claler.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_link.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.
This should be -ENOMEM and you should just return ERR_PTR(-ENOMEM);
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.
Label should not be 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.
You don't need to delete devm_ managed memory.
drivers/gpu/drm/msm/dp/dp_link.h
Quoted 20 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 +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
SPDX please.
drivers/gpu/drm/msm/dp/dp_link.h
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_link.h 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.
The last item in a enum will be the value of the previous item plus 1 - which is really the only good reason to use a enum IMO. You don't need to assign it which is good because if you ever added anything to this list it would take two lines of change and not just one.
drivers/gpu/drm/msm/dp/dp_link.h
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_link.h 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.
drivers/gpu/drm/msm/dp/dp_link.h
Quoted 94 lines
drivers/gpu/drm/msm/dp/dp_link.h new file +94
-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 a bit beefy for a inline for my tastes.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 73 lines
drivers/gpu/drm/msm/dp/dp_link.h new file +54
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_panel.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.
SPDX please.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
An enum of 1 is never useful.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 43 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
It appears that dp_panel will always be valid at every call point.
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.
Just return -ENVAL here and everywhere else end: is used.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 55 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +55
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_panel will always be valid.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_panel.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 usint const variables just set the variables directly.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
It doesn't look like a return value is needed here.
And maybe this function isn't needed at all? This could all happen inline where this function is called.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
dp_panel will always be valid.
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.
You don't need an error here because the error prints an error on your behalf and you certainly don't want to print 10 errors without more details about what the failure actually was.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
My edid parsing days were over back when DVI was new and interesting but as just a kernel developer this seems odd. I'll leave it to the experts.
But at least I would use a valid for() loop:
for(retry_cnt = 0; retry_cnt < 10; retry_cnt++) {
..
}drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
Looks like both of these are valid from the caller.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 63 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +62
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_panel and mode_edid_bpp are valid from the caller, not sure about mode_pcklk_hz. Might want to use a WARN_ON for that one.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
Panel will always be valid.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 63 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +62
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
panel should always be valid.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
What is the valid return of this function? Is it supposed to be boolean?
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
Indentation is suspect here.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
You don't need a log message here. Maybe a WARN_ON.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
Panel can't be NULL here.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 21 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
This likely can't be NULL.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 55 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
This likely can't be NULL.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 61 lines
drivers/gpu/drm/msm/dp/dp_panel.c new file +60
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
dp_panel can't be NULL.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
It doesn't seem like this function should return anything.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
dp_panel_can't be NULL.
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_panel.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.
It looks like none of these are likely to be NULL;
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_panel.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 ERR_PTR(-ENOMEM);
drivers/gpu/drm/msm/dp/dp_panel.c
Quoted 39 lines
drivers/gpu/drm/msm/dp/dp_panel.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 to do this for devm managed memory.
drivers/gpu/drm/msm/dp/dp_panel.h
Quoted 20 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 +13
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
SPDX please.
drivers/gpu/drm/msm/dp/dp_panel.h
Quoted 107 lines
drivers/gpu/drm/msm/dp/dp_panel.h new file +107
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
And I'll end here for for now.
Jordan
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.
Re: [DPU PATCH 2/3] drm/msm/dp: add displayPort driver support
In reply to a message not in the archiveQuoted 32 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.Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 15 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 ++++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 +++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1475 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 ++ drivers/gpu/drm/msm/dp/dp_display.c | 977 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 55 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 ++++++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 ++++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 +++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 ++++++++++++
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_parser.h | 205 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 599 +++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 57 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 ++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 30 files changed, 10887 insertions(+), 1 deletion(-)
This is my last go - the end is in sight.
<snip all the way to dp_parser.c>
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +3
-0@@ -0,0 +1,679 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_parser.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +12
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/of_gpio.h> + +#include "dp_parser.h" + +static void dp_parser_unmap_io_resources (struct dp_parser *parser) +{ +struct dp_io *io = &parser->io; + +msm_dss_iounmap (&io->dp_ahb); +msm_dss_iounmap (&io->dp_aux);
drivers/gpu/drm/msm/dp/dp_parser.c line 36
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+msm_dss_iounmap (&io->dp_link); +msm_dss_iounmap (&io->dp_p0); +msm_dss_iounmap (&io->phy_io); +msm_dss_iounmap (&io->ln_tx0_io); +msm_dss_iounmap (&io->ln_tx0_io); +msm_dss_iounmap (&io->dp_pll_io); +msm_dss_iounmap (&io->dp_cc_io); +msm_dss_iounmap (&io->usb3_dp_com); +msm_dss_iounmap (&io->qfprom_io); +}
If you use devm_ to ioremap as suggested previously, then this all ends up going away.
drivers/gpu/drm/msm/dp/dp_parser.c line 50
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +13
-0+static int dp_parser_ctrl_res (struct dp_parser *parser) +{ +int rc =0 ; +u32 index; +struct platform_device *pdev = parser->pdev; +struct device_node *of_node = parser->pdev->dev.of_node; +struct dp_io *io = &parser->io; + + rc =of_property_read_u32 (of_node,"cell-index" , &index); +if (rc) { +pr_err ("cell-index not specified, rc=%d\n" , rc); + goto err; + }
This value doesn't appear to be used anywhere in this code, so why are you grabbing it?
drivers/gpu/drm/msm/dp/dp_parser.c line 54
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +3
-0+ rc =msm_dss_ioremap_byname (pdev, &io->dp_ahb,"dp_ahb" ); +if (rc) { +pr_err ("unable to remap dp io resources\n" );
msm_ioremap() helpfully gives an informative error message including the name of the region that failed so you don't need a redundant message here.
Quoted 49 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +49
-0+ goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->dp_aux,"dp_aux" ); +if (rc) { +pr_err ("unable to remap dp io resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->dp_link,"dp_link" ); +if (rc) { +pr_err ("unable to remap dp io resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->dp_p0,"dp_p0" ); +if (rc) { +pr_err ("unable to remap dp io resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->phy_io,"dp_phy" ); +if (rc) { +pr_err ("unable to remap dp PHY resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->ln_tx0_io,"dp_ln_tx0" ); +if (rc) { +pr_err ("unable to remap dp TX0 resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->ln_tx1_io,"dp_ln_tx1" ); +if (rc) { +pr_err ("unable to remap dp TX1 resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->dp_pll_io,"dp_pll" ); +if (rc) { +pr_err ("unable to remap DP PLL resources\n" ); + goto err; + } + + rc =msm_dss_ioremap_byname (pdev, &io->usb3_dp_com,"usb3_dp_com" ); +if (rc) { +pr_err ("unable to remap USB3 DP com resources\n" ); + goto err;
drivers/gpu/drm/msm/dp/dp_parser.c line 113
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ } + +if (msm_dss_ioremap_byname (pdev, &io->dp_cc_io,"dp_mmss_cc" )) { +pr_err ("unable to remap dp MMSS_CC resources\n" ); + goto err; + } + +if (msm_dss_ioremap_byname (pdev, &io->qfprom_io,"qfprom_physical" )) +pr_warn ("unable to remap dp qfprom resources\n" ); +
It doesn't look like you are using this in the current code so you can remove it but if you did need to read fuses use nvram_cell instead.
drivers/gpu/drm/msm/dp/dp_parser.c line 118
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+return 0 ; +err: +dp_parser_unmap_io_resources (parser); +return rc; +}
This whole function is crying out for an array:
struct {
void __iomem **base;
const char *name;
} regions[] = {
{ &io->dp_aux.base, "dp_aux" },
...
{ &io->dp_cc_io.base, "dp_mms_cc" },
{ NULL, NULL }
};for(i = 0; regions[i].name; i++) {
void __iomem *ptr = msm_ioremap(pdev, regions[i].name, NULL);
if (IS_ERR(ptr))
return -ENODEV;
*(regions[i].base) = ptr;
}return 0;
Quoted 18 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +18
-0+ +static const char *dp_get_phy_aux_config_property (u32 cfg_type) +{ +switch (cfg_type) { +case PHY_AUX_CFG0 : +return "qcom,aux-cfg0-settings" ; +case PHY_AUX_CFG1 : +return "qcom,aux-cfg1-settings" ; +case PHY_AUX_CFG2 : +return "qcom,aux-cfg2-settings" ; +case PHY_AUX_CFG3 : +return "qcom,aux-cfg3-settings" ; +case PHY_AUX_CFG4 : +return "qcom,aux-cfg4-settings" ; +case PHY_AUX_CFG5 : +return "qcom,aux-cfg5-settings" ; +case PHY_AUX_CFG6 : +return "qcom,aux-cfg6-settings" ;
drivers/gpu/drm/msm/dp/dp_parser.c line 146
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+case PHY_AUX_CFG7 : +return "qcom,aux-cfg7-settings" ; +case PHY_AUX_CFG8 : +return "qcom,aux-cfg8-settings" ; +case PHY_AUX_CFG9 : +return "qcom,aux-cfg9-settings" ; +default : +return "unknown" ; + } +}
Since CFG0 is 0 and CFG1 is and so on instead of calling
a function you can just construct the string inline when you need it....
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +7
-0+static void dp_parser_phy_aux_cfg_reset (struct dp_parser *parser) +{ +int i =0 ; + +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) + parser->aux_cfg[i] = (const struct dp_aux_cfg ){0 }; +}
drivers/gpu/drm/msm/dp/dp_parser.c line 164
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ +static int dp_parser_aux (struct dp_parser *parser) +{ +struct device_node *of_node = parser->pdev->dev.of_node; +int len =0 , i =0 , j =0 , config_count =0 ; +const char *data; +int const minimum_config_count =1 ; + +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) { +const char *property =dp_get_phy_aux_config_property (i);
Here, instead of this, do
char property[24];snprintf(property, sizeof(property), "qcom,aux-cfg%d-settings", i);
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +17
-0+ data =of_get_property (of_node, property, &len); +if (!data) { +pr_err ("Unable to read %s\n" , property); + goto error; + } + + config_count = len -1 ; +if ((config_count < minimum_config_count) || + (config_count >DP_AUX_CFG_MAX_VALUE_CNT )) { +pr_err ("Invalid config count (%d) configs for %s\n" , + config_count, property); + goto error; + } + + parser->aux_cfg[i].offset = data[0 ]; + parser->aux_cfg[i].cfg_cnt = config_count; + pr_debug("%s offset=0x%x, cfg_cnt=%d\n",
drivers/gpu/drm/msm/dp/dp_parser.c line 192
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ property, + parser->aux_cfg[i].offset, + parser->aux_cfg[i].cfg_cnt); +for (j =1 ; j < len; j++) { + parser->aux_cfg[i].lut[j -1 ] = data[j]; +pr_debug ("%s lut[%d]=0x%x\n" , + property, + i, + parser->aux_cfg[i].lut[j -1 ]); + }
qcom,aux-cfgN-settings appears to be an array. Seems like it would be easier just to use of_property_read_u32_array()? Seems like it would save yourself a bit of work.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +7
-0+ } +return 0 ; + +error: +dp_parser_phy_aux_cfg_reset (parser); +return -EINVAL ; +}
drivers/gpu/drm/msm/dp/dp_parser.c line 209
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ +static int dp_parser_misc (struct dp_parser *parser) +{ +int rc =0 ; +struct device_node *of_node = parser->pdev->dev.of_node; + + rc =of_property_read_u32 (of_node, +"qcom,max-pclk-frequency-khz" , &parser->max_pclk_khz); +if (rc) + parser->max_pclk_khz =DP_MAX_PIXEL_CLK_KHZ ;
On error, of_property_read_u32 and friends will not touch the passed in pointer, so you can safely set the pointer to a default and then not worry about checking the value of the function - so this can just turn into:
parser->max_pclk_hz = DP_MAX_PIXEL_CLK_KHZ; of_property_read_u32(of_node, "qcom,max-pclk-frequency-khz", &parser->max_pclk_khz);
drivers/gpu/drm/msm/dp/dp_parser.c line 206
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +2
-0+ +return 0 ;
This function doesn't need to return anything. And technically, it doesn't need to be a function, but the place where it gets called is entirely comprised of functions so thats probably not a huge deal.
drivers/gpu/drm/msm/dp/dp_parser.c line 221
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+} + +static int dp_parser_pinctrl (struct dp_parser *parser) +{ +int rc =0 ; +struct dp_pinctrl *pinctrl = &parser->pinctrl; + + pinctrl->pin =devm_pinctrl_get (&parser->pdev->dev); + +if (IS_ERR_OR_NULL (pinctrl->pin)) {
It looks to me like pinctrl_get only returns ERR_PTR so you can just use IS_ERR() for your check.
drivers/gpu/drm/msm/dp/dp_parser.c line 223
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +2
-0+ rc =PTR_ERR (pinctrl->pin); +pr_err ("failed to get pinctrl, rc=%d\n" , rc);
And you can just return PTR_ERR(pinctrl->pin) here
drivers/gpu/drm/msm/dp/dp_parser.c line 229
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +6
-0+ goto error; + } + + pinctrl->state_active =pinctrl_lookup_state (pinctrl->pin, +"mdss_dp_active" ); +if (IS_ERR_OR_NULL (pinctrl->state_active)) {
Same.
drivers/gpu/drm/msm/dp/dp_parser.c line 237
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +8
-0+ rc =PTR_ERR (pinctrl->state_active); +pr_err ("failed to get pinctrl active state, rc=%d\n" , rc); + goto error; + } + + pinctrl->state_suspend =pinctrl_lookup_state (pinctrl->pin, +"mdss_dp_sleep" ); +if (IS_ERR_OR_NULL (pinctrl->state_suspend)) {
Same
drivers/gpu/drm/msm/dp/dp_parser.c line 243
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +6
-0+ rc =PTR_ERR (pinctrl->state_suspend); +pr_err ("failed to get pinctrl suspend state, rc=%d\n" , rc); + goto error; + } +error: +return rc;
You don't need this label if you return as soon as you get the error.
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +36
-0+} + +static int dp_parser_gpio (struct dp_parser *parser) +{ +int i =0 ; +struct device *dev = &parser->pdev->dev; +struct device_node *of_node = dev->of_node; +struct dss_module_power *mp = &parser->mp[DP_CORE_PM ]; +static const char *const dp_gpios[] = { +"qcom,aux-en-gpio" , +"qcom,aux-sel-gpio" , +"qcom,usbplug-cc-gpio" , + }; + + mp->gpio_config =devm_kzalloc (dev, +sizeof (struct dss_gpio ) *ARRAY_SIZE (dp_gpios),GFP_KERNEL ); +if (!mp->gpio_config) +return -ENOMEM ; + + mp->num_gpio =ARRAY_SIZE (dp_gpios); + +for (i =0 ; i <ARRAY_SIZE (dp_gpios); i++) { + mp->gpio_config[i].gpio =of_get_named_gpio (of_node, + dp_gpios[i],0 ); + +if (!gpio_is_valid (mp->gpio_config[i].gpio)) { +pr_err ("%s gpio not specified\n" , dp_gpios[i]); +return -EINVAL ; + } + +strlcpy (mp->gpio_config[i].gpio_name, dp_gpios[i], +sizeof (mp->gpio_config[i].gpio_name)); + + mp->gpio_config[i].value =0 ; + } +
drivers/gpu/drm/msm/dp/dp_parser.c line 289
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+return 0 ; +} + +static const char *dp_parser_supply_node_name (enum dp_pm_type module) +{ +switch (module) { +case DP_CORE_PM :return "qcom,core-supply-entries" ; +case DP_CTRL_PM :return "qcom,ctrl-supply-entries" ; +case DP_PHY_PM :return "qcom,phy-supply-entries" ; +default :return "???" ;
This isn't possible. At the very least return NULL and give you self a chance to detect the error - otherwise you'll be returning odd error messages with ???? in it that would be harder to debug.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +40
-0+ } +} + +static int dp_parser_get_vreg (struct dp_parser *parser, +enum dp_pm_type module) +{ +int i =0 , rc =0 ; +u32 tmp =0 ; +const char *pm_supply_name =NULL ; +struct device_node *supply_node =NULL ; +struct device_node *of_node = parser->pdev->dev.of_node; +struct device_node *supply_root_node =NULL ; +struct dss_module_power *mp = &parser->mp[module]; + + mp->num_vreg =0 ; + pm_supply_name =dp_parser_supply_node_name (module); + supply_root_node =of_get_child_by_name (of_node, pm_supply_name); +if (!supply_root_node) { +pr_err ("no supply entry present: %s\n" , pm_supply_name); + goto novreg; + } + + mp->num_vreg =of_get_available_child_count (supply_root_node); + +if (mp->num_vreg ==0 ) { +pr_debug ("no vreg\n" ); + goto novreg; + }else { +pr_debug ("vreg found. count=%d\n" , mp->num_vreg); + } + + mp->vreg_config =devm_kzalloc (&parser->pdev->dev, +sizeof (struct dss_vreg ) * mp->num_vreg,GFP_KERNEL ); +if (!mp->vreg_config) { + rc = -ENOMEM ; + goto error; + } + +for_each_child_of_node (supply_root_node, supply_node) { +const char *st =NULL ;
drivers/gpu/drm/msm/dp/dp_parser.c line 339
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+/* vreg-name */ + rc =of_property_read_string (supply_node, +"qcom,supply-name" , &st); +if (rc) { +pr_err ("error reading name. rc=%d\n" , + rc); + goto error; + } +snprintf (mp->vreg_config[i].vreg_name, +ARRAY_SIZE ((mp->vreg_config[i].vreg_name)),"%s" , st);
ARRAY_SIZE works for a string, but we prefer sizeof() in most cases. If you are just copying a string, consider using strncpy() and friends. It will be faster than snprintf.
drivers/gpu/drm/msm/dp/dp_parser.c line 342
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +3
-0+/* vreg-min-voltage */ + rc =of_property_read_u32 (supply_node, +"qcom,supply-min-voltage" , &tmp);
As mentioned above, on error they don't touch the value of the pointer so you don't need to use a temporary variable.
Quoted 41 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +41
-0+if (rc) { +pr_err ("error reading min volt. rc=%d\n" , + rc); + goto error; + } + mp->vreg_config[i].min_voltage = tmp; + +/* vreg-max-voltage */ + rc =of_property_read_u32 (supply_node, +"qcom,supply-max-voltage" , &tmp); +if (rc) { +pr_err ("error reading max volt. rc=%d\n" , + rc); + goto error; + } + mp->vreg_config[i].max_voltage = tmp; + +/* enable-load */ + rc =of_property_read_u32 (supply_node, +"qcom,supply-enable-load" , &tmp); +if (rc) { +pr_err ("error reading enable load. rc=%d\n" , + rc); + goto error; + } + mp->vreg_config[i].enable_load = tmp; + +/* disable-load */ + rc =of_property_read_u32 (supply_node, +"qcom,supply-disable-load" , &tmp); +if (rc) { +pr_err ("error reading disable load. rc=%d\n" , + rc); + goto error; + } + mp->vreg_config[i].disable_load = tmp; + + pr_debug("%s min=%d, max=%d, enable=%d, disable=%d\n", + mp->vreg_config[i].vreg_name, + mp->vreg_config[i].min_voltage, + mp->vreg_config[i].max_voltage,
drivers/gpu/drm/msm/dp/dp_parser.c line 393
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ mp->vreg_config[i].enable_load, + mp->vreg_config[i].disable_load + ); + ++i; + } + +return rc; + +error: +if (mp->vreg_config) {
You don't need to check for NULL here.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +4
-0+devm_kfree (&parser->pdev->dev, mp->vreg_config); + mp->vreg_config =NULL ; + } +novreg:
drivers/gpu/drm/msm/dp/dp_parser.c line 407
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ mp->num_vreg =0 ; + +return rc; +} + +static void dp_parser_put_vreg_data (struct device *dev, +struct dss_module_power *mp) +{ +if (!mp) { +DEV_ERR ("invalid input\n" );
This error message isn't useful when you are taking down the device - just quietly skip.
drivers/gpu/drm/msm/dp/dp_parser.c line 412
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+return ; + } + +if (mp->vreg_config) { +devm_kfree (dev, mp->vreg_config);
You don't need to kfree managed memory.
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +6
-0+ mp->vreg_config =NULL ; + } + mp->num_vreg =0 ; +} + +static int dp_parser_regulator (struct dp_parser *parser)
drivers/gpu/drm/msm/dp/dp_parser.c line 428
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+{ +int i, rc =0 ; +struct platform_device *pdev = parser->pdev; + +/* Parse the regulator information */ +for (i =DP_CORE_PM ; i <DP_MAX_PM ; i++) { + rc =dp_parser_get_vreg (parser, i); +if (rc) { +pr_err ("get_dt_vreg_data failed for %s. rc=%d\n" , +dp_parser_pm_name (i), rc);
dp_parser_get_vreg() is very loud about errors - you don't need to pile on.
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +4
-0+ i--; +for (; i >=DP_CORE_PM ; i--) +dp_parser_put_vreg_data (&pdev->dev, + &parser->mp[i]);
drivers/gpu/drm/msm/dp/dp_parser.c line 442
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+break ; + } + } + +return rc; +} + +static bool dp_parser_check_prefix (const char *clk_prefix,const char *clk_name) +{ +return !!strnstr (clk_name, clk_prefix,strlen (clk_name));
This isn't saving you any lines of code - you can do the string compare directly in the calling functions.
drivers/gpu/drm/msm/dp/dp_parser.c line 449
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +7
-0+} + +static void dp_parser_put_clk_data (struct device *dev, +struct dss_module_power *mp) +{ +if (!mp) { +DEV_ERR ("%s: invalid input\n" , __func__);
You are taking down the device so you don't care if anything is invalid.
drivers/gpu/drm/msm/dp/dp_parser.c line 454
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+return ; + } + +if (mp->clk_config) { +devm_kfree (dev, mp->clk_config);
You don't need to free managed device memory.
drivers/gpu/drm/msm/dp/dp_parser.c line 465
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +11
-0+ mp->clk_config =NULL ; + } + + mp->num_clk =0 ; +} + +static void dp_parser_put_gpio_data (struct device *dev, +struct dss_module_power *mp) +{ +if (!mp) { +DEV_ERR ("%s: invalid input\n" , __func__);
As above.
drivers/gpu/drm/msm/dp/dp_parser.c line 470
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+return ; + } + +if (mp->gpio_config) { +devm_kfree (dev, mp->gpio_config);
Also as above.
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +20
-0+ mp->gpio_config =NULL ; + } + + mp->num_gpio =0 ; +} + +static int dp_parser_init_clk_data (struct dp_parser *parser) +{ +int num_clk =0 , i =0 , rc =0 ; +int core_clk_count =0 , ctrl_clk_count =0 ; +const char *core_clk ="core" ; +const char *ctrl_clk ="ctrl" ; +const char *clk_name; +struct device *dev = &parser->pdev->dev; +struct dss_module_power *core_power = &parser->mp[DP_CORE_PM ]; +struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM ]; + + num_clk =of_property_count_strings (dev->of_node,"clock-names" ); +if (num_clk <=0 ) { +pr_err ("no clocks are defined\n" );
drivers/gpu/drm/msm/dp/dp_parser.c line 500
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ rc = -EINVAL ; + goto exit; + } + +for (i =0 ; i < num_clk; i++) { +of_property_read_string_index (dev->of_node, +"clock-names" , i, &clk_name); + +if (dp_parser_check_prefix (core_clk, clk_name)) + core_clk_count++;
According to your bindings, 'core' or 'ctrl' will be the prefix for the clock, so why are you using strnstr? strncmp works just as well.
!strncmp("core", clk_name, 4)
drivers/gpu/drm/msm/dp/dp_parser.c line 502
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +2
-0+ +if (dp_parser_check_prefix (ctrl_clk, clk_name))
if (!strncmp("ctrl", clk_name, 4)
drivers/gpu/drm/msm/dp/dp_parser.c line 507
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+ ctrl_clk_count++; + } + +/* Initialize the CORE power module */ +if (core_clk_count <=0 ) {
core_clk_count clearly can't be less than zero.
drivers/gpu/drm/msm/dp/dp_parser.c line 518
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +11
-0+pr_err ("no core clocks are defined\n" ); + rc = -EINVAL ; + goto exit; + } + + core_power->num_clk = core_clk_count; + core_power->clk_config =devm_kzalloc (dev, +sizeof (struct dss_clk ) * core_power->num_clk, +GFP_KERNEL ); +if (!core_power->clk_config) { + rc = -EINVAL ;
the return value should be -ENOMEM here.
drivers/gpu/drm/msm/dp/dp_parser.c line 523
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +5
-0+ goto exit; + } + +/* Initialize the CTRL power module */ +if (ctrl_clk_count <=0 ) {
Again, this clearly can't be less than zero.
drivers/gpu/drm/msm/dp/dp_parser.c line 535
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +12
-0+pr_err ("no ctrl clocks are defined\n" ); + rc = -EINVAL ; + goto ctrl_clock_error; + } + + ctrl_power->num_clk = ctrl_clk_count; + ctrl_power->clk_config =devm_kzalloc (dev, +sizeof (struct dss_clk ) * ctrl_power->num_clk, +GFP_KERNEL ); +if (!ctrl_power->clk_config) { + ctrl_power->num_clk =0 ; + rc = -EINVAL ;
And -ENOMEM again.
drivers/gpu/drm/msm/dp/dp_parser.c line 544
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +9
-0+ goto ctrl_clock_error; + } + +return rc; + +ctrl_clock_error: +dp_parser_put_clk_data (dev, core_power); +exit: +return rc;
Don't use this label - just return the error code directly instead.
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +20
-0+} + +static int dp_parser_clock (struct dp_parser *parser) +{ +int rc =0 , i =0 ; +int num_clk =0 ; +int core_clk_index =0 , ctrl_clk_index =0 ; +int core_clk_count =0 , ctrl_clk_count =0 ; +const char *clk_name; +const char *core_clk ="core" ; +const char *ctrl_clk ="ctrl" ; +struct device *dev = &parser->pdev->dev; +struct dss_module_power *core_power = &parser->mp[DP_CORE_PM ]; +struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM ]; + + core_power = &parser->mp[DP_CORE_PM ]; + ctrl_power = &parser->mp[DP_CTRL_PM ]; + + rc =dp_parser_init_clk_data (parser); +if (rc) {
drivers/gpu/drm/msm/dp/dp_parser.c line 574
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+pr_err ("failed to initialize power data\n" ); + rc = -EINVAL ; + goto exit; + } + + core_clk_count = core_power->num_clk; + ctrl_clk_count = ctrl_power->num_clk; + + num_clk = core_clk_count + ctrl_clk_count; +
According to your bindings, not every clock in your list is a core or a ctrl - are those clocks ignored?
drivers/gpu/drm/msm/dp/dp_parser.c line 577
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +3
-0+for (i =0 ; i < num_clk; i++) { +of_property_read_string_index (dev->of_node,"clock-names" , + i, &clk_name);
This implies that a core_ or ctrl_ clock are first in the list. Your bindings do not specify an order.
drivers/gpu/drm/msm/dp/dp_parser.c line 579
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +2
-0+ + if (dp_parser_check_prefix(core_clk, clk_name) &&
Again, you should use strncmp() here
drivers/gpu/drm/msm/dp/dp_parser.c line 580
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_parser.c new file +1
-0+ core_clk_index < core_clk_count) {
If you already went to the trouble of counting you can be pretty sure that you won't overrun your array.
drivers/gpu/drm/msm/dp/dp_parser.c line 587
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +7
-0+struct dss_clk *clk = + &core_power->clk_config[core_clk_index]; +strlcpy (clk->clk_name, clk_name,sizeof (clk->clk_name)); + clk->type =DSS_CLK_AHB ; + core_clk_index++; + }else if (dp_parser_check_prefix (ctrl_clk, clk_name) && + ctrl_clk_index < ctrl_clk_count) {
You aren't going to overrun your array.
drivers/gpu/drm/msm/dp/dp_parser.c line 599
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +12
-0+struct dss_clk *clk = + &ctrl_power->clk_config[ctrl_clk_index]; +strlcpy (clk->clk_name, clk_name,sizeof (clk->clk_name)); + ctrl_clk_index++; + +if (!strcmp (clk_name,"ctrl_link_clk" ) || + !strcmp (clk_name,"ctrl_pixel_clk" )) + clk->type =DSS_CLK_PCLK ; +else + clk->type =DSS_CLK_AHB ; + } + }
There is a lot going on in these two functions but I feel they can be combined. The number of clocks in each array shouldn't be a mystery - you can pre-allocate or statically allocate the arrays. That will save you from the initial step of walking the list to allocate the memory. Then you can have a single walk of the list, checking the clock type and handle it accordingly.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +6
-0+ +pr_debug ("clock parsing successful\n" ); + +exit: +return rc; +}
drivers/gpu/drm/msm/dp/dp_parser.c line 615
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+ +static int dp_parser_parse (struct dp_parser *parser) +{ +int rc =0 ; + +if (!parser) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto err; + }
parser can never be null here.
drivers/gpu/drm/msm/dp/dp_parser.c line 619
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +3
-0+ rc =dp_parser_ctrl_res (parser); +if (rc) + goto err;
You can just return rc here and throughout without the label.
Quoted 37 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +37
-0+ + rc =dp_parser_aux (parser); +if (rc) + goto err; + + rc =dp_parser_misc (parser); +if (rc) + goto err; + + rc =dp_parser_clock (parser); +if (rc) + goto err; + + rc =dp_parser_regulator (parser); +if (rc) + goto err; + + rc =dp_parser_gpio (parser); +if (rc) + goto err; + + rc =dp_parser_pinctrl (parser); +err: +return rc; +} + +struct dp_parser *dp_parser_get (struct platform_device *pdev) +{ +struct dp_parser *parser; + + parser =devm_kzalloc (&pdev->dev,sizeof (*parser),GFP_KERNEL ); +if (!parser) +return ERR_PTR (-ENOMEM ); + + parser->parse = dp_parser_parse; + parser->pdev = pdev; +
drivers/gpu/drm/msm/dp/dp_parser.c line 666
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +10
-0+return parser; +} + +void dp_parser_put (struct dp_parser *parser) +{ +int i =0 ; +struct dss_module_power *power =NULL ; + +if (!parser) { +pr_err ("invalid parser module\n" );
If parser is null, you don't care. Just quietly exit.
drivers/gpu/drm/msm/dp/dp_parser.c line 678
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +12
-0+return ; + } + + power = parser->mp; + +for (i =0 ; i <DP_MAX_PM ; i++) { +dp_parser_put_clk_data (&parser->pdev->dev, &power[i]); +dp_parser_put_vreg_data (&parser->pdev->dev, &power[i]); +dp_parser_put_gpio_data (&parser->pdev->dev, &power[i]); + } + +devm_kfree (&parser->pdev->dev, parser);
You don't need to free managed device memory.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_parser.h new file +3
-0@@ -0,0 +1,205 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_parser.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +13
-0+#ifndef _DP_PARSER_H_ +#define _DP_PARSER_H_ + +#include "dpu_io_util.h" + +#define DP_LABEL "MDSS DP DISPLAY" +#define AUX_CFG_LEN 10 +#define DP_MAX_PIXEL_CLK_KHZ 675000 + +enum dp_pm_type { +DP_CORE_PM , +DP_CTRL_PM , + DP_PHY_PM,
drivers/gpu/drm/msm/dp/dp_parser.h line 37
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +10
-0+ DP_MAX_PM +}; + +static inline const char *dp_parser_pm_name (enum dp_pm_type module) +{ +switch (module) { +case DP_CORE_PM :return "DP_CORE_PM" ; +case DP_CTRL_PM :return "DP_CTRL_PM" ; +case DP_PHY_PM :return "DP_PHY_PM" ; +default :return "???" ;
You go out of your way to make sure that the default case can't happen here. also this function is only used once, I don't think it needs to be a static inline in the header.
Quoted 177 lines
drivers/gpu/drm/msm/dp/dp_parser.h new file +168
-0+ } +} + +/** +* struct dp_display_data - display related device tree data. +* +* @ctrl_node: referece to controller device +* @phy_node: reference to phy device +* @is_active: is the controller currently active +* @name: name of the display +* @display_type: type of the display +*/ +struct dp_display_data { +struct device_node *ctrl_node; +struct device_node *phy_node; +bool is_active; +const char *name; +const char *display_type; +}; + +/** +* struct dp_ctrl_resource - controller's IO related data +* +* @dp_ahb: controller's ahb mapped memory address +* @dp_aux: controller's aux mapped memory address +* @dp_link: controller's link mapped memory address +* @dp_p0: controller's p0 mapped memory address +* @phy_io: phy's mapped memory address +* @ln_tx0_io: USB-DP lane TX0's mapped memory address +* @ln_tx1_io: USB-DP lane TX1's mapped memory address +* @dp_cc_io: DP cc's mapped memory address +* @qfprom_io: qfprom's mapped memory address +* @dp_pll_io: DP PLL mapped memory address +* @usb3_dp_com: USB3 DP PHY combo mapped memory address +*/ +struct dp_io { +struct dss_io_data ctrl_io; +struct dss_io_data dp_ahb; +struct dss_io_data dp_aux; +struct dss_io_data dp_link; +struct dss_io_data dp_p0; +struct dss_io_data phy_io; +struct dss_io_data ln_tx0_io; +struct dss_io_data ln_tx1_io; +struct dss_io_data dp_cc_io; +struct dss_io_data qfprom_io; +struct dss_io_data dp_pll_io; +struct dss_io_data usb3_dp_com; +}; + +/** +* struct dp_pinctrl - DP's pin control +* +* @pin: pin-controller's instance +* @state_active: active state pin control +* @state_hpd_active: hpd active state pin control +* @state_suspend: suspend state pin control +*/ +struct dp_pinctrl { +struct pinctrl *pin; +struct pinctrl_state *state_active; +struct pinctrl_state *state_hpd_active; +struct pinctrl_state *state_suspend; +}; + +#define DP_ENUM_STR (x) #x +#define DP_AUX_CFG_MAX_VALUE_CNT 3 +/** +* struct dp_aux_cfg - DP's AUX configuration settings +* +* @cfg_cnt: count of the configurable settings for the AUX register +* @current_index: current index of the AUX config lut +* @offset: register offset of the AUX config register +* @lut: look up table for the AUX config values for this register +*/ +struct dp_aux_cfg { +u32 cfg_cnt; +u32 current_index; +u32 offset; +u32 lut[DP_AUX_CFG_MAX_VALUE_CNT ]; +}; + +/* PHY AUX config registers */ +enum dp_phy_aux_config_type { +PHY_AUX_CFG0 , +PHY_AUX_CFG1 , +PHY_AUX_CFG2 , +PHY_AUX_CFG3 , +PHY_AUX_CFG4 , +PHY_AUX_CFG5 , +PHY_AUX_CFG6 , +PHY_AUX_CFG7 , +PHY_AUX_CFG8 , +PHY_AUX_CFG9 , +PHY_AUX_CFG_MAX , +}; + +static inline char *dp_phy_aux_config_type_to_string (u32 cfg_type) +{ +switch (cfg_type) { +case PHY_AUX_CFG0 : +return DP_ENUM_STR (PHY_AUX_CFG0 ); +case PHY_AUX_CFG1 : +return DP_ENUM_STR (PHY_AUX_CFG1 ); +case PHY_AUX_CFG2 : +return DP_ENUM_STR (PHY_AUX_CFG2 ); +case PHY_AUX_CFG3 : +return DP_ENUM_STR (PHY_AUX_CFG3 ); +case PHY_AUX_CFG4 : +return DP_ENUM_STR (PHY_AUX_CFG4 ); +case PHY_AUX_CFG5 : +return DP_ENUM_STR (PHY_AUX_CFG5 ); +case PHY_AUX_CFG6 : +return DP_ENUM_STR (PHY_AUX_CFG6 ); +case PHY_AUX_CFG7 : +return DP_ENUM_STR (PHY_AUX_CFG7 ); +case PHY_AUX_CFG8 : +return DP_ENUM_STR (PHY_AUX_CFG8 ); +case PHY_AUX_CFG9 : +return DP_ENUM_STR (PHY_AUX_CFG9 ); +default : +return "unknown" ; + } +} + +/** +* struct dp_parser - DP parser's data exposed to clients +* +* @pdev: platform data of the client +* @mp: gpio, regulator and clock related data +* @pinctrl: pin-control related data +* @disp_data: controller's display related data +* @parse: function to be called by client to parse device tree. +*/ +struct dp_parser { +struct platform_device *pdev; +struct dss_module_power mp[DP_MAX_PM ]; +struct dp_pinctrl pinctrl; +struct dp_io io; +struct dp_display_data disp_data; + +u8 l_map[4 ]; +struct dp_aux_cfg aux_cfg[AUX_CFG_LEN ]; +u32 max_pclk_khz; + +int (*parse)(struct dp_parser *parser); +}; + +/** +* dp_parser_get() - get the DP's device tree parser module +* +* @pdev: platform data of the client +* return: pointer to dp_parser structure. +* +* This function provides client capability to parse the +* device tree and populate the data structures. The data +* related to clock, regulators, pin-control and other +* can be parsed using this module. +*/ +struct dp_parser *dp_parser_get (struct platform_device *pdev); + +/** +* dp_parser_put() - cleans the dp_parser module +* +* @parser: pointer to the parser's data. +*/ +void dp_parser_put (struct dp_parser *parser); +#endif drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0@@ -0,0 +1,599 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_power.c line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 25 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +25
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/clk.h> +#include "dp_power.h" + +#define DP_CLIENT_NAME_SIZE 20 + +struct dp_power_private { +struct dp_parser *parser; +struct platform_device *pdev; +struct clk *pixel_clk_rcg; +struct clk *pixel_parent; + +struct dp_power dp_power; + +bool core_clks_on; +bool link_clks_on; +}; + +static int dp_power_regulator_init (struct dp_power_private *power) +{ +int rc =0 , i =0 , j =0 ; +struct platform_device *pdev; +struct dp_parser *parser; +
drivers/gpu/drm/msm/dp/dp_power.c line 49
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ parser = power->parser; + pdev = power->pdev; + +for (i =DP_CORE_PM ; !rc && (i <DP_MAX_PM ); i++) { + rc =msm_dss_config_vreg (&pdev->dev, + parser->mp[i].vreg_config, + parser->mp[i].num_vreg,1 ); +if (rc) { +pr_err ("failed to init vregs for %s\n" , +dp_parser_pm_name (i));
msm_dss_config_vreg() already prints lots of error messages for you.
drivers/gpu/drm/msm/dp/dp_power.c line 56
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0+for (j = i -1 ; j >=DP_CORE_PM ; j--) { +msm_dss_config_vreg (&pdev->dev, + parser->mp[j].vreg_config, + parser->mp[j].num_vreg,0 ); + } + + goto error;
just return rc;
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +12
-0+ } + } +error: +return rc; +} + +static void dp_power_regulator_deinit (struct dp_power_private *power) +{ +int rc =0 , i =0 ; +struct platform_device *pdev; +struct dp_parser *parser; +
drivers/gpu/drm/msm/dp/dp_power.c line 78
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ parser = power->parser; + pdev = power->pdev; + +for (i =DP_CORE_PM ; (i <DP_MAX_PM ); i++) { + rc =msm_dss_config_vreg (&pdev->dev, + parser->mp[i].vreg_config, + parser->mp[i].num_vreg,0 ); +if (rc) +pr_err ("failed to deinit vregs for %s\n" , +dp_parser_pm_name (i));
Same.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+ } +} + +static int dp_power_regulator_ctrl (struct dp_power_private *power,bool enable) +{ +int rc =0 , i =0 , j =0 ; +struct dp_parser *parser; +
drivers/gpu/drm/msm/dp/dp_power.c line 96
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ parser = power->parser; + +for (i =DP_CORE_PM ; i <DP_MAX_PM ; i++) { + rc =msm_dss_enable_vreg ( + parser->mp[i].vreg_config, + parser->mp[i].num_vreg, enable); +if (rc) { +pr_err ("failed to '%s' vregs for %s\n" , + enable ?"enable" :"disable" , +dp_parser_pm_name (i));
msm_dss_enable_vreg() already gives you the errors you need.
drivers/gpu/drm/msm/dp/dp_power.c line 108
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +12
-0+if (enable) { +for (j = i-1 ; j >=DP_CORE_PM ; j--) { +msm_dss_enable_vreg ( + parser->mp[j].vreg_config, + parser->mp[j].num_vreg,0 ); + } + } + goto error; + } + } +error: +return rc;
You don't need a label with a single return in it.
drivers/gpu/drm/msm/dp/dp_power.c line 119
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +11
-0+} + +static int dp_power_pinctrl_set (struct dp_power_private *power,bool active) +{ +int rc = -EFAULT ; +struct pinctrl_state *pin_state; +struct dp_parser *parser; + + parser = power->parser; + +if (IS_ERR_OR_NULL (parser->pinctrl.pin))
Recall that pinctrl.in cannot be NULL.
drivers/gpu/drm/msm/dp/dp_power.c line 124
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +5
-0+return PTR_ERR (parser->pinctrl.pin); + + pin_state = active ? parser->pinctrl.state_active + : parser->pinctrl.state_suspend; +if (!IS_ERR_OR_NULL (pin_state)) {
Same
drivers/gpu/drm/msm/dp/dp_power.c line 134
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ rc =pinctrl_select_state (parser->pinctrl.pin, + pin_state); +if (rc) +pr_err ("can not set %s pins\n" , + active ?"dp_active" + :"dp_sleep" ); + }else { +pr_err ("invalid '%s' pinstate\n" , + active ?"dp_active" + :"dp_sleep" );
You already let the user know during inint that the pin_state was not correct. You don't need to update them again every time you try to change it.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +11
-0+ } + +return rc; +} + +static int dp_power_clk_init (struct dp_power_private *power,bool enable) +{ +int rc =0 ; +struct dss_module_power *core, *ctrl; +struct device *dev; +
drivers/gpu/drm/msm/dp/dp_power.c line 155
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ core = &power->parser->mp[DP_CORE_PM ]; + ctrl = &power->parser->mp[DP_CTRL_PM ]; + + dev = &power->pdev->dev; + +if (!core || !ctrl) { +pr_err ("invalid power_data\n" ); + rc = -EINVAL ; + goto exit; + }
These are both impossible since you are deriving the pointer above.
drivers/gpu/drm/msm/dp/dp_power.c line 161
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ +if (enable) { + rc =msm_dss_get_clk (dev, core->clk_config, core->num_clk); +if (rc) { +pr_err ("failed to get %s clk. err=%d\n" , +dp_parser_pm_name (DP_CORE_PM ), rc);
msm_dss_get_clk already prints an error message for you.
drivers/gpu/drm/msm/dp/dp_power.c line 168
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0+ goto exit; + } + + rc =msm_dss_get_clk (dev, ctrl->clk_config, ctrl->num_clk); +if (rc) { +pr_err ("failed to get %s clk. err=%d\n" , +dp_parser_pm_name (DP_CTRL_PM ), rc);
Same
drivers/gpu/drm/msm/dp/dp_power.c line 174
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto ctrl_get_error; + } + + power->pixel_clk_rcg =devm_clk_get (dev,"pixel_clk_rcg" ); +if (IS_ERR (power->pixel_clk_rcg)) { +pr_debug ("Unable to get DP pixel clk RCG\n" );
This seems like it should be an error?
drivers/gpu/drm/msm/dp/dp_power.c line 180
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ power->pixel_clk_rcg =NULL ; + } + + power->pixel_parent =devm_clk_get (dev,"pixel_parent" ); +if (IS_ERR (power->pixel_parent)) { +pr_debug ("Unable to get DP pixel RCG parent\n" );
Same?
drivers/gpu/drm/msm/dp/dp_power.c line 183
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0+ power->pixel_parent =NULL ; + } + }else {
This is another one of those functions that shares very little with the other side and can be easily split into a separate function that is easier to understand.
drivers/gpu/drm/msm/dp/dp_power.c line 188
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +5
-0+if (power->pixel_parent) +devm_clk_put (dev, power->pixel_parent); + +if (power->pixel_clk_rcg) +devm_clk_put (dev, power->pixel_clk_rcg);
You don't need to put managed clocks.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +14
-0+ +msm_dss_put_clk (ctrl->clk_config, ctrl->num_clk); +msm_dss_put_clk (core->clk_config, core->num_clk); + } + +return rc; + +ctrl_get_error: +msm_dss_put_clk (core->clk_config, core->num_clk); +exit: +return rc; +} + +static int dp_power_clk_set_rate(struct dp_power_private *power,
drivers/gpu/drm/msm/dp/dp_power.c line 212
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ enum dp_pm_type module, bool enable) +{ + int rc = 0; +struct dss_module_power *mp; + +if (!power) { +pr_err ("invalid power data\n" ); + rc = -EINVAL ; + goto exit; + }
power will always be valid.
drivers/gpu/drm/msm/dp/dp_power.c line 219
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ mp = &power->parser->mp[module]; + +if (enable) { + rc =msm_dss_clk_set_rate (mp->clk_config, mp->num_clk); +if (rc) { +pr_err ("failed to set clks rate.\n" );
msm_dss_clk_set_rate() already gives you an error message;
drivers/gpu/drm/msm/dp/dp_power.c line 225
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto exit; + } + + rc =msm_dss_enable_clk (mp->clk_config, mp->num_clk,1 ); +if (rc) { +pr_err ("failed to enable clks\n" );
Same.
drivers/gpu/drm/msm/dp/dp_power.c line 231
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto exit; + } + }else { + rc =msm_dss_enable_clk (mp->clk_config, mp->num_clk,0 ); +if (rc) { +pr_err ("failed to disable clks\n" );
Same
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_power.c new file +1
-0+ goto exit;
Suspect indentation, but as usual, don't use a single return in a label - just return directly.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+ } + } +exit: +return rc; +} + +static int dp_power_clk_enable (struct dp_power *dp_power, +enum dp_pm_type pm_type,bool enable)
drivers/gpu/drm/msm/dp/dp_power.c line 250
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+{ +int rc =0 ; +struct dss_module_power *mp; +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); + rc = -EINVAL ; + goto error; + }
dp_power will always be valid.
drivers/gpu/drm/msm/dp/dp_power.c line 258
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + + mp = &power->parser->mp[pm_type]; + +if ((pm_type !=DP_CORE_PM ) && (pm_type !=DP_CTRL_PM )) { +pr_err ("unsupported power module: %s\n" , +dp_parser_pm_name (pm_type));
This seems like it would be never be true outside of egregious developer error. - I suppose you could WARN_ON here but it just doesn't seem like a thing.
Quoted 32 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +32
-0+return -EINVAL ; + } + +if (enable) { +if ((pm_type ==DP_CORE_PM ) + && (power->core_clks_on)) { +pr_debug ("core clks already enabled\n" ); +return 0 ; + } + +if ((pm_type ==DP_CTRL_PM ) + && (power->link_clks_on)) { +pr_debug ("links clks already enabled\n" ); +return 0 ; + } + +if ((pm_type ==DP_CTRL_PM ) && (!power->core_clks_on)) { +pr_debug ("Need to enable core clks before link clks\n" ); + + rc =dp_power_clk_set_rate (power,DP_CORE_PM , enable); +if (rc) { +pr_err ("failed to enable clks: %s. err=%d\n" , +dp_parser_pm_name (DP_CORE_PM ), rc); + goto error; + }else { + power->core_clks_on = true; + } + } + } + + rc =dp_power_clk_set_rate (power, pm_type, enable); +if (rc) {
drivers/gpu/drm/msm/dp/dp_power.c line 300
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+pr_err ("failed to '%s' clks for: %s. err=%d\n" , + enable ?"enable" :"disable" , +dp_parser_pm_name (pm_type), rc); + goto error; + } + +if (pm_type ==DP_CORE_PM ) + power->core_clks_on = enable; +else + power->link_clks_on = enable;
With the number of if statements in here it almost seems more logical to have a separate function for both DP_CORE_PM and DP_CTRL_PM - yeah, it would copy a bit of code but it would be a heck of a lot more readable.
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +36
-0+pr_debug ("%s clocks for %s\n" , + enable ?"enable" :"disable" , +dp_parser_pm_name (pm_type)); +pr_debug ("link_clks:%s core_clks:%s\n" , + power->link_clks_on ?"on" :"off" , + power->core_clks_on ?"on" :"off" ); +error: +return rc; +} + +static int dp_power_request_gpios (struct dp_power_private *power) +{ +int rc =0 , i; +struct device *dev; +struct dss_module_power *mp; +static const char *const gpio_names[] = { +"aux_enable" ,"aux_sel" ,"usbplug_cc" , + }; + +if (!power) { +pr_err ("invalid power data\n" ); +return -EINVAL ; + } + + dev = &power->pdev->dev; + mp = &power->parser->mp[DP_CORE_PM ]; + +for (i =0 ; i <ARRAY_SIZE (gpio_names); i++) { +unsigned int gpio = mp->gpio_config[i].gpio; + +if (gpio_is_valid (gpio)) { + rc =devm_gpio_request (dev, gpio, gpio_names[i]); +if (rc) { +pr_err ("request %s gpio failed, rc=%d\n" , + gpio_names[i], rc); + goto error;
drivers/gpu/drm/msm/dp/dp_power.c line 347
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ } + } + } +return 0 ; +error: +for (i =0 ; i <ARRAY_SIZE (gpio_names); i++) { +unsigned int gpio = mp->gpio_config[i].gpio; + +if (gpio_is_valid (gpio)) +gpio_free (gpio);
Can you call gpio_free() on a device managed resource? I think you probably want devm_gpio_free.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0+ } +return rc; +} + +static bool dp_power_find_gpio (const char *gpio1,const char *gpio2) +{ +return !!strnstr (gpio1, gpio2,strlen (gpio1));
drivers/gpu/drm/msm/dp/dp_power.c line 364
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+} + +static void dp_power_set_gpio (struct dp_power_private *power,bool flip) +{ +int i; +struct dss_module_power *mp = &power->parser->mp[DP_CORE_PM ]; +struct dss_gpio *config = mp->gpio_config; + +for (i =0 ; i < mp->num_gpio; i++) { +if (dp_power_find_gpio (config->gpio_name,"aux-sel" ))
I think config->gpio_name is the name from the DT, basically qcom,aux-sel-gpio? Why not just strcmp on that instead of going the much harder route
drivers/gpu/drm/msm/dp/dp_power.c line 372
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+ config->value = flip; + +if (gpio_is_valid (config->gpio)) { +pr_debug ("gpio %s, value %d\n" , config->gpio_name, + config->value); + +if (dp_power_find_gpio (config->gpio_name,"aux-en" ) || +dp_power_find_gpio (config->gpio_name,"aux-sel" ))
Same and same
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +14
-0+gpio_direction_output (config->gpio, + config->value); + else + gpio_set_value(config->gpio, config->value); + + } + config++; + } +} + +static int dp_power_config_gpios (struct dp_power_private *power,bool flip, +bool enable) +{ +int rc =0 , i;
drivers/gpu/drm/msm/dp/dp_power.c line 396
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+struct dss_module_power *mp; +struct dss_gpio *config; + + mp = &power->parser->mp[DP_CORE_PM ]; + config = mp->gpio_config; + +if (enable) { + rc =dp_power_request_gpios (power); +if (rc) { +pr_err ("gpio request failed\n" );
dp_power_request_gpios prints an error message on every failure point.
drivers/gpu/drm/msm/dp/dp_power.c line 400
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0+return rc; + } + +dp_power_set_gpio (power, flip);
It seems like maybe dp_power_request_gpios() and dp_power_set_gpio() can be combined - both of them only get called here.
drivers/gpu/drm/msm/dp/dp_power.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_power.c new file +1
-0+ }else {
Again, this feels like it could safely be in its own function for clarity.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+for (i =0 ; i < mp->num_gpio; i++) { +gpio_set_value (config[i].gpio,0 ); +gpio_free (config[i].gpio); + } + } + +return 0 ; +}
drivers/gpu/drm/msm/dp/dp_power.c line 419
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+ +static int dp_power_client_init (struct dp_power *dp_power) +{ +int rc =0 ; +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); +return -EINVAL ; + }
dp_power can never be NULL here.
drivers/gpu/drm/msm/dp/dp_power.c line 427
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +7
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + +pm_runtime_enable (&power->pdev->dev); + + rc =dp_power_regulator_init (power); +if (rc) { +pr_err ("failed to init regulators\n" );
The sub function already prints error messages.
drivers/gpu/drm/msm/dp/dp_power.c line 433
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto error_power; + } + + rc =dp_power_clk_init (power, true); +if (rc) { +pr_err ("failed to init clocks\n" );
Also this one.
drivers/gpu/drm/msm/dp/dp_power.c line 436
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0+ goto error_clk; + } +return 0 ;
You can flip this if statement and save a goto:
if (!rc)
return 0;
dp_power_regulator_deinit(power);
...
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ +error_clk: +dp_power_regulator_deinit (power); +error_power: +pm_runtime_disable (&power->pdev->dev); +return rc;
drivers/gpu/drm/msm/dp/dp_power.c line 452
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+} + +static void dp_power_client_deinit (struct dp_power *dp_power) +{ +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); +return ; + }
dp_power is always set.
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + +dp_power_clk_init (power, false); +dp_power_regulator_deinit (power); +pm_runtime_disable (&power->pdev->dev); + +} +
drivers/gpu/drm/msm/dp/dp_power.c line 471
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+static int dp_power_set_pixel_clk_parent (struct dp_power *dp_power) +{ +int rc =0 ; +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); + rc = -EINVAL ; + goto exit; + }
dp_power is always set.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +8
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + +if (power->pixel_clk_rcg && power->pixel_parent) +clk_set_parent (power->pixel_clk_rcg, power->pixel_parent); +exit: +return rc; +} +
drivers/gpu/drm/msm/dp/dp_power.c line 490
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+static int dp_power_init (struct dp_power *dp_power,bool flip) +{ +int rc =0 ; +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); + rc = -EINVAL ; + goto exit; + }
dp_power is always set.
drivers/gpu/drm/msm/dp/dp_power.c line 497
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + +pm_runtime_get_sync (&power->pdev->dev); + rc =dp_power_regulator_ctrl (power, true); +if (rc) { +pr_err ("failed to enable regulators\n" );
This already prints the error messages you need.
drivers/gpu/drm/msm/dp/dp_power.c line 503
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto exit; + } + + rc =dp_power_pinctrl_set (power, true); +if (rc) { +pr_err ("failed to set pinctrl state\n" );
Same.
drivers/gpu/drm/msm/dp/dp_power.c line 509
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto err_pinctrl; + } + + rc =dp_power_config_gpios (power, flip, true); +if (rc) { +pr_err ("failed to enable gpios\n" );
Same.
drivers/gpu/drm/msm/dp/dp_power.c line 515
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +6
-0+ goto err_gpio; + } + + rc =dp_power_clk_enable (dp_power,DP_CORE_PM , true); +if (rc) { +pr_err ("failed to enable DP core clocks\n" );
Same.
drivers/gpu/drm/msm/dp/dp_power.c line 519
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +4
-0+ goto err_clk; + } + +return 0 ;
As above, flip the if statement and save a goto:
if (!rc)
return 0;
dp_power_config_gpios(power, flip, false);
...
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +12
-0+ +err_clk: +dp_power_config_gpios (power, flip, false); +err_gpio: +dp_power_pinctrl_set (power, false); +err_pinctrl: +dp_power_regulator_ctrl (power, false); +exit: +pm_runtime_put_sync (&power->pdev->dev); +return rc; +} +
drivers/gpu/drm/msm/dp/dp_power.c line 541
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+static int dp_power_deinit (struct dp_power *dp_power) +{ +int rc =0 ; +struct dp_power_private *power; + +if (!dp_power) { +pr_err ("invalid power data\n" ); + rc = -EINVAL ; + goto exit; + }
dp_power can never be NULL;
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +12
-0+ power = container_of(dp_power, struct dp_power_private, dp_power); + +dp_power_clk_enable (dp_power,DP_CORE_PM , false); +dp_power_config_gpios (power, false, false); +dp_power_pinctrl_set (power, false); +dp_power_regulator_ctrl (power, false); +pm_runtime_put_sync (&power->pdev->dev); +exit: +return rc; +} + +struct dp_power *dp_power_get (struct dp_parser *parser)
drivers/gpu/drm/msm/dp/dp_power.c line 564
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+{ +int rc =0 ; +struct dp_power_private *power; +struct dp_power *dp_power; + +if (!parser) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto error; + }
parser can never be NULL;
drivers/gpu/drm/msm/dp/dp_power.c line 568
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +3
-0+ power =devm_kzalloc (&parser->pdev->dev,sizeof (*power),GFP_KERNEL ); +if (!power) { + rc = -ENOMEM ;
Just return ERR_PTR(-ENOMEM);
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +20
-0+ goto error; + } + + power->parser = parser; + power->pdev = parser->pdev; + + dp_power = &power->dp_power; + + dp_power->init = dp_power_init; + dp_power->deinit = dp_power_deinit; + dp_power->clk_enable = dp_power_clk_enable; + dp_power->set_pixel_clk_parent = dp_power_set_pixel_clk_parent; + dp_power->power_client_init = dp_power_client_init; + dp_power->power_client_deinit = dp_power_client_deinit; + +return dp_power; +error: +return ERR_PTR (rc); +} +
drivers/gpu/drm/msm/dp/dp_power.c line 598
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +10
-0+void dp_power_put (struct dp_power *dp_power) +{ +struct dp_power_private *power =NULL ; + +if (!dp_power) +return ; + + power = container_of(dp_power, struct dp_power_private, dp_power); + +devm_kfree (&power->pdev->dev, power);
You don't need to kfree device managed mmemory.
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.c new file +1
-0+}drivers/gpu/drm/msm/dp/dp_power.h new file +3
-0@@ -0,0 +1,57 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_power.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_power.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
Quoted 53 lines
drivers/gpu/drm/msm/dp/dp_power.h new file +44
-0+ +#ifndef _DP_POWER_H_ +#define _DP_POWER_H_ + +#include "dp_parser.h" +#include "dpu_power_handle.h" + +/** +* sruct dp_power - DisplayPort's power related data +* +* @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_pixel_clk_parent: set the parent of DP pixel clock +*/ +struct dp_power { +int (*init)(struct dp_power *power,bool flip); +int (*deinit)(struct dp_power *power); +int (*clk_enable)(struct dp_power *power,enum dp_pm_type pm_type, +bool enable); +int (*set_pixel_clk_parent)(struct dp_power *power); +int (*power_client_init)(struct dp_power *power); +void (*power_client_deinit)(struct dp_power *power); +}; + +/** +* dp_power_get() - configure and get the DisplayPort power module data +* +* @parser: instance of parser module +* return: pointer to allocated power module data +* +* This API will configure the DisplayPort's power module and provides +* methods to be called by the client to configure the power related +* modueles. +*/ +struct dp_power *dp_power_get (struct dp_parser *parser); + +/** +* dp_power_put() - release the power related resources +* +* @power: pointer to the power module's data +*/ +void dp_power_put (struct dp_power *power); +#endif /* _DP_POWER_H_ */ drivers/gpu/drm/msm/dp/dp_reg.h new file +3
-0@@ -0,0 +1,357 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +*
drivers/gpu/drm/msm/dp/dp_reg.h line 13
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_reg.h new file +10
-0+* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
SPDX please.
<snip the rest>
Jordan
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
Re: [DPU PATCH 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.
Hi Chandan,
A few themes which I've pointed out below, but want to call out at the top so it's obvious.
- Please remove all superfluous NULL checks at the beginning of functions. Included in this is reflowing initialization of variables and checking that return types still make sense (ie: if a function's only error path is the NULL check, make it void).
- Please remove all of the new callbacks and just call functions directly. This should also get rid of the _get/_put functions that allocate/set them up
- Please consolidate state structs into one struct with a few substructs, there's too much state right now.
- Please #define hardcoded values
- Instead of sprinkling wmb() everywhere, use readl/writel instead of *_relaxed
- There are a bunch of races that I found, please audit the code and remove races with locks as necessary
- I tried to catch as much dead code as possible, please audit the rest for unused structs/variables/functions/etc
- Use drm dp helper structs for link parameter storage
Quoted 64 lines
Signed-off-by Chandan Uddaraju <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 9 + drivers/gpu/drm/msm/Makefile | 15 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 206 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 44 + drivers/gpu/drm/msm/dp/dp_aux.c | 570 ++++++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 44 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1188 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 144 +++ drivers/gpu/drm/msm/dp/dp_ctrl.c | 1475 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 + drivers/gpu/drm/msm/dp/dp_debug.c | 507 +++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 81 ++ drivers/gpu/drm/msm/dp/dp_display.c | 977 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 55 + drivers/gpu/drm/msm/dp/dp_drm.c | 542 ++++++++++ drivers/gpu/drm/msm/dp/dp_drm.h | 52 + drivers/gpu/drm/msm/dp/dp_extcon.c | 400 +++++++ drivers/gpu/drm/msm/dp/dp_extcon.h | 111 ++ drivers/gpu/drm/msm/dp/dp_link.c | 1549 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 184 ++++ drivers/gpu/drm/msm/dp/dp_panel.c | 624 +++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 121 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 679 ++++++++++++ drivers/gpu/drm/msm/dp/dp_parser.h | 205 ++++ drivers/gpu/drm/msm/dp/dp_power.c | 599 +++++++++++ drivers/gpu/drm/msm/dp/dp_power.h | 57 + drivers/gpu/drm/msm/dp/dp_reg.h | 357 ++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 22 + include/drm/drm_dp_helper.h | 19 + 30 files changed, 10887 insertions(+), 1 deletion(-) 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_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.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@@ -49,6 +49,15 @@ config DRM_MSM_HDMI_HDCP help Choose this option to enable HDCP state machine
drivers/gpu/drm/msm/Kconfig config DRM_MSM_HDMI_HDCP · line 60
Quoted 10 lines
drivers/gpu/drm/msm/Kconfig +9
-0+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.
Why are these line lengths so short? You can go to 80 columns. Please also add an empty line here.
Quoted 16 lines
drivers/gpu/drm/msm/Kconfig +0
-0config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSMdrivers/gpu/drm/msm/Makefile +1
-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 \
drivers/gpu/drm/msm/Makefile msm-y := \ · line 98
Quoted 6 lines
drivers/gpu/drm/msm/Makefile +2
-1@@ -93,7 +94,19 @@ msm-y := \ msm_submitqueue.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ - disp/dpu1/dpu_dbg.o + disp/dpu1/dpu_dbg.o \ + dp/dp_debug.o
Does this compile if CONFIG_DEBUG_FS is selected, but not CONFIG_DRM_MSM_DP?
drivers/gpu/drm/msm/Makefile msm-y := \ · line 109
Quoted 11 lines
drivers/gpu/drm/msm/Makefile +11
-0+ +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_extcon.o \ + dp/dp_parser.o \ + dp/dp_power.o \ + dp/dp_catalog.o \ + dp/dp_aux.o \ + dp/dp_panel.o \ + dp/dp_link.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o
The rest of the file has files in alphabetical order, this should too.
Quoted 19 lines
drivers/gpu/drm/msm/Makefile +0
-0msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.odrivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +4
-0@@ -14,10 +14,216 @@#include <linux/clk.h> #include <linux/clk/clk-conf.h> #include <linux/err.h> +#include <linux/io.h> +#include <linux/regulator/consumer.h> #include <linux/delay.h> #include "dpu_io_util.h" +static struct resource *msm_dss_get_res_byname(struct platform_device *pdev, + unsigned int type,
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 34
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+ const char *name) +{ +struct resource *res =NULL ; + + res =platform_get_resource_byname (pdev, type, name); +if (!res) +DEV_ERR ("%s: '%s' resource not found\n" , __func__, name); + +return res; +}/* msm_dss_get_res_byname */
Why don't you just call platform_get_resource_byname directly?
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 41
Quoted 7 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +7
-0+ +int msm_dss_ioremap_byname (struct platform_device *pdev, +struct dss_io_data *io_data,const char *name) +{ +struct resource *res =NULL ; + +if (!pdev || !io_data) {
Given that we've been aggressively trying to get rid of these superfluous checks, I'm not thrilled that they're being re-introduced. Can you please go through the patch and remove all of the unnecessary checks?
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 50
Quoted 9 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +9
-0+DEV_ERR ("%pS->%s: invalid input\n" , +__builtin_return_address (0 ), __func__); +return -EINVAL ; + } + + res =msm_dss_get_res_byname (pdev,IORESOURCE_MEM , name); +if (!res) { +DEV_ERR ("%pS->%s: '%s' msm_dss_get_res_byname failed\n" , +__builtin_return_address (0 ), __func__, name);
Yet another error format :) Could we please stick with one of DPU_ERROR, DRM_ERROR, or DRM_DEV_ERROR?
Quoted 18 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +18
-0+return -ENODEV ; + } + + io_data->len = (u32 )resource_size (res); + io_data->base =ioremap (res->start, io_data->len); +if (!io_data->base) { +DEV_ERR ("%pS->%s: '%s' ioremap failed\n" , +__builtin_return_address (0 ), __func__, name); +return -EIO ; + } + +return 0 ; +}/* msm_dss_ioremap_byname */ + +void msm_dss_iounmap (struct dss_io_data *io_data) +{ +if (!io_data) { + DEV_ERR("%pS->%s: invalid input\n",
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 78
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+ __builtin_return_address(0), __func__); +return ; + } + +if (io_data->base) { +iounmap (io_data->base); + io_data->base =NULL ; + } + io_data->len =0 ; +}/* msm_dss_iounmap */
These two functions are only used in dp_parser.c, why not just make them static functions there?
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 81
Quoted 3 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +3
-0+ +int msm_dss_config_vreg (struct device *dev,struct dss_vreg *in_vreg, +int num_vreg,int config)
This should be 2 functions, one for initialization and one for deinitializing, the 2 paths don't share any code, so there's no need to combine them.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 93
Quoted 12 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +12
-0+{ +int i =0 , rc =0 ; +struct dss_vreg *curr_vreg =NULL ; +enum dss_vreg_type type; + +if (!in_vreg || !num_vreg) +return rc; + +if (config) { +for (i =0 ; i < num_vreg; i++) { + curr_vreg = &in_vreg[i]; + curr_vreg->vreg = regulator_get(dev,
Use devm_* please
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 95
Quoted 2 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +2
-0+ curr_vreg->vreg_name); + rc =PTR_RET (curr_vreg->vreg);
PTR_RET is deprecated. The pattern for this is usually:
ptr = some_func();
if (IS_ERR_OR_NULL(ptr)) {
...
rc = PTR_ERR(ptr);
goto fail_label:
}Quoted 120 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +120
-0+if (rc) { +DEV_ERR ("%pS->%s: %s get failed. rc=%d\n" , +__builtin_return_address (0 ), __func__, + curr_vreg->vreg_name, rc); + curr_vreg->vreg =NULL ; + goto vreg_get_fail; + } + type = (regulator_count_voltages (curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; +if (type ==DSS_REG_LDO ) { + rc =regulator_set_voltage ( + curr_vreg->vreg, + curr_vreg->min_voltage, + curr_vreg->max_voltage); +if (rc <0 ) { +DEV_ERR ("%pS->%s: %s set vltg fail\n" , +__builtin_return_address (0 ), + __func__, + curr_vreg->vreg_name); + goto vreg_set_voltage_fail; + } + } + } + }else { +for (i = num_vreg-1 ; i >=0 ; i--) { + curr_vreg = &in_vreg[i]; +if (curr_vreg->vreg) { + type = (regulator_count_voltages ( + curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; +if (type ==DSS_REG_LDO ) { +regulator_set_voltage (curr_vreg->vreg, +0 , curr_vreg->max_voltage); + } +regulator_put (curr_vreg->vreg); + curr_vreg->vreg =NULL ; + } + } + } +return 0 ; + +vreg_unconfig: +if (type ==DSS_REG_LDO ) +regulator_set_load (curr_vreg->vreg,0 ); + +vreg_set_voltage_fail: +regulator_put (curr_vreg->vreg); + curr_vreg->vreg =NULL ; + +vreg_get_fail: +for (i--; i >=0 ; i--) { + curr_vreg = &in_vreg[i]; + type = (regulator_count_voltages (curr_vreg->vreg) >0 ) + ?DSS_REG_LDO :DSS_REG_VS ; + goto vreg_unconfig; + } +return rc; +}/* msm_dss_config_vreg */ + +int msm_dss_enable_vreg (struct dss_vreg *in_vreg,int num_vreg,int enable) +{ +int i =0 , rc =0 ; +bool need_sleep; + +if (enable) { +for (i =0 ; i < num_vreg; i++) { + rc =PTR_RET (in_vreg[i].vreg); +if (rc) { +DEV_ERR ("%pS->%s: %s regulator error. rc=%d\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name, rc); + goto vreg_set_opt_mode_fail; + } + need_sleep = !regulator_is_enabled (in_vreg[i].vreg); +if (in_vreg[i].pre_on_sleep && need_sleep) +usleep_range (in_vreg[i].pre_on_sleep *1000 , + in_vreg[i].pre_on_sleep *1000 ); + rc =regulator_set_load (in_vreg[i].vreg, + in_vreg[i].enable_load); +if (rc <0 ) { +DEV_ERR ("%pS->%s: %s set opt m fail\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name); + goto vreg_set_opt_mode_fail; + } + rc =regulator_enable (in_vreg[i].vreg); +if (in_vreg[i].post_on_sleep && need_sleep) +usleep_range (in_vreg[i].post_on_sleep *1000 , + in_vreg[i].post_on_sleep *1000 ); +if (rc <0 ) { +DEV_ERR ("%pS->%s: %s enable failed\n" , +__builtin_return_address (0 ), __func__, + in_vreg[i].vreg_name); + goto disable_vreg; + } + } + }else { +for (i = num_vreg-1 ; i >=0 ; i--) { +if (in_vreg[i].pre_off_sleep) +usleep_range (in_vreg[i].pre_off_sleep *1000 , + in_vreg[i].pre_off_sleep *1000 ); +regulator_set_load (in_vreg[i].vreg, + in_vreg[i].disable_load); +regulator_disable (in_vreg[i].vreg); +if (in_vreg[i].post_off_sleep) +usleep_range (in_vreg[i].post_off_sleep *1000 , + in_vreg[i].post_off_sleep *1000 ); + } + } +return rc; + +disable_vreg: +regulator_set_load (in_vreg[i].vreg, in_vreg[i].disable_load); + +vreg_set_opt_mode_fail: +for (i--; i >=0 ; i--) { +if (in_vreg[i].pre_off_sleep) +usleep_range (in_vreg[i].pre_off_sleep *1000 , + in_vreg[i].pre_off_sleep *1000 ); + regulator_set_load(in_vreg[i].vreg,
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c line 225
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +10
-0+ in_vreg[i].disable_load); +regulator_disable (in_vreg[i].vreg); +if (in_vreg[i].post_off_sleep) +usleep_range (in_vreg[i].post_off_sleep *1000 , + in_vreg[i].post_off_sleep *1000 ); + } + +return rc; +}/* msm_dss_enable_vreg */ +
Same question here, but with dp_power.
Quoted 17 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c +1
-0+void msm_dss_put_clk (struct dss_clk *clk_arry,int num_clk) {int i;drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +1
-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)
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 29
Quoted 7 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +4
-0@@ -22,6 +23,39 @@ #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; +};
len isn't used anywhere, so this struct can go away. If the struct goes away, you can really simplify (or eliminate msm_dss_ioremap_byname())
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 40
Quoted 11 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +11
-0+ +/* +void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug); +u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug); +void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug); + +#define DSS_REG_W_ND(io, offset, val) dss_reg_w(io, offset, val, false) +#define DSS_REG_W(io, offset, val) dss_reg_w(io, offset, val, true) +#define DSS_REG_R_ND(io, offset) dss_reg_r(io, offset, false) +#define DSS_REG_R(io, offset) dss_reg_r(io, offset, true) +*/
None of the dss_reg_*/DSS_REG_* functions/macros are used. Please remove.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 44
Quoted 4 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +4
-0+enum dss_vreg_type { +DSS_REG_LDO , +DSS_REG_VS , +};
These are only used in msm_dss_config_vreg(). Please remove.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 50
Quoted 6 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +6
-0+ +struct dss_vreg { +struct regulator *vreg;/* vreg handle */ +char vreg_name[32 ]; +int min_voltage; +int max_voltage;
Can't we deduce these from the regulator subsystem with regulator_list_voltage()?
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 52
Quoted 2 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +2
-0+int enable_load; +int disable_load;
These are really a function of the dp device than the regulator.
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 56
Quoted 4 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +4
-0+int pre_on_sleep; +int post_on_sleep; +int pre_off_sleep; +int post_off_sleep;
None of these sleep values are set? Also, shouldn't these constraints usually expressed/acted upon in the regulator driver?
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h line 57
Quoted 1 line
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +1
-0+};
So if we can remove all of the extra goop around the regulator, then we can get rid of dss_vreg.
Quoted 16 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +3
-0+struct dss_gpio {unsigned int gpio;unsigned int value;@@ -42,12 +76,22 @@ 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;struct dss_clk *clk_config; };
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h struct dss_clk { · line 96
Quoted 10 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +8
-0+int msm_dss_ioremap_byname (struct platform_device *pdev, +struct dss_io_data *io_data,const char *name); +void msm_dss_iounmap (struct dss_io_data *io_data); + +int msm_dss_config_vreg (struct device *dev,struct dss_vreg *in_vreg, +int num_vreg,int config); +int msm_dss_enable_vreg (struct dss_vreg *in_vreg,int num_vreg,int enable); +int msm_dss_get_clk (struct device *dev,struct dss_clk *clk_arry,int num_clk);void msm_dss_put_clk (struct dss_clk *clk_arry,int num_clk);
Why are these msm_dss* functions in dpu_io_util.h?
drivers/gpu/drm/msm/dp/dp_aux.c
Quoted 7 lines
drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h +0
-0int msm_dss_clk_set_rate (struct dss_clk *clk_arry,int num_clk);drivers/gpu/drm/msm/dp/dp_aux.c new file +0
-0@@ -0,0 +1,570 @@
/snip
drivers/gpu/drm/msm/dp/dp_aux.h
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_aux.h new file +0
-0
/snip
I didn't really review the dp_aux.* files as-is. Please convert to using drm_dp_aux and I'll take another look.
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +14
-0@@ -0,0 +1,1188 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ +
drivers/gpu/drm/msm/dp/dp_catalog.c line 24
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/delay.h> +#include <drm/drm_dp_helper.h> + +#include "dp_catalog.h" +#include "dp_reg.h" + +#define DP_GET_MSB (x) (x >> 8) +#define DP_GET_LSB (x) (x & 0xff)
These aren't used anywhere
drivers/gpu/drm/msm/dp/dp_catalog.c line 27
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +3
-0+ +#define dp_read (offset) readl_relaxed((offset)) +#define dp_write (offset, data) writel_relaxed((data), (offset))
These macros aren't useful. I think you'd be much better having a read_/write_ for the different io types, ie:
static inline u32 dp_read_audio(struct dp_catalog *catalog, u32 offset)
{
return readl_relaxed(catalog->io->dp_link.base + offset);
}Then you can remove a ton of boilerplate code below getting base;
drivers/gpu/drm/msm/dp/dp_catalog.c line 29
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+ +#define dp_catalog_get_priv (x) { \
static inline struct dp_catalog_private *dp_catalog_get_priv(...)
{
...
}Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+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 | \
drivers/gpu/drm/msm/dp/dp_catalog.c line 49
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ + DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) + +#define DP_INTR_MASK1 (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_INTR_MASK2 (DP_INTERRUPT_STATUS2 << 2)
Can you please rename these to be consistent with each other? DP_INTERRUPT_STATUS2_MASK perhaps?
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +23
-0+ +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 */ +}; + +/* audio related catalog functions */ +struct dp_catalog_private { +struct device *dev; +struct dp_io *io; + +u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX ]; +struct dp_catalog dp_catalog;
drivers/gpu/drm/msm/dp/dp_catalog.c line 82
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+}; + +/* aux related catalog functions */ +static u32 dp_catalog_aux_read_data (struct dp_catalog_aux *aux) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" );
And another logging type, please remove pr_* and use a DPU_/DRM_/DRM_DEV_ variant.
drivers/gpu/drm/msm/dp/dp_catalog.c line 91
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +9
-0+ goto end; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +return dp_read (base +DP_AUX_DATA ); +end: +return 0 ;
... or you could just return directly in the if above and remove the label :) Same comment applies below.
Also, probably shouldn't return 0 in an error case.
Then again, I'm guessing hitting the NULL case is likely impossible, so you can probably remove all of the machinery around checking !aux.
Quoted 76 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +76
-0+} + +static int dp_catalog_aux_write_data (struct dp_catalog_aux *aux) +{ +int rc =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +dp_write (base +DP_AUX_DATA , aux->data); +end: +return rc; +} + +static int dp_catalog_aux_write_trans (struct dp_catalog_aux *aux) +{ +int rc =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +dp_write (base +DP_AUX_TRANS_CTRL , aux->data); +end: +return rc; +} + +static int dp_catalog_aux_clear_trans (struct dp_catalog_aux *aux,bool read) +{ +int rc =0 ; +u32 data =0 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); + rc = -EINVAL ; + goto end; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + +if (read) { + data =dp_read (base +DP_AUX_TRANS_CTRL ); + data &= ~BIT (9 ); +dp_write (base +DP_AUX_TRANS_CTRL , data); + }else { +dp_write (base +DP_AUX_TRANS_CTRL ,0 ); + } +end: +return rc; +} + +static void dp_catalog_aux_reset (struct dp_catalog_aux *aux) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) {
drivers/gpu/drm/msm/dp/dp_catalog.c line 177
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + + aux_ctrl =dp_read (base +DP_AUX_CTRL ); + + aux_ctrl |=BIT (1 );
What's BIT(1)? Can you please #define it?
drivers/gpu/drm/msm/dp/dp_catalog.c line 179
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+dp_write (base +DP_AUX_CTRL , aux_ctrl); +usleep_range (1000 ,1010 );/* h/w recommended delay */
10us diff is right on the line of enough delay to make usleep_range worth it. I'd recommend increasing to 100us to increase the chance of the scheduler being able to batch this wakeup with another.
drivers/gpu/drm/msm/dp/dp_catalog.c line 183
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ + aux_ctrl &= ~BIT (1 ); +dp_write (base +DP_AUX_CTRL , aux_ctrl); +wmb ();
Can you just use writel for these cases instead of using _relaxed and then wmb()? This applies elsewhere too.
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+} + +static void dp_catalog_aux_enable (struct dp_catalog_aux *aux,bool enable) +{ +u32 aux_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!aux) { +pr_err ("invalid input\n" ); +return ; + }
drivers/gpu/drm/msm/dp/dp_catalog.c line 205
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +dp_catalog_get_priv (aux); + base = catalog->io->dp_aux.base; + + aux_ctrl =dp_read (base +DP_AUX_CTRL ); + +if (enable) { +dp_write (base +DP_TIMEOUT_COUNT ,0xffff ); +dp_write (base +DP_AUX_LIMITS ,0xffff ); + aux_ctrl |=BIT (0 );
Please #define BIT(0)
Quoted 35 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +35
-0+ }else { + aux_ctrl &= ~BIT (0 ); + } + +dp_write (base +DP_AUX_CTRL , aux_ctrl); +} + +static 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 )) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + + current_index = cfg[type].current_index; + new_index = (current_index +1 ) % cfg[type].cfg_cnt; +pr_debug ("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 (catalog->io->phy_io.base + cfg[type].offset, + cfg[type].lut[new_index]); + cfg[type].current_index = new_index; +} + +static void dp_catalog_aux_setup (struct dp_catalog_aux *aux, +struct dp_aux_cfg *cfg) +{ +struct dp_catalog_private *catalog;
drivers/gpu/drm/msm/dp/dp_catalog.c line 250
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+int i =0 ; + +if (!aux || !cfg) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + +dp_write (catalog->io->phy_io.base +DP_PHY_PD_CTL ,0x65 );
What's 0x65? Please #define
drivers/gpu/drm/msm/dp/dp_catalog.c line 255
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+wmb ();/* make sure PD programming happened */ + +/* Turn on BIAS current for PHY/PLL */ +dp_write (catalog->io->dp_pll_io.base + +QSERDES_COM_BIAS_EN_CLKBUFLR_EN ,0x1b );
Same here for 0x1b. I'm going to stop mentioning this, please audit the driver for other instances of hardcoded values (like this and the one at the end of this function) and break them out into meaningful #defines.
Quoted 118 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +118
-0+ +/* DP AUX CFG register programming */ +for (i =0 ; i <PHY_AUX_CFG_MAX ; i++) { +pr_debug ("%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 (catalog->io->phy_io.base + cfg[i].offset, + cfg[i].lut[cfg[i].current_index]); + } + +dp_write (catalog->io->phy_io.base +DP_PHY_AUX_INTERRUPT_MASK ,0x1F ); +} + +static void dp_catalog_aux_get_irq (struct dp_catalog_aux *aux,bool cmd_busy) +{ +u32 ack; +struct dp_catalog_private *catalog; +void __iomem *ahb_base; + +if (!aux) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (aux); + ahb_base = catalog->io->dp_ahb.base; + + aux->isr =dp_read (ahb_base +DP_INTR_STATUS ); + aux->isr &= ~DP_INTR_MASK1 ; + ack = aux->isr &DP_INTERRUPT_STATUS1 ; + ack <<=1 ; + ack |=DP_INTR_MASK1 ; +dp_write (ahb_base +DP_INTR_STATUS , ack); +} + +/* controller related catalog functions */ +static void dp_catalog_ctrl_update_transfer_unit (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +dp_write (base +DP_VALID_BOUNDARY , ctrl->valid_boundary); +dp_write (base +DP_TU , ctrl->dp_tu); +dp_write (base +DP_VALID_BOUNDARY_2 , ctrl->valid_boundary2); +} + +static void dp_catalog_ctrl_state_ctrl (struct dp_catalog_ctrl *ctrl,u32 state) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +dp_write (base +DP_STATE_CTRL , state); +} + +static void dp_catalog_ctrl_config_ctrl (struct dp_catalog_ctrl *ctrl,u32 cfg) +{ +struct dp_catalog_private *catalog; +void __iomem *link_base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + link_base = catalog->io->dp_link.base; + +pr_debug ("DP_CONFIGURATION_CTRL=0x%x\n" , cfg); + +dp_write (link_base +DP_CONFIGURATION_CTRL , cfg); +} + +static void dp_catalog_ctrl_lane_mapping (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +dp_write (base +DP_LOGICAL2PHYSICAL_LANE_MAPPING ,0xe4 ); +} + +static void dp_catalog_ctrl_mainlink_ctrl (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +u32 mainlink_ctrl; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base;
drivers/gpu/drm/msm/dp/dp_catalog.c line 383
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +if (enable) { +dp_write (base +DP_MAINLINK_CTRL ,0x02000000 ); +wmb ();/* make sure mainlink is turned off before reset */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000002 ); +wmb ();/* make sure mainlink entered reset */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000000 ); +wmb ();/* make sure mainlink reset done */ +dp_write (base +DP_MAINLINK_CTRL ,0x02000001 ); +wmb ();/* make sure mainlink turned on */
Same comments here re: readl vs readl_relaxed + wmb
Please #define the bits you're setting.
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +14
-0+ }else { + mainlink_ctrl =dp_read (base +DP_MAINLINK_CTRL ); + mainlink_ctrl &= ~BIT (0 ); +dp_write (base +DP_MAINLINK_CTRL , mainlink_ctrl); + } +} + +static void dp_catalog_ctrl_config_misc (struct dp_catalog_ctrl *ctrl, +u32 cc,u32 tb) +{ +u32 misc_val; +struct dp_catalog_private *catalog; +void __iomem *base; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 407
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + + misc_val =dp_read (base +DP_MISC1_MISC0 ); + misc_val |= cc;
Should you mask this so it doesn't stomp areas it shouldn't?
drivers/gpu/drm/msm/dp/dp_catalog.c line 408
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+ misc_val |= (tb <<5 );
Parentheses are unnecessary
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ misc_val |=BIT (0 );/* Configure clock to synchronous mode */ + +pr_debug ("misc settings = 0x%x\n" , misc_val); +dp_write (base +DP_MISC1_MISC0 , misc_val);
drivers/gpu/drm/msm/dp/dp_catalog.c line 422
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+} + +static 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 ;
You should pull this out into a #define in drm_dp_helper.h and use the new define in the i915 driver (in a separate patch) as well as here.
Quoted 37 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +37
-0+u32 const link_rate_hbr2 =540000 ; +u32 const link_rate_hbr3 =810000 ; +struct dp_catalog_private *catalog; +void __iomem *base_cc, *base_ctrl; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); +if (fixed_nvid) { +pr_debug ("use fixed NVID=0x%x\n" , nvid_fixed); + nvid = nvid_fixed; + +pr_debug ("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 { + base_cc = catalog->io->dp_cc_io.base; + + pixel_m =dp_read (base_cc +MMSS_DP_PIXEL_M ); + pixel_n =dp_read (base_cc +MMSS_DP_PIXEL_N ); +pr_debug ("pixel_m=0x%x, pixel_n=0x%x\n" , pixel_m, pixel_n); +
drivers/gpu/drm/msm/dp/dp_catalog.c line 469
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ mvid = (pixel_m &0xFFFF ) *5 ; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m &0xFFFF ); + +pr_debug ("rate = %d\n" , rate); + +if (link_rate_hbr2 == rate) + nvid *=2 ; + +if (link_rate_hbr3 == rate) + nvid *=3 ;
switch (drm_dp_bw_code_to_link_rate(rate)) {
case DP_LINK_BW_5_4:
nvid *= 2;
break;
case DP_LINK_BW_8_1:
nvid *= 3;
break;
default:
break;
}And remove link_rate_hbr* above.
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +16
-0+ } + + base_ctrl = catalog->io->dp_link.base; +pr_debug ("mvid=0x%x, nvid=0x%x\n" , mvid, nvid); +dp_write (base_ctrl +DP_SOFTWARE_MVID , mvid); +dp_write (base_ctrl +DP_SOFTWARE_NVID , nvid); +} + +static void dp_catalog_ctrl_set_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +int bit, cnt =10 ; +u32 data; +struct dp_catalog_private *catalog; +void __iomem *base; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 495
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + + bit =1 ; + bit <<= (pattern -1 );
bit = BIT(pattern - 1);
drivers/gpu/drm/msm/dp/dp_catalog.c line 500
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+pr_debug ("hw: bit=%d train=%d\n" , bit, pattern); +dp_write (base +DP_STATE_CTRL , bit); + + bit =8 ; + bit <<= (pattern -1 );
bit = BIT(pattern - 1) << 3;
drivers/gpu/drm/msm/dp/dp_catalog.c line 505
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+ +while (cnt--) { + data =dp_read (base +DP_MAINLINK_READY ); +if (data & bit) +break ;
Should there be a sleep in here? Also, consider using readx_poll_timeout instead of rolling your own polling.
drivers/gpu/drm/msm/dp/dp_catalog.c line 509
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ } + +if (cnt ==0 ) +pr_err ("set link_train=%d failed\n" , pattern);
This function should return an int and report this failure instead of ignoring it.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +7
-0+} + +static void dp_catalog_ctrl_usb_reset (struct dp_catalog_ctrl *ctrl,bool flip) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 526
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + base = catalog->io->usb3_dp_com.base; + +dp_write (base +USB3_DP_COM_RESET_OVRD_CTRL ,0x0a );
Again, all of these magic values need to be pulled out into #defines so we know what the values mean.
drivers/gpu/drm/msm/dp/dp_catalog.c line 530
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+dp_write (base +USB3_DP_COM_PHY_MODE_CTRL ,0x02 ); +dp_write (base +USB3_DP_COM_SW_RESET ,0x01 ); +/* make sure usb3 com phy software reset is done */ +wmb ();
Same comments here wrt wmb()
drivers/gpu/drm/msm/dp/dp_catalog.c line 535
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+ +if (!flip)/* CC1 */ +dp_write (base +USB3_DP_COM_TYPEC_CTRL ,0x02 ); +else /* CC2 */ +dp_write (base +USB3_DP_COM_TYPEC_CTRL ,0x03 );
u32 val;
...
val = SOME_DEFINE_THAT_MAKES_SENSE;
if (flip)
val |= ANOTHER_DEFINE_THAT_MEANS_FLIP;
dp_io_write(USB3_DP_COM_TYPEC_CTRL, val);Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +24
-0+ +dp_write (base +USB3_DP_COM_SWI_CTRL ,0x00 ); +dp_write (base +USB3_DP_COM_SW_RESET ,0x00 ); +/* make sure the software reset is done */ +wmb (); + +dp_write (base +USB3_DP_COM_POWER_DOWN_CTRL ,0x01 ); +dp_write (base +USB3_DP_COM_RESET_OVRD_CTRL ,0x00 ); +/* make sure phy is brought out of reset */ +wmb (); + +} + +static void dp_catalog_panel_tpg_cfg (struct dp_catalog_panel *panel, +bool enable) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!panel) { +pr_err ("invalid input\n" ); +return ; + } +
drivers/gpu/drm/msm/dp/dp_catalog.c line 569
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_catalog_get_priv (panel); + base = catalog->io->dp_p0.base; + +if (!enable) { +dp_write (base +MMSS_DP_TPG_MAIN_CONTROL ,0x0 ); +dp_write (base +MMSS_DP_BIST_ENABLE ,0x0 ); +dp_write (base +MMSS_DP_TIMING_ENGINE_EN ,0x0 ); +wmb ();/* ensure Timing generator is turned off */ +return ; + }
There's really no reason to have both the enable + disable path in the same function, they don't share any code (aside from writing a few different values to the same registers). Could you please split this function into a timing_generator_disable and timing_generator_enable?
Quoted 38 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +38
-0+ +dp_write (base +MMSS_DP_INTF_CONFIG ,0x0 ); +dp_write (base +MMSS_DP_INTF_HSYNC_CTL , panel->hsync_ctl); +dp_write (base +MMSS_DP_INTF_VSYNC_PERIOD_F0 , panel->vsync_period * + panel->hsync_period); +dp_write (base +MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0 , panel->v_sync_width * + panel->hsync_period); +dp_write (base +MMSS_DP_INTF_VSYNC_PERIOD_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_DISPLAY_HCTL , panel->display_hctl); +dp_write (base +MMSS_DP_INTF_ACTIVE_HCTL ,0 ); +dp_write (base +MMSS_INTF_DISPLAY_V_START_F0 , panel->display_v_start); +dp_write (base +MMSS_DP_INTF_DISPLAY_V_END_F0 , panel->display_v_end); +dp_write (base +MMSS_INTF_DISPLAY_V_START_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_DISPLAY_V_END_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_ACTIVE_V_START_F0 ,0 ); +dp_write (base +MMSS_DP_INTF_ACTIVE_V_END_F0 ,0 ); +dp_write (base +MMSS_DP_INTF_ACTIVE_V_START_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_ACTIVE_V_END_F1 ,0 ); +dp_write (base +MMSS_DP_INTF_POLARITY_CTL ,0 ); +wmb ();/* ensure TPG registers are programmed */ + +dp_write (base +MMSS_DP_TPG_MAIN_CONTROL ,0x100 ); +dp_write (base +MMSS_DP_TPG_VIDEO_CONFIG ,0x5 ); +wmb ();/* ensure TPG config is programmed */ +dp_write (base +MMSS_DP_BIST_ENABLE ,0x1 ); +dp_write (base +MMSS_DP_TIMING_ENGINE_EN ,0x1 ); +wmb ();/* ensure Timing generator is turned on */ +pr_debug ("%s: enabled tpg\n" , __func__); +} + +static void dp_catalog_ctrl_reset (struct dp_catalog_ctrl *ctrl) +{ +u32 sw_reset; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) {
drivers/gpu/drm/msm/dp/dp_catalog.c line 617
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + + sw_reset =dp_read (base +DP_SW_RESET ); + + sw_reset |=BIT (0 );
Should be a #define
drivers/gpu/drm/msm/dp/dp_catalog.c line 619
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+dp_write (base +DP_SW_RESET , sw_reset); +usleep_range (1000 ,1010 );/* h/w recommended delay */
Same comment here regarding the 10us range
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +17
-0+ + sw_reset &= ~BIT (0 ); +dp_write (base +DP_SW_RESET , sw_reset); +} + +static bool dp_catalog_ctrl_mainlink_ready (struct dp_catalog_ctrl *ctrl) +{ +u32 data; +int cnt =10 ; +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); + goto end; + } +
drivers/gpu/drm/msm/dp/dp_catalog.c line 646
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_catalog_get_priv (ctrl); + base = catalog->io->dp_link.base; + +while (--cnt) { +/* DP_MAINLINK_READY */ + data =dp_read (base +DP_MAINLINK_READY ); +if (data &BIT (0 )) +return true; + +usleep_range (1000 ,1010 );/* 1ms wait before next reg read */
Same comment here regarding using readx_poll_timeout wrapped in a helper, also 10us comment.
Quoted 40 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +40
-0+ } +pr_err ("mainlink not ready\n" ); +end: +return false; +} + +static void dp_catalog_ctrl_enable_irq (struct dp_catalog_ctrl *ctrl, +bool enable) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + +if (enable) { +dp_write (base +DP_INTR_STATUS ,DP_INTR_MASK1 ); +dp_write (base +DP_INTR_STATUS2 ,DP_INTR_MASK2 ); + }else { +dp_write (base +DP_INTR_STATUS ,0x00 ); +dp_write (base +DP_INTR_STATUS2 ,0x00 ); + } +} + +static void dp_catalog_ctrl_hpd_config (struct dp_catalog_ctrl *ctrl,bool en) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl);
drivers/gpu/drm/msm/dp/dp_catalog.c line 696
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ base = catalog->io->dp_aux.base; + +if (en) { +u32 reftimer =dp_read (base +DP_DP_HPD_REFTIMER ); + +dp_write (base +DP_DP_HPD_INT_ACK ,0xF ); +dp_write (base +DP_DP_HPD_INT_MASK ,0xF ); + +/* Enabling REFTIMER */ + reftimer |=BIT (16 );
You don't use this anywhere?
drivers/gpu/drm/msm/dp/dp_catalog.c line 701
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+dp_write (base +DP_DP_HPD_REFTIMER ,0xF ); +/* Enable HPD */ +dp_write (base +DP_DP_HPD_CTRL ,0x1 ); + }else { +/*Disable HPD */
Space after *
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +9
-0+dp_write (base +DP_DP_HPD_CTRL ,0x0 ); + } +} + +static void dp_catalog_ctrl_get_interrupt (struct dp_catalog_ctrl *ctrl) +{ +u32 ack =0 ; +struct dp_catalog_private *catalog; +void __iomem *base;
drivers/gpu/drm/msm/dp/dp_catalog.c line 720
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + + ctrl->isr =dp_read (base +DP_INTR_STATUS2 );
This value should just get returned instead of being stored.
drivers/gpu/drm/msm/dp/dp_catalog.c line 721
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+ ctrl->isr &= ~DP_INTR_MASK2 ;
Unmasking the interrupts should not be returned from this function, it should be part of the ack below.
drivers/gpu/drm/msm/dp/dp_catalog.c line 722
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+ ack = ctrl->isr &DP_INTERRUPT_STATUS2 ;
And this does the above unmask already, so you can just turf it.
drivers/gpu/drm/msm/dp/dp_catalog.c line 724
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+ ack <<=1 ; + ack |=DP_INTR_MASK2 ;
Instead of rolling the ack code yourself, I'd prefer what you did with _MASK, where you define DP_INTERRUPT_STATUS2_ACK above and just do a bitwise-OR to add the acks here. Without the register map in front of me, it would take a while to figure out what you're trying to accomplish.
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +7
-0+dp_write (base +DP_INTR_STATUS2 , ack); +} + +static void dp_catalog_ctrl_phy_reset (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +void __iomem *base;
drivers/gpu/drm/msm/dp/dp_catalog.c line 741
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + base = catalog->io->dp_ahb.base; + +dp_write (base +DP_PHY_CTRL ,0x5 );/* bit 0 & 2 */
The comment doesn't help here, please #define these bits
drivers/gpu/drm/msm/dp/dp_catalog.c line 742
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_catalog.c new file +1
-0+usleep_range (1000 ,1010 );/* h/w recommended delay */
Same comment re: delay range
drivers/gpu/drm/msm/dp/dp_catalog.c line 744
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +2
-0+dp_write (base +DP_PHY_CTRL ,0x0 ); +wmb ();/* make sure PHY reset done */
Same comment re: wmb
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +7
-0+} + +static 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;
drivers/gpu/drm/msm/dp/dp_catalog.c line 761
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+u8 orientation =BIT (!!flipped); + +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + info |= (ln_cnt &0x0F );
Remove the | and just make this an assignment (and you can remove the initialization to 0 above)
drivers/gpu/drm/msm/dp/dp_catalog.c line 773
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +12
-0+ info |= ((orientation &0x0F ) <<4 ); +pr_debug ("Shared Info = 0x%x\n" , info); + +dp_write (catalog->io->phy_io.base +DP_PHY_SPARE0 , info); +} + +static void dp_catalog_ctrl_update_vx_px (struct dp_catalog_ctrl *ctrl, +u8 v_level,u8 p_level) +{ +struct dp_catalog_private *catalog; +void __iomem *base0, *base1; +u8 value0, value1;
Can we please pick better names for these?!
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +6
-0+ +if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } +
drivers/gpu/drm/msm/dp/dp_catalog.c line 789
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_catalog_get_priv (ctrl); + base0 = catalog->io->ln_tx0_io.base; + base1 = catalog->io->ln_tx1_io.base; + +pr_debug ("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]; + +/* program default setting first */
Why do you need to do this?
drivers/gpu/drm/msm/dp/dp_catalog.c line 793
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+dp_write (base0 + TXn_TX_DRV_LVL,0x2A ); +dp_write (base1 + TXn_TX_DRV_LVL,0x2A ); +dp_write (base0 + TXn_TX_EMP_POST1_LVL,0x20 ); +dp_write (base1 + TXn_TX_EMP_POST1_LVL,0x20 );
#define these magic values
drivers/gpu/drm/msm/dp/dp_catalog.c line 797
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +4
-0+ +/* Enable MUX to use Cursor values from these registers */ + value0 |=BIT (5 ); + value1 |=BIT (5 );
#define these bits please
drivers/gpu/drm/msm/dp/dp_catalog.c line 800
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +3
-0+ +/* Configure host and panel only if both values are allowed */ +if (value0 !=0xFF && value1 !=0xFF ) {
You can check this a lot earlier in the function.
drivers/gpu/drm/msm/dp/dp_catalog.c line 810
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_write (base0 + TXn_TX_DRV_LVL, value0); +dp_write (base1 + TXn_TX_DRV_LVL, value0); +dp_write (base0 + TXn_TX_EMP_POST1_LVL, value1); +dp_write (base1 + TXn_TX_EMP_POST1_LVL, value1); + +pr_debug ("hw: vx_value=0x%x px_value=0x%x\n" , + value0, value1); + }else { +pr_err ("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n" , + v_level, value0, p_level, value1);
Seems like returning an error in this case would be useful
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ } +} + +static void dp_catalog_ctrl_send_phy_pattern (struct dp_catalog_ctrl *ctrl, +u32 pattern) +{ +struct dp_catalog_private *catalog; +u32 value =0x0 ; +void __iomem *base =NULL ; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 830
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+if (!ctrl) { +pr_err ("invalid input\n" ); +return ; + } + +dp_catalog_get_priv (ctrl); + + base = catalog->io->dp_link.base; + +dp_write (base +DP_STATE_CTRL ,0x0 );
Do you really need to do this?
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +22
-0+ +switch (pattern) { +case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING : +dp_write (base +DP_STATE_CTRL ,0x1 ); +break ; +case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT : + value &= ~(1 <<16 ); +dp_write (base +DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=0xFC ; +dp_write (base +DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write (base +DP_MAINLINK_LEVELS ,0x2 ); +dp_write (base +DP_STATE_CTRL ,0x10 ); +break ; +case DP_TEST_PHY_PATTERN_PRBS7 : +dp_write (base +DP_STATE_CTRL ,0x20 ); +break ; +case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN : +dp_write (base +DP_STATE_CTRL ,0x40 ); +/* 00111110000011111000001111100000 */ +dp_write (base +DP_TEST_80BIT_CUSTOM_PATTERN_REG0 ,0x3E0F83E0 ); +/* 00001111100000111110000011111000 */ +dp_write (base +DP_TEST_80BIT_CUSTOM_PATTERN_REG1 ,0x0F83E0F8 );
drivers/gpu/drm/msm/dp/dp_catalog.c line 862
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+/* 1111100000111110 */ +dp_write (base +DP_TEST_80BIT_CUSTOM_PATTERN_REG2 ,0x0000F83E ); +break ; +case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN : + value =BIT (16 ); +dp_write (base +DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); + value |=0xFC ; +dp_write (base +DP_HBR2_COMPLIANCE_SCRAMBLER_RESET , value); +dp_write (base +DP_MAINLINK_LEVELS ,0x2 ); +dp_write (base +DP_STATE_CTRL ,0x10 );
This code is the exact same as the case for DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT, aside from BIT(16) vs ~BIT(16). Can you please combine these cases and share code?
drivers/gpu/drm/msm/dp/dp_catalog.c line 867
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +5
-0+break ; +default : +pr_debug ("No valid test pattern requested: 0x%x\n" , pattern); +return ; + }
All of the DP_STATE_CTRL values should be #defined, and you can move the write down here instead of duplicating it everywhere (with DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN writing a 0).
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +31
-0+ +/* Make sure the test pattern is programmed in the hardware */ +wmb (); +} + +static u32 dp_catalog_ctrl_read_phy_pattern (struct dp_catalog_ctrl *ctrl) +{ +struct dp_catalog_private *catalog; +void __iomem *base =NULL ; + +if (!ctrl) { +pr_err ("invalid input\n" ); +return 0 ; + } + +dp_catalog_get_priv (ctrl); + + base = catalog->io->dp_link.base; + +return dp_read (base +DP_MAINLINK_READY ); +} + +/* panel related catalog functions */ +static int dp_catalog_panel_timing_cfg (struct dp_catalog_panel *panel) +{ +struct dp_catalog_private *catalog; +void __iomem *base; + +if (!panel) { +pr_err ("invalid input\n" ); + goto end;
drivers/gpu/drm/msm/dp/dp_catalog.c line 908
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ } + +dp_catalog_get_priv (panel); + base = catalog->io->dp_link.base; + +dp_write (base +DP_TOTAL_HOR_VER , panel->total); +dp_write (base +DP_START_HOR_VER_FROM_SYNC , panel->sync_start); +dp_write (base +DP_HSYNC_VSYNC_WIDTH_POLARITY , panel->width_blanking); +dp_write (base +DP_ACTIVE_HOR_VER , panel->dp_active); +end:
useless label, but it'll probably go away when you strip out all of the unnecessary NULL checks from the driver.
Quoted 30 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +30
-0+return 0 ; +} + +static void dp_catalog_audio_init (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX ] = { + { +MMSS_DP_AUDIO_STREAM_0 , +MMSS_DP_AUDIO_STREAM_1 , +MMSS_DP_AUDIO_STREAM_1 , + }, + { +MMSS_DP_AUDIO_TIMESTAMP_0 , +MMSS_DP_AUDIO_TIMESTAMP_1 , +MMSS_DP_AUDIO_TIMESTAMP_1 , + }, + { +MMSS_DP_AUDIO_INFOFRAME_0 , +MMSS_DP_AUDIO_INFOFRAME_1 , +MMSS_DP_AUDIO_INFOFRAME_1 , + }, + { +MMSS_DP_AUDIO_COPYMANAGEMENT_0 , +MMSS_DP_AUDIO_COPYMANAGEMENT_1 , +MMSS_DP_AUDIO_COPYMANAGEMENT_1 , + }, + { +MMSS_DP_AUDIO_ISRC_0 , +MMSS_DP_AUDIO_ISRC_1 ,
drivers/gpu/drm/msm/dp/dp_catalog.c line 948
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ MMSS_DP_AUDIO_ISRC_1, + }, + }; + +if (!audio) +return ; + +dp_catalog_get_priv (audio); + + catalog->audio_map = sdp_map;
Hmm, this is a bit spooky, we're storing a (non-const) pointer to a static stack variable. Fortunately this looks like it'll be easy to fix since this data is only accessed in this file. So move the map into a static const global and reference it directly when needed (and drop audio_map).
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +17
-0+} + +static void dp_catalog_audio_config_sdp (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +u32 sdp_cfg =0 ; +u32 sdp_cfg2 =0 ; + +if (!audio) +return ; + +dp_catalog_get_priv (audio); + base = catalog->io->dp_link.base; + + sdp_cfg =dp_read (base +MMSS_DP_SDP_CFG ); +
drivers/gpu/drm/msm/dp/dp_catalog.c line 975
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+/* AUDIO_TIMESTAMP_SDP_EN */ + sdp_cfg |=BIT (1 ); +/* AUDIO_STREAM_SDP_EN */ + sdp_cfg |=BIT (2 ); +/* AUDIO_COPY_MANAGEMENT_SDP_EN */ + sdp_cfg |=BIT (5 ); +/* AUDIO_ISRC_SDP_EN */ + sdp_cfg |=BIT (6 ); +/* AUDIO_INFOFRAME_SDP_EN */ + sdp_cfg |=BIT (20 );
#define the values and combine the assignment
drivers/gpu/drm/msm/dp/dp_catalog.c line 984
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +9
-0+ +pr_debug ("sdp_cfg = 0x%x\n" , sdp_cfg); +dp_write (base +MMSS_DP_SDP_CFG , sdp_cfg); + + sdp_cfg2 =dp_read (base +MMSS_DP_SDP_CFG2 ); +/* IFRM_REGSRC -> Do not use reg values */ + sdp_cfg2 &= ~BIT (0 ); +/* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ + sdp_cfg2 &= ~BIT (1 );
The reset value of this register is 0x4, so how can the bits in position 0/1 get flipped? We shouldn't need this code, afaict.
If we do, the same comments regarding #define and combination as above.
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +15
-0+ +pr_debug ("sdp_cfg2 = 0x%x\n" , sdp_cfg2); +dp_write (base +MMSS_DP_SDP_CFG2 , sdp_cfg2); +} + +static void dp_catalog_audio_get_header (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX ]; +void __iomem *base; +enum dp_catalog_audio_sdp_type sdp; +enum dp_catalog_audio_header_type header; + +if (!audio) +return ;
drivers/gpu/drm/msm/dp/dp_catalog.c line 1009
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + sdp_map = catalog->audio_map; + sdp = audio->sdp_type; + header = audio->sdp_header; + + audio->data =dp_read (base + sdp_map[sdp][header]); +}
This function is unused, please remove.
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +13
-0+ +static void dp_catalog_audio_set_header (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX ]; +void __iomem *base; +enum dp_catalog_audio_sdp_type sdp; +enum dp_catalog_audio_header_type header; +u32 data; + +if (!audio) +return ; +
drivers/gpu/drm/msm/dp/dp_catalog.c line 1032
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + sdp_map = catalog->audio_map; + sdp = audio->sdp_type; + header = audio->sdp_header; + data = audio->data; + +dp_write (base + sdp_map[sdp][header], data); +}
This function is unused, please remove.
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +8
-0+ +static void dp_catalog_audio_config_acr (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +u32 acr_ctrl, select; + +dp_catalog_get_priv (audio);
drivers/gpu/drm/msm/dp/dp_catalog.c line 1050
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ + select = audio->data; + base = catalog->io->dp_link.base; + + acr_ctrl = select <<4 |BIT (31 ) |BIT (8 ) |BIT (14 ); + +pr_debug ("select = 0x%x, acr_ctrl = 0x%x\n" , select, acr_ctrl); + +dp_write (base +MMSS_DP_AUDIO_ACR_CTRL , acr_ctrl); +}
This function is unused, please remove.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +11
-0+ +static void dp_catalog_audio_safe_to_exit_level (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +u32 mainlink_levels, safe_to_exit_level; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + safe_to_exit_level = audio->data;
drivers/gpu/drm/msm/dp/dp_catalog.c line 1071
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ + mainlink_levels =dp_read (base +DP_MAINLINK_LEVELS ); + mainlink_levels &=0xFE0 ; + mainlink_levels |= safe_to_exit_level; + +pr_debug ("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n" , + mainlink_levels, safe_to_exit_level); + +dp_write (base +DP_MAINLINK_LEVELS , mainlink_levels); +}
This function is unused, please remove.
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +16
-0+ +static void dp_catalog_audio_enable (struct dp_catalog_audio *audio) +{ +struct dp_catalog_private *catalog; +void __iomem *base; +bool enable; +u32 audio_ctrl; + +dp_catalog_get_priv (audio); + + base = catalog->io->dp_link.base; + enable = !!audio->data; + + audio_ctrl =dp_read (base +MMSS_DP_AUDIO_CFG ); + +if (enable)
drivers/gpu/drm/msm/dp/dp_catalog.c line 1097
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ audio_ctrl |=BIT (0 ); + else + audio_ctrl &= ~BIT(0); + +pr_debug ("dp_audio_cfg = 0x%x\n" , audio_ctrl); +dp_write (base +MMSS_DP_AUDIO_CFG , audio_ctrl); + +/* make sure audio engine is disabled */ +wmb (); +}
This function is unused, please remove.
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +6
-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;
drivers/gpu/drm/msm/dp/dp_catalog.c line 1113
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+struct dp_catalog_aux aux = { + .read_data = dp_catalog_aux_read_data, + .write_data = dp_catalog_aux_write_data, + .write_trans = dp_catalog_aux_write_trans, + .clear_trans = dp_catalog_aux_clear_trans, + .reset = dp_catalog_aux_reset, + .update_aux_cfg = dp_catalog_aux_update_cfg, + .enable = dp_catalog_aux_enable, + .setup = dp_catalog_aux_setup, + .get_irq = dp_catalog_aux_get_irq,
Out of these, it seems like write_trans, clear_trans, update_aux_cfg, setup and get_irq are all unused. Please remove them.
Please also check the other functions to ensure they're used.
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +11
-0+ }; +struct dp_catalog_ctrl ctrl = { + .state_ctrl = dp_catalog_ctrl_state_ctrl, + .config_ctrl = dp_catalog_ctrl_config_ctrl, + .lane_mapping = dp_catalog_ctrl_lane_mapping, + .mainlink_ctrl = dp_catalog_ctrl_mainlink_ctrl, + .config_misc = dp_catalog_ctrl_config_misc, + .config_msa = dp_catalog_ctrl_config_msa, + .set_pattern = dp_catalog_ctrl_set_pattern, + .reset = dp_catalog_ctrl_reset, + .usb_reset = dp_catalog_ctrl_usb_reset,
drivers/gpu/drm/msm/dp/dp_catalog.c line 1134
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +10
-0+ .mainlink_ready = dp_catalog_ctrl_mainlink_ready, + .enable_irq = dp_catalog_ctrl_enable_irq, + .hpd_config = dp_catalog_ctrl_hpd_config, + .phy_reset = dp_catalog_ctrl_phy_reset, + .phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg, + .update_vx_px = dp_catalog_ctrl_update_vx_px, + .get_interrupt = dp_catalog_ctrl_get_interrupt, + .update_transfer_unit = dp_catalog_ctrl_update_transfer_unit, + .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern, + .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern,
So, what's the benefit of adding the catalog abstractions? Do you ever have multiple/alternate implementations of a catalog? It doesn't seem like it. You should just remove all of the catalog overhead and call the functions directly.
Quoted 162 lines
drivers/gpu/drm/msm/dp/dp_catalog.c new file +54
-0+ }; +struct dp_catalog_audio audio = { + .init = dp_catalog_audio_init, + .config_acr = dp_catalog_audio_config_acr, + .enable = dp_catalog_audio_enable, + .config_sdp = dp_catalog_audio_config_sdp, + .set_header = dp_catalog_audio_set_header, + .get_header = dp_catalog_audio_get_header, + .safe_to_exit_level = dp_catalog_audio_safe_to_exit_level, + }; +struct dp_catalog_panel panel = { + .timing_cfg = dp_catalog_panel_timing_cfg, + .tpg_config = dp_catalog_panel_tpg_cfg, + }; + +if (!io) { +pr_err ("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; + + dp_catalog->aux = aux; + dp_catalog->ctrl = ctrl; + dp_catalog->audio = audio; + dp_catalog->panel = panel; + +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 +102
-0@@ -0,0 +1,144 @@ +/* +* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _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; + + u32 (*read_data)(struct dp_catalog_aux *aux); + int (*write_data)(struct dp_catalog_aux *aux); + int (*write_trans)(struct dp_catalog_aux *aux); + int (*clear_trans)(struct dp_catalog_aux *aux, bool read); + void (*reset)(struct dp_catalog_aux *aux); + void (*enable)(struct dp_catalog_aux *aux, bool enable); + void (*update_aux_cfg)(struct dp_catalog_aux *aux, + struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type); + void (*setup)(struct dp_catalog_aux *aux, + struct dp_aux_cfg *aux_cfg); + void (*get_irq)(struct dp_catalog_aux *aux, bool cmd_busy); +}; + +struct dp_catalog_ctrl { + u32 dp_tu; + u32 valid_boundary; + u32 valid_boundary2; + u32 isr; + + void (*state_ctrl)(struct dp_catalog_ctrl *ctrl, u32 state); + void (*config_ctrl)(struct dp_catalog_ctrl *ctrl, u32 config); + void (*lane_mapping)(struct dp_catalog_ctrl *ctrl); + void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable); + void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb); + void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate, + u32 stream_rate_khz, bool fixed_nvid); + void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); + void (*reset)(struct dp_catalog_ctrl *ctrl); + void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip); + bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl); + void (*enable_irq)(struct dp_catalog_ctrl *ctrl, bool enable); + void (*hpd_config)(struct dp_catalog_ctrl *ctrl, bool enable); + void (*phy_reset)(struct dp_catalog_ctrl *ctrl); + void (*phy_lane_cfg)(struct dp_catalog_ctrl *ctrl, bool flipped, + u8 lane_cnt); + void (*update_vx_px)(struct dp_catalog_ctrl *ctrl, u8 v_level, + u8 p_level); + void (*get_interrupt)(struct dp_catalog_ctrl *ctrl); + void (*update_transfer_unit)(struct dp_catalog_ctrl *ctrl); + void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl, + u32 pattern); + u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl); +}; + +enum dp_catalog_audio_sdp_type { + DP_AUDIO_SDP_STREAM, + DP_AUDIO_SDP_TIMESTAMP, + DP_AUDIO_SDP_INFOFRAME, + DP_AUDIO_SDP_COPYMANAGEMENT, + DP_AUDIO_SDP_ISRC, + DP_AUDIO_SDP_MAX, +}; + +enum dp_catalog_audio_header_type { + DP_AUDIO_SDP_HEADER_1, + DP_AUDIO_SDP_HEADER_2, + DP_AUDIO_SDP_HEADER_3, + DP_AUDIO_SDP_HEADER_MAX, +}; + +struct dp_catalog_audio { + enum dp_catalog_audio_sdp_type sdp_type;
drivers/gpu/drm/msm/dp/dp_catalog.h line 112
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +10
-0+enum dp_catalog_audio_header_type sdp_header; +u32 data; + +void (*init)(struct dp_catalog_audio *audio); +void (*enable)(struct dp_catalog_audio *audio); +void (*config_acr)(struct dp_catalog_audio *audio); +void (*config_sdp)(struct dp_catalog_audio *audio); +void (*set_header)(struct dp_catalog_audio *audio); +void (*get_header)(struct dp_catalog_audio *audio); +void (*safe_to_exit_level)(struct dp_catalog_audio *audio);
None of these are called? So get rid of this entire structure, the functions that aren't called, and the audio enums above.
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +6
-0+}; + +struct dp_catalog_panel { +u32 total; +u32 sync_start; +u32 width_blanking;
drivers/gpu/drm/msm/dp/dp_catalog.h line 128
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +10
-0+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;
All of this information is already available from drm core, so it can go.
drivers/gpu/drm/msm/dp/dp_catalog.h line 131
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +3
-0+ +int (*timing_cfg)(struct dp_catalog_panel *panel); +void (*tpg_config)(struct dp_catalog_panel *panel,bool enable);
As suggested elsewhere, these functions should just be called directly wherever applicable. So we can get rid of this struct.
drivers/gpu/drm/msm/dp/dp_catalog.h line 142
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +11
-0+}; + +struct dp_catalog { +struct dp_catalog_aux aux; +struct dp_catalog_ctrl ctrl; +struct dp_catalog_audio audio; +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);
As mentioned above, all of this should be removed. We can just call the functions directly.
Quoted 35 lines
drivers/gpu/drm/msm/dp/dp_catalog.h new file +2
-0+ +#endif /* _DP_CATALOG_H_ */ drivers/gpu/drm/msm/dp/dp_ctrl.c new file +27
-0@@ -0,0 +1,1475 @@ +/* +* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#define pr_fmt (fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/types.h> +#include <linux/completion.h> +#include <linux/delay.h> + +#include "dp_ctrl.h" + +#define DP_KHZ_TO_HZ 1000 + +#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) +#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) +
drivers/gpu/drm/msm/dp/dp_ctrl.c line 37
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+/* dp state ctrl */ +#define ST_TRAIN_PATTERN_1 BIT(0) +#define ST_TRAIN_PATTERN_2 BIT(1) +#define ST_TRAIN_PATTERN_3 BIT(2) +#define ST_TRAIN_PATTERN_4 BIT(3) +#define ST_SYMBOL_ERR_RATE_MEASUREMENT BIT(4) +#define ST_PRBS7 BIT(5) +#define ST_CUSTOM_80_BIT_PATTERN BIT(6) +#define ST_SEND_VIDEO BIT(7) +#define ST_PUSH_IDLE BIT(8)
I'd like to see these defined with DP_STATE_CTRL (and s/ST/DP_STATE_CTRL/).
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0+ +#define MR_LINK_TRAINING1 0x8 +#define MR_LINK_SYMBOL_ERM 0x80 +#define MR_LINK_PRBS7 0x100 +#define MR_LINK_CUSTOM80 0x200 + +struct dp_vc_tu_mapping_table { +u32 vic;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 55
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+u8 lanes; +u8 lrate;/* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */ +u8 bpp; +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;
Please check this struct for unused members, there are at least a couple.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 67
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +12
-0+}; + +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;
Once you remove struct dp_ctrl and call the functions directly, I suspect you can get rid of all of these.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 76
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +9
-0+ +struct completion idle_comp; +struct completion video_comp; + +bool orientation; +atomic_t aborted; + +u32 pixel_rate; +u32 vic;
'u32 vic' shows up in 3 places in this driver, but there is not one use of any vic :) Please remove from here and elsewhere.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 85
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +9
-0+}; + +enum notification_status { +NOTIFY_UNKNOWN , +NOTIFY_CONNECT , +NOTIFY_DISCONNECT , +NOTIFY_CONNECT_IRQ_HPD , +NOTIFY_DISCONNECT_IRQ_HPD , +};
Unused, please remove.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 97
Quoted 12 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +12
-0+ +static void dp_ctrl_idle_patterns_sent (struct dp_ctrl_private *ctrl) +{ +pr_debug ("idle_patterns_sent\n" ); +complete (&ctrl->idle_comp); +} + +static void dp_ctrl_video_ready (struct dp_ctrl_private *ctrl) +{ +pr_debug ("dp_video_ready\n" ); +complete (&ctrl->video_comp); +}
These functions don't provide value, please remove and just call complete() directly.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 108
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +11
-0+ +static void dp_ctrl_abort (struct dp_ctrl *dp_ctrl) +{ +struct dp_ctrl_private *ctrl; + +if (!dp_ctrl) { +pr_err ("Invalid input data\n" ); +return ; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
JFYI, this is sprinkled everywhere, would be a good candidate for an inline function. Since dp_ctrl can be removed, it's kind of a moot point now.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 115
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0+ +atomic_set (&ctrl->aborted,1 ); +} + +static void dp_ctrl_state_ctrl (struct dp_ctrl_private *ctrl,u32 state) +{ + ctrl->catalog->state_ctrl (ctrl->catalog, state);
No need to wrap this in a function
drivers/gpu/drm/msm/dp/dp_ctrl.c line 120
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +5
-0+} + +static void dp_ctrl_push_idle (struct dp_ctrl *dp_ctrl) +{ +int const idle_pattern_completion_timeout_ms =3 *HZ /100 ;
This should be #define'd outside of the functioninstead. Also, why the '_ms_' suffix? The units are in jiffies.
I think something like
#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000) /* 30 ms */
would be clearer.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 130
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+struct dp_ctrl_private *ctrl; + +if (!dp_ctrl) { +pr_err ("Invalid input data\n" ); +return ; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + +reinit_completion (&ctrl->idle_comp);
This function is called from a bunch of places, and idle_comp is also used in a bunch of places. Are you certain this is thread-safe if you have concurrent callers or users of idle_comp?
drivers/gpu/drm/msm/dp/dp_ctrl.c line 135
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +5
-0+dp_ctrl_state_ctrl (ctrl,ST_PUSH_IDLE ); + +if (!wait_for_completion_timeout (&ctrl->idle_comp, + idle_pattern_completion_timeout_ms)) +pr_warn ("PUSH_IDLE pattern timedout\n" );
Return an error?
drivers/gpu/drm/msm/dp/dp_ctrl.c line 145
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ +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; + + config |= (2 <<13 );/* Default-> LSCLK DIV: 1/4 LCLK */
#define value
drivers/gpu/drm/msm/dp/dp_ctrl.c line 146
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +1
-0+ config |= (0 <<11 );/* RGB */
This is a no-op, can be removed
drivers/gpu/drm/msm/dp/dp_ctrl.c line 155
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +9
-0+ +/* Scrambler reset enable */ +if (dpcd[DP_EDP_CONFIGURATION_CAP ] &DP_ALTERNATE_SCRAMBLER_RESET_CAP ) + config |= (1 <<10 ); + + tbd = ctrl->link->get_test_bits_depth (ctrl->link, + ctrl->panel->pinfo.bpp); + +if (tbd ==DP_TEST_BIT_DEPTH_UNKNOWN )
Should we print a debug message here?
drivers/gpu/drm/msm/dp/dp_ctrl.c line 161
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +6
-0+ tbd =DP_TEST_BIT_DEPTH_8 ; + + config |= tbd <<8 ; + +/* Num of Lanes */ + config |= ((ctrl->link->link_params.lane_count -1 ) <<4 );
These shift values should be #defined
drivers/gpu/drm/msm/dp/dp_ctrl.c line 164
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +3
-0+ +if (drm_dp_enhanced_frame_cap (dpcd)) + config |=0x40 ;
#define 0x40
drivers/gpu/drm/msm/dp/dp_ctrl.c line 168
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +4
-0+ + config |=0x04 ;/* progressive video */ + + config |=0x03 ;/* sycn clock & static Mvid */
And these, plus s/sycn/sync/
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0+ + ctrl->catalog->config_ctrl (ctrl->catalog, config); +} + +/** +* dp_ctrl_configure_source_params() - configures DP transmitter source params +* @ctrl: Display Port Driver data
drivers/gpu/drm/msm/dp/dp_ctrl.c line 185
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+* +* 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; + + ctrl->catalog->lane_mapping (ctrl->catalog); + ctrl->catalog->mainlink_ctrl (ctrl->catalog, true);
We go through ctrl->catalog->callback_hook to call a function that is specific to ctrl and only called in this file. It could easily just be a static function without having to go through 2 structs and a callback hook.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 192
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0+ +dp_ctrl_config_ctrl (ctrl); + + tb = ctrl->link->get_test_bits_depth (ctrl->link, + ctrl->panel->pinfo.bpp); + cc = ctrl->link->get_colorimetry_config (ctrl->link); + ctrl->catalog->config_misc (ctrl->catalog, cc, tb);
Same comments with these hooks, they're only called from this file. I'll stop harping on this, but could we please remove the layers of indirection and just embed and call functions as appropriate?
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +22
-0+ ctrl->panel->timing_cfg (ctrl->panel); +} + +static void dp_ctrl_get_extra_req_bytes (u64 result_valid, +int valid_bdary_link, +u64 value1,u64 value2, +bool *negative,u64 *result, +u64 compare) +{ + *negative = false; +if (result_valid >= compare) { +if (valid_bdary_link + >= compare) + *result = value1 + value2; +else { +if (value1 < value2) + *negative = true; + *result = (value1 >= value2) ? + (value1 - value2) : (value2 - value1); + } + }else { + if (valid_bdary_link
drivers/gpu/drm/msm/dp/dp_ctrl.c line 224
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ >= compare) { + if (value1 >= value2) + *negative = true; + *result = (value1 >= value2) ? + (value1 - value2) : (value2 - value1); + } else { + *result = value1 + value2; + *negative = true; + } + }
I think this can be simplified to the following, it's still super hard to follow, but I'm not sure if that can be helped.
bool result_bigger = result_valid >= compare;
bool valid_bdary_bigger = valid_bdary_link >= compare;
if (result_bigger && valid_bdary_bigger ||
!result_bigger && !valid_bdary_bigger) {
*negative = !valid_bdary_bigger;
return value1 + value2;
}
*negative = (result_bigger && !valid_bdary_bigger && value1 < value2) ||
(!result_bigger && valid_bdary_bigger && value1 >= value2);
return max(value1, value2) - min(value1, value2);I don't know. The more I stare at this the less convinced I become that it's better. So take it or leave it. At the very least you can collapse the
if (cond)
*negative = true;
to
*negative = cond;
and do the max(v,v) - min(v,v) trick to shave off some of the conditionals in the original.
drivers/gpu/drm/msm/dp/dp_ctrl.c line 231
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +7
-0+} + +static u64 roundup_u64 (u64 x,u64 y) +{ + x += (y -1 ); +return (div64_ul (x, y) * y); +}
Please replace all usage with DIV_ROUND_UP_ULL
drivers/gpu/drm/msm/dp/dp_ctrl.c line 239
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +8
-0+ +static u64 rounddown_u64 (u64 x,u64 y) +{ +u64 rem; + +div64_u64_rem (x, y, &rem); +return (x - rem); +}
Please replace all usage with DIV_ROUND_DOWN_ULL
Quoted 58 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +58
-0+ +static void dp_ctrl_calc_tu_parameters (struct dp_ctrl_private *ctrl, +struct dp_vc_tu_mapping_table *tu_table) +{ +u32 multiplier =1000000 ; +u64 pclk, lclk; +u8 bpp, ln_cnt; +int run_idx =0 ; +u32 lwidth, h_blank; +u32 fifo_empty =0 ; +u32 ratio_scale =1001 ; +u64 temp, ratio, original_ratio; +u64 temp2, reminder; +u64 temp3, temp4, result =0 ; + +u64 err = multiplier; +u64 n_err =0 , n_n_err =0 ; +bool n_err_neg, nn_err_neg; +u8 hblank_margin =16 ; + +u8 tu_size, tu_size_desired =0 , tu_size_minus1; +int valid_boundary_link; +u64 resulting_valid; +u64 total_valid; +u64 effective_valid; +u64 effective_valid_recorded; +int n_tus; +int n_tus_per_lane; +int paired_tus; +int remainder_tus; +int remainder_tus_upper, remainder_tus_lower; +int extra_bytes; +int filler_size; +int delay_start_link; +int boundary_moderation_en =0 ; +int upper_bdry_cnt =0 ; +int lower_bdry_cnt =0 ; +int i_upper_bdry_cnt =0 ; +int i_lower_bdry_cnt =0 ; +int valid_lower_boundary_link =0 ; +int even_distribution_bf =0 ; +int even_distribution_legacy =0 ; +int even_distribution =0 ; +int min_hblank =0 ; +int extra_pclk_cycles; +u8 extra_pclk_cycle_delay =4 ; +int extra_pclk_cycles_in_link_clk; +u64 ratio_by_tu; +u64 average_valid2; +u64 extra_buffer_margin; +int new_valid_boundary_link; + +u64 resulting_valid_tmp; +u64 ratio_by_tu_tmp; +int n_tus_tmp; +int extra_pclk_cycles_tmp; +int extra_pclk_cycles_in_lclk_tmp; +int extra_req_bytes_new_tmp;
drivers/gpu/drm/msm/dp/dp_ctrl.c line 307
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+int filler_size_tmp; +int lower_filler_size_tmp; +int delay_start_link_tmp; +int min_hblank_tmp =0 ; +bool extra_req_bytes_is_neg = false; +struct dp_panel_info *pinfo = &ctrl->panel->pinfo; + +u8 dp_brute_force =1 ; +u64 brute_force_threshold =10 ; +u64 diff_abs;
76 stack vars and ~450 lines must be a new record somewhere :)
I'm going to skip reviewing this function and let you split/simplify/reduce it. Please just make it more readable (comments, docs, helper functions, etc).
Quoted 402 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +402
-0+ + ln_cnt = ctrl->link->link_params.lane_count; + + bpp = pinfo->bpp; + lwidth = pinfo->h_active; + h_blank = pinfo->h_back_porch + pinfo->h_front_porch + + pinfo->h_sync_width; + pclk = pinfo->pixel_clk_khz *1000 ; + + boundary_moderation_en =0 ; + upper_bdry_cnt =0 ; + lower_bdry_cnt =0 ; + i_upper_bdry_cnt =0 ; + i_lower_bdry_cnt =0 ; + valid_lower_boundary_link =0 ; + even_distribution_bf =0 ; + even_distribution_legacy =0 ; + even_distribution =0 ; + min_hblank =0 ; + + lclk =drm_dp_bw_code_to_link_rate ( + ctrl->link->link_params.bw_code) *DP_KHZ_TO_HZ ; + +pr_debug ("pclk=%lld, active_width=%d, h_blank=%d\n" , + pclk, lwidth, h_blank); +pr_debug ("lclk = %lld, ln_cnt = %d\n" , lclk, ln_cnt); + ratio =div64_u64_rem (pclk * bpp * multiplier, +8 * ln_cnt * lclk, &reminder); + ratio =div64_u64 ((pclk * bpp * multiplier), (8 * ln_cnt * lclk)); + original_ratio = ratio; + + extra_buffer_margin =roundup_u64 (div64_u64 (extra_pclk_cycle_delay + * lclk * multiplier, pclk), multiplier); + extra_buffer_margin =div64_u64 (extra_buffer_margin, multiplier); + +/* To deal with cases where lines are not distributable */ +if (((lwidth % ln_cnt) !=0 ) && ratio < multiplier) { + ratio = ratio * ratio_scale; + ratio = ratio < (1000 * multiplier) + ? ratio : (1000 * multiplier); + } +pr_debug ("ratio = %lld\n" , ratio); + +for (tu_size =32 ; tu_size <=64 ; tu_size++) { + temp = ratio * tu_size; + temp2 = ((temp / multiplier) +1 ) * multiplier; + n_err =roundup_u64 (temp, multiplier) - temp; + +if (n_err < err) { + err = n_err; + tu_size_desired = tu_size; + } + } +pr_debug ("Info: tu_size_desired = %d\n" , tu_size_desired); + + tu_size_minus1 = tu_size_desired -1 ; + + valid_boundary_link =roundup_u64 (ratio * tu_size_desired, multiplier); + valid_boundary_link /= multiplier; + n_tus =rounddown ((lwidth * bpp * multiplier) + / (8 * valid_boundary_link), multiplier) / multiplier; + even_distribution_legacy = n_tus % ln_cnt ==0 ?1 :0 ; +pr_debug ("Info: n_symbol_per_tu=%d, number_of_tus=%d\n" , + valid_boundary_link, n_tus); + + extra_bytes =roundup_u64 ((n_tus +1 ) + * ((valid_boundary_link * multiplier) + - (original_ratio * tu_size_desired)), multiplier); + extra_bytes /= multiplier; + extra_pclk_cycles =roundup (extra_bytes *8 * multiplier / bpp, + multiplier); + extra_pclk_cycles /= multiplier; + extra_pclk_cycles_in_link_clk =roundup_u64 (div64_u64 (extra_pclk_cycles + * lclk * multiplier, pclk), multiplier); + extra_pclk_cycles_in_link_clk /= multiplier; + filler_size =roundup_u64 ((tu_size_desired - valid_boundary_link) + * multiplier, multiplier); + filler_size /= multiplier; + ratio_by_tu =div64_u64 (ratio * tu_size_desired, multiplier); + +pr_debug ("extra_pclk_cycles_in_link_clk=%d, extra_bytes=%d\n" , + extra_pclk_cycles_in_link_clk, extra_bytes); +pr_debug ("extra_pclk_cycles_in_link_clk=%d\n" , + extra_pclk_cycles_in_link_clk); +pr_debug ("filler_size=%d, extra_buffer_margin=%lld\n" , + filler_size, extra_buffer_margin); + + delay_start_link = ((extra_bytes > extra_pclk_cycles_in_link_clk) + ? extra_bytes + : extra_pclk_cycles_in_link_clk) + + filler_size + extra_buffer_margin; + resulting_valid = valid_boundary_link; +pr_debug ("Info: delay_start_link=%d, filler_size=%d\n" , + delay_start_link, filler_size); +pr_debug ("valid_boundary_link=%d ratio_by_tu=%lld\n" , + valid_boundary_link, ratio_by_tu); + + diff_abs = (resulting_valid >= ratio_by_tu) + ? (resulting_valid - ratio_by_tu) + : (ratio_by_tu - resulting_valid); + + if (err != 0 && ((diff_abs > brute_force_threshold)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 419
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +10
-0+ || (even_distribution_legacy == 0) + || (dp_brute_force == 1))) { + err = multiplier; +for (tu_size =32 ; tu_size <=64 ; tu_size++) { +for (i_upper_bdry_cnt =1 ; i_upper_bdry_cnt <=15 ; + i_upper_bdry_cnt++) { +for (i_lower_bdry_cnt =1 ; + i_lower_bdry_cnt <=15 ; + i_lower_bdry_cnt++) { + new_valid_boundary_link =
Again here, if you just call the function directly, you can avoid the callback. If you add function arguments, you can avoid having to store dp_tu/valid_boundary/ valid_boundary2 entirely.
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.
Break out the timeout into a #define
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
You're not checking the return value at the callsite.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
I don't think this needs to be a function, just move it all into dp_ctrl_update_vx_px.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
DP_TRAIN_MAX_SWING_REACHED
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
DP_TRAIN_MAX_PRE_EMPHASIS_REACHED
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
This is DP_TRAIN_PRE_EMPHASIS_SHIFT, but I'm guessing you aren't using the DP_TRAIN_PRE_EMPH_LEVEL_* values when you set p_level. So the right way to fix this is to use those #defines and get rid of this shift.
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.
You shouldn't assume 4 lanes here, use drm_dp_link->num_lanes
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
s/0x103/DP_TRAINING_LANE0_SET/ and s/4/drm_dp_link->num_lanes/
Also, this will return number of bytes transmitted, not (0 || -errno).
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Fortunately (or unfortunately), the return value isn't checked. So please check the return value.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Why 4?
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check the return value of this and alll drm_dp_dpcd_(read|write) calls.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Just return directly here. You can also just drop len and use ret (or drop ret and use len).
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
And return 0 directly here
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Here you're returning successful in the timeout case :( Once you convert the above to direct returns, this can become return -ETIMEDOUT;
I think you should also drop the number of retries drastically.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 13 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
#define that bit please
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.
the train_1 comment isn't needed.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Instead of unbounded, this should be:
for (tries = 0; tries < maximum_retries; tries++) {You'll need to s/break/return ret/ in the rest of the loop and move the timeout error to the bottom of the function
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.
Since DP_LINK_VOLTAGE_MAX == DP_LINK_VOLTAGE_LEVEL_2, you'll end up not retrying LEVEL_2 at all.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 55 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +55
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
DP_TRAINING_PATTERN_DISABLE
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
for (tries = 0; tries < maximum_retries; tries++)
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
DP_SET_ANSI_8B10B
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Drop the hand-rolled ctrl->panel->link_info and use drm_dp_link_probe to fill in drm_dp_link.
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.
print ret
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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 should be debug loglevel
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
print ret
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
debug loglevel
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Same comments re: wmb
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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 can fit on one line
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.
All of the "goto end"'s can be replaced with "return ret", then delete the end label.
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.
You should really protect sink_request with a lock, it's racy. I'm trying to catch the race conditions while I review, but I'd urge you to audit the driver for other places that need locking.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Instead of adding the label, just wrap the reset and train calls in an if (train) {} block.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
"we have to first _do_ a..."
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check return value please
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Instead of doing all of this work, just store pointers to the link and pixel clock when you parse the dt. That way you can just access them directly in dp_ctrl_enable_mainlink_clocks.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 25 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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 function isn't necesary (even less so when all of the catalog abstractions are gone).
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 63 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +63
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
For this, you should use the DP_DPCD_QUIRK_CONSTANT_N quirk and drm_dp_has_quirk() instead.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 27 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Return value should be checked
Below you have:
+ /* hw recommended delay before re-enabling clocks */
+ msleep(20);
Between the disable and enable, so you should probably have that here too?
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Do you really want to continue here? Seems like you could get into an infinite loop pretty easily in the -EINVAL case.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Are you guaranteed that this doesn't race with other idle_comp uses?
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
The do/while is a bit awkward, especially since it starts with a conditional block that can't possibly be true on the first iteration. How about:
for (tries = 0; tries < max_tries; tries++) {
ctrl->catalog->phy_lane_cfg(ctrl->catalog,
ctrl->orientation, ctrl->link->link_params.lane_count);
/*
* Disable and re-enable the mainlink clock since the
* link clock might have been adjusted as part of the
* link maintenance.
*/
ret = dp_ctrl_disable_mainlink_clocks(ctrl);
if (ret)
return ret;
ret = dp_ctrl_enable_mainlink_clocks(ctrl);
if (ret)
return ret;
dp_ctrl_configure_source_params(ctrl);
ctrl->catalog->config_msa(ctrl->catalog,
drm_dp_bw_code_to_link_rate(
ctrl->link->link_params.bw_code),
ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
reinit_completion(&ctrl->idle_comp);
ret = dp_ctrl_setup_main_link(ctrl, true);
if (ret != -EAGAIN)
return ret;
/* try with lower link rate */
dp_ctrl_link_rate_down_shift(ctrl);
ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
}
return -ETIMEDOUT;There's a lot of similarity between this code and dp_ctrl_on. If the code were shared, we wouldn't have the missing 20ms delay above. So can you please pull the common bits which [re-]initialize the link into a helper function that you call from both functions?
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.
It's nice that we return a value here, but it's never checked by our callers :(
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.
This and the "end" debug statements should be removed
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
s/related/ralated/
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Please propagate errors instead of swallowing them.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
success = pattern_requested == DP_LINK_QUAL_PATTERN_11_D10_2;
Same can be done below.
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.
I feel like you should return success (or a ret). As it is, this doesn't do much.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Downgrade to DEBUG level please
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check return value
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check return value
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 15 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
I think this function goes away with all of the catalog stuff removed.
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 amount is excessive, 5 times should suffice (unless you have data that suggests otherwise).
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Should this be a #define in drm_dp_helper?
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Why is this needed over is_connected? It seems like if you had proper locking around is_connected (which I think is necessary), you could just acquire the lock and try the training. If it fails b/c someone unplugged the cable, that's quite Ok.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 29 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Are you guaranteed that this doesn't race with other idle_comp uses (or other dp_ctrl_on callers)?
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check return code
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
Check return code
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_ctrl.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 comment here as in dp_ctrl_link_maintenance(), we should pull out the common code and put it in a helper.
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.
This is racy, sink_request could change between the check above and here.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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 remove
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
readl/wmb nit
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.
Check and propagate return value
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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 should return the isr instead of store it in ctrl->catalog->isr, since that could potentially be overwritten after this function acks the current interrupts.
(Also, it's only used in this function, so there's no need to store it). One you remove the catalog indirection, hopefully there will be a bunch of these cases that become clear.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_ctrl.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.
As mentioned above, just call the completions directly.
drivers/gpu/drm/msm/dp/dp_ctrl.c
Quoted 62 lines
drivers/gpu/drm/msm/dp/dp_ctrl.c new file +62
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Once again, these functions can be deleted. Just store the _necessary_ data in a central struct (with substructs as necessary) and call functions directly.
drivers/gpu/drm/msm/dp/dp_ctrl.h
Quoted 41 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +35
-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 catalog, these should just be functions to be called directly.
drivers/gpu/drm/msm/dp/dp_ctrl.h
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h 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.
This struct is not needed, function arguments work just as well.
drivers/gpu/drm/msm/dp/dp_debug.c
Quoted 387 lines
drivers/gpu/drm/msm/dp/dp_ctrl.h new file +5
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_debug.c new file +376
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
edid, hpd, and connected can all be deleted. They're provided by core.
AFAICT, you can also infer the information from dp_debug, so I think you can just drop this entire file.
drivers/gpu/drm/msm/dp/dp_debug.h
Quoted 216 lines
drivers/gpu/drm/msm/dp/dp_debug.c new file +131
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_debug.h new file +79
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Drop this too
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 214 lines
drivers/gpu/drm/msm/dp/dp_debug.h new file +2
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.c new file +206
-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 called from a few different threads with no locking. It seems like there's good opportunity for is_connected and notification_comp to get out of sync.
Additionally, is_connected is set to true before the function returns (and enable has been completed). So is that going to cause problems when we call detect/get_modes where is_connected == true and the hw is not up?
Perhaps I'm misreading this function, but it seems like the plan is to block until userspace has been notified and does a full modeset (ie: enable)? If that is the case, we usually don't want to have the hardware lit up until it's actually going to be used. In these cases, we'll wrap get_modes in enable/disable (with proper locking), and wait for modeset to leave it on.
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 686 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +686
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
These 2 functions are never used, and as such g_dp_display is never used. AFAICT, the callback hooks linked from g_dp_display also aren't called from anywhere else. So can you just dump these functions, the struct, and all of the unused callback hooks?
drivers/gpu/drm/msm/dp/dp_display.c
Quoted 47 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +47
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Where is this called?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 221 lines
drivers/gpu/drm/msm/dp/dp_display.c new file +38
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_display.h new file +55
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.c new file +116
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Just use the drm modes directly and delete these functions.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 159 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +159
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
I'm not convinced you need any of this. The only advantage a bridge gets you is to be involved in modeset. However the only thing you do in modeset is save the mode (which is only used in enable). So why not just use the mode from the crtc's state when encoder->enable is called?
That allows you to delete all of the bridge stuff here.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
This isn't called from anything?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 19 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
no need for dp_conn, just do
dp = to_dp_connector(conn)->dp_display;
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 9 lines
drivers/gpu/drm/msm/dp/dp_drm.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 is always true.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
detect() should never do work, please remove.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
Why?
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.
Once dp_conn is devm managed, you can just remove this function and set .destroy to drm_connector_cleanup
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
Where is this called?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +36
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
When you get rid of dp_display_mode, please use the stack for the new drm_display_mode
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
Why is only one mode returned?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_drm.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 also return -errno, you should check for that too.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 1 line
drivers/gpu/drm/msm/dp/dp_drm.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.
Why continue if you know you failed?
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 14 lines
drivers/gpu/drm/msm/dp/dp_drm.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 shouldn't overwrite these.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 4 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
This shouldn't be an error
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 86 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +86
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
I think the value of max_pclk_khz is racy, you'll probably want to audit its use.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 7 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
Please drop this.
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
So I guess I was wrong when I said none of the g_dp_display functions are being used. I'm still unsure where they're set, perhaps there's some missing code. At any rate, what's the benefit of sticking all of that work into an abstract callback hook when it only has one implementation and one callsite.
All of that code can move in here (and the same goes for the other callbacks (move the code where it's used).
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 24 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
Use devm_kzalloc (you've already got a memory leak if drm_connector_init fails below).
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 17 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
These lines don't extend to 80 chars
drivers/gpu/drm/msm/dp/dp_drm.c
Quoted 6 lines
drivers/gpu/drm/msm/dp/dp_drm.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.
These are already false by virtue of kzalloc
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 115 lines
drivers/gpu/drm/msm/dp/dp_drm.c new file +5
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_drm.h new file +52
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.c new file +46
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Where is this used?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 26 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
No need to have this just for one debug statement, just print the enum value with %d below.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 11 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Same here.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Where is this called from?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Please #define hardcoded values
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
All of the values in cap->port seem to be hardcoded, so why not just use the #define's directly where applicable?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Where is this called?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Only multi_func, hpd_high, and hpd_irq are used out of this struct. Can you cull the values down? hpd_irq is also only set to its hardcoded value, so just use that value directly where applicable.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
This function is also unused
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 44 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +44
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Just return -EINVAL and get rid of the error label and rc.
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.
If forced_disconnect is always !dp_usbpd->hpd_high, why not just use !dp_usbpd->hpd_high directly?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 5 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Do you need locking in this function/file?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 22 lines
drivers/gpu/drm/msm/dp/dp_extcon.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 (property.intval) ? 2 : 4;
and delete lanes
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 20 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Can fit on 1 line
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.
Can fit on 1 line, plus remove all () from this, they're not needed.
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.
This part is a bit confusing, you add a helper function to get the lanes, and interpret the USB_SS property to return 2 vs. 4, but then immediately convert that back into what the USB_SS property returns. Instead, remove the helper function and read USB_SS directly here.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
I feel like this can never be false anyways, but you're not using either of these members in the conditional block. So why not just call dp_extcon_connect unconditionally?
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.
Check return value
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_extcon.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 here.
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.
Check return value
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.
What's the benefit of using a dedicated workqueue instead of the system wq?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 8 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
This function can't fail, so it should return void. In fact, this really doesn't need to be a separate function, roll it into dp_extcon_register().
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 23 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Yikes, this doesn't look like an error!
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Why keep going and create the workqueue if we have no notifier? This should probably be a return.
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 ret?
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
Same here
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.
remove.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 10 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
remove.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 16 lines
drivers/gpu/drm/msm/dp/dp_extcon.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.
remove.
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.
remove.
drivers/gpu/drm/msm/dp/dp_extcon.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_extcon.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 label isn't useful, return directly where applicable.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 163 lines
drivers/gpu/drm/msm/dp/dp_extcon.c new file +16
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_extcon.h new file +111
-0Lines of this file are not shown. View the raw message.
drivers/gpu/drm/msm/dp/dp_link.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.
These should be in drm_dp_helper.h
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 329 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +329
-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, just print the value in the debug statement.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 34 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +34
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Same thing here, just remove this and print the enum value.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 3 lines
drivers/gpu/drm/msm/dp/dp_link.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.
pass-by-value doesn't need const same comment applies elsewhere, please sweep the code for other instances.
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.
If you're going to check len < 2, you should probably also check len > 2 to prevent overflow. At this point, len can really only be 2, so you can just remove it entirely as an argument.
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.
Same comment here rt bounds checking
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 31 lines
drivers/gpu/drm/msm/dp/dp_link.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.
Putting aside the uninformative names, these dp_link_parse_timing_params* can be combined into one pretty easily, like:
static int dp_link_read_u32(struct dp_link_private *link, unsigned int offset,
u32 *val, int num_bytes)
{
int i;
ssize_t ret;
__be32 tmp_val;
for (i = 0; num_bytes > 0; i += sizeof(*val)) {
int to_read = min(sizeof(tmp_val), num_bytes);
tmp_val = 0;
ret = drm_dp_dpcd_read(link->aux->drm_aux, offset + i, &tmp_val,
to_read);
if (rlen < 0) {
/* print error message here */
return rlen;
}
val[i] = be32_to_cpu(tmp_val);
num_bytes -= to_read;
}
return 0;
}If you need to strip off the first bit, do it from the caller.
I didn't compile or test this, so it might need tweaking, but you get the idea.
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.
ssize_t
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 2 lines
drivers/gpu/drm/msm/dp/dp_link.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.
Why do you need data and bp? I think you only need one.
drivers/gpu/drm/msm/dp/dp_link.c
Quoted 36 lines
drivers/gpu/drm/msm/dp/dp_link.c new file +36
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
This mask isolates one bit from data
4,294 lines not shown · raw message
Parts of this message are not shown here. View the raw message.