From 97e00119534bf3c9f47c4eae0b7dd982ef2de92b Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 16 Jan 2017 09:42:03 +0530 Subject: drm/msm: Construct only one encoder for DSI We currently create 2 encoders for DSI interfaces, one for command mode and other for video mode operation. This isn't needed as we can't really use both the encoders at the same time. It also makes connecting bridges harder. Switch to creating a single encoder. For now, we assume that the encoder is configured only in video mode. Later, the same encoder would be usable in both modes. Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 03f115f532c2..ddcda8cec9a7 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -73,8 +73,8 @@ struct msm_dsi { struct device *phy_dev; bool phy_enabled; - /* the encoders we are hooked to (outside of dsi block) */ - struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]; + /* the encoder we are hooked to (outside of dsi block) */ + struct drm_encoder *encoder; int id; }; -- cgit From 9c9f6f8d472cc9e11f2c0b370685ce78ab7eb2fa Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 5 Dec 2016 15:24:53 +0530 Subject: drm/msm: Set encoder's mode of operation using a kms func The mdp5 kms driver currently sets up multiple encoders per interface (INTF), one for each kind of mode of operation it supports. We create 2 drm_encoders for DSI, one for Video Mode and the other for Command Mode operation. The reason behind this approach could have been that we aren't aware of the DSI device's mode of operation when we create the encoders. This makes things a bit complicated, since these encoders have to be further attached to the same DSI bridge. The easier way out is to create a single encoder, and make the DSI driver set its mode of operation when we know what the DSI device's mode flags are. Start with providing a way to set the mdp5_intf_mode using a kms func that sets the encoder's mode of operation. When constructing a DSI encoder, we set the mode of operation to Video Mode as default. When the DSI device is attached to the host, we probe the DSI mode flags and set the corresponding mode of operation. Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index ddcda8cec9a7..81971b3caf3b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -90,6 +90,7 @@ int msm_dsi_manager_phy_enable(int id, void msm_dsi_manager_phy_disable(int id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); +void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); -- cgit From dceac340155b66b6c97cb802b03d4778dd82e9be Mon Sep 17 00:00:00 2001 From: Hai Li Date: Thu, 15 Sep 2016 14:34:49 +0530 Subject: drm/msm/dsi: Return more timings from PHY to host The DSI host is required to configure more timings calculated in PHY. By introducing a shared structure, this change allows more timing information passed from PHY to host. Signed-off-by: Hai Li Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 81971b3caf3b..f5e4ccfc902d 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -27,6 +27,8 @@ #define DSI_1 1 #define DSI_MAX 2 +struct msm_dsi_phy_shared_timings; + enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_HPM, MSM_DSI_PHY_28NM_LP, @@ -86,7 +88,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id); struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); int msm_dsi_manager_phy_enable(int id, const unsigned long bit_rate, const unsigned long esc_rate, - u32 *clk_pre, u32 *clk_post); + struct msm_dsi_phy_shared_timings *shared_timing); void msm_dsi_manager_phy_disable(int id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); @@ -165,13 +167,18 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi); /* dsi phy */ struct msm_dsi_phy; +struct msm_dsi_phy_shared_timings { + u32 clk_post; + u32 clk_pre; + bool clk_pre_inc_by_2; +}; void msm_dsi_phy_driver_register(void); void msm_dsi_phy_driver_unregister(void); int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate); void msm_dsi_phy_disable(struct msm_dsi_phy *phy); -void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, - u32 *clk_pre, u32 *clk_post); +void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy, + struct msm_dsi_phy_shared_timings *shared_timing); struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); #endif /* __DSI_CONNECTOR_H__ */ -- cgit From 57bf433893370c069a0c34842f35a3bb8aa130fc Mon Sep 17 00:00:00 2001 From: Hai Li Date: Thu, 15 Sep 2016 14:44:22 +0530 Subject: drm/msm/dsi: Pass down use case to PHY For some new types of DSI PHY, more settings depend on use cases controlled by DSI manager. This change allows DSI manager to setup PHY with a use case. Signed-off-by: Hai Li Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index f5e4ccfc902d..d516fe296b78 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -37,6 +37,12 @@ enum msm_dsi_phy_type { MSM_DSI_PHY_MAX }; +enum msm_dsi_phy_usecase { + MSM_DSI_PHY_STANDALONE, + MSM_DSI_PHY_MASTER, + MSM_DSI_PHY_SLAVE, +}; + #define DSI_DEV_REGULATOR_MAX 8 #define DSI_BUS_CLK_MAX 4 @@ -180,6 +186,8 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy, struct msm_dsi_phy_shared_timings *shared_timing); struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); +void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy, + enum msm_dsi_phy_usecase uc); #endif /* __DSI_CONNECTOR_H__ */ -- cgit From 34d9545b9f769c6553e31a6820c9cb51f5e93099 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 29 Jul 2015 12:14:12 -0400 Subject: drm/msm/dsi: Reset both PHYs before clock operation for dual DSI In case of dual DSI, some registers in PHY1 have been programmed during PLL0 clock's set_rate. The PHY1 reset called by host1 later will silently reset those PHY1 registers. This change is to reset and enable both PHYs before any PLL clock operation. [Originally worked on by Hai Li . Fixed up by Archit Taneja ] Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index d516fe296b78..9407a682d045 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -166,6 +166,7 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); void msm_dsi_host_unregister(struct mipi_dsi_host *host); int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_pll *src_pll); +void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); -- cgit From b62aa70a98c5401ada63657eee7c88da70bdbb27 Mon Sep 17 00:00:00 2001 From: Hai Li Date: Sat, 7 Jan 2017 14:24:38 +0530 Subject: drm/msm/dsi: Move PHY operations out of host Since DSI PHY has been a separate platform device, it should not depend on the resources in host to be functional. This change is to trigger PHY operations in manager, instead of host, so that host and PHY can be completely separated. Signed-off-by: Hai Li Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 9407a682d045..9465996d0869 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -28,6 +28,7 @@ #define DSI_MAX 2 struct msm_dsi_phy_shared_timings; +struct msm_dsi_phy_clk_request; enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_HPM, @@ -92,10 +93,6 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); struct drm_connector *msm_dsi_manager_connector_init(u8 id); struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); -int msm_dsi_manager_phy_enable(int id, - const unsigned long bit_rate, const unsigned long esc_rate, - struct msm_dsi_phy_shared_timings *shared_timing); -void msm_dsi_manager_phy_disable(int id); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags); @@ -155,7 +152,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, u32 len); int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); -int msm_dsi_host_power_on(struct mipi_dsi_host *host); +int msm_dsi_host_power_on(struct mipi_dsi_host *host, + struct msm_dsi_phy_shared_timings *phy_shared_timings); int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, struct drm_display_mode *mode); @@ -167,6 +165,8 @@ void msm_dsi_host_unregister(struct mipi_dsi_host *host); int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_pll *src_pll); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); +void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, + struct msm_dsi_phy_clk_request *clk_req); void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); @@ -179,10 +179,16 @@ struct msm_dsi_phy_shared_timings { u32 clk_pre; bool clk_pre_inc_by_2; }; + +struct msm_dsi_phy_clk_request { + unsigned long bitclk_rate; + unsigned long escclk_rate; +}; + void msm_dsi_phy_driver_register(void); void msm_dsi_phy_driver_unregister(void); int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, - const unsigned long bit_rate, const unsigned long esc_rate); + struct msm_dsi_phy_clk_request *clk_req); void msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy, struct msm_dsi_phy_shared_timings *shared_timing); -- cgit From f079f6d999cbf857f899732de680f2b62f245b8c Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 3 Jan 2017 19:45:43 +0530 Subject: drm/msm/dsi: Add PHY/PLL for 8x96 Extend the DSI PHY/PLL drivers to support the DSI 14nm PHY/PLL found on 8x96. These are picked up from the downstream driver. The PHY part is similar to the other DSI PHYs. The PLL driver requires some trickery so that one DSI PLL can drive both the DSIs (i.e, dual DSI mode). In the case of dual DSI mode. One DSI instance becomes the clock master, and other the clock slave. The master PLL's output (Byte and Pixel clock) is fed to both the DSI hosts/PHYs. When the DSIs are configured in dual DSI mode, the PHY driver communicates to the PLL driver using msm_dsi_pll_set_usecase() which instance is the master and which one is the slave. When setting rate, the master PLL also configures some of the slave PLL/PHY registers which need to be identical to the master's for correct dual DSI behaviour. There are 2 PLL post dividers that should have ideally been modelled as generic clk_divider clocks, but require some customization for dual DSI. In particular, when the master PLL's post-diviers are set, the slave PLL's post-dividers need to be set too. The clk_ops for these use clk_divider's helper ops and flags internally to prevent redundant code. Cc: Stephen Boyd Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 9465996d0869..32369975d155 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -35,6 +35,7 @@ enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_LP, MSM_DSI_PHY_20NM, MSM_DSI_PHY_28NM_8960, + MSM_DSI_PHY_14NM, MSM_DSI_PHY_MAX }; @@ -117,6 +118,8 @@ int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, struct clk **byte_clk_provider, struct clk **pixel_clk_provider); void msm_dsi_pll_save_state(struct msm_dsi_pll *pll); int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll); +int msm_dsi_pll_set_usecase(struct msm_dsi_pll *pll, + enum msm_dsi_phy_usecase uc); #else static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, enum msm_dsi_phy_type type, int id) { @@ -137,6 +140,11 @@ static inline int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll) { return 0; } +static inline int msm_dsi_pll_set_usecase(struct msm_dsi_pll *pll, + enum msm_dsi_phy_usecase uc) +{ + return -ENODEV; +} #endif /* dsi host */ -- cgit