drm/msm/dsi: Dual DSI and 8x96 PHY/PLL support
cover drm/msm/dsi: Dual DSI and 8x96 PHY/PLL support
This set adds 8x96 PHY/PLL with Dual DSI mode supported too.
Dual DSI on 8x96 requires the DSI host/manager drivers to propagate some usecase info to the PHY/PLL drivers. Hai Li had worked on some patches in the past to implement this.
Tested on 8996 MTP Dual DSI panel, and with a LeMaker panel (single DSI) on DB820c.
Archit Taneja (6):
drm/msm/dsi: Don't error if a DSI host doesn't have a device connected drm/msm/dsi: Add 8x96 info in dsi_cfg
drm/msm/dsi: Add a PHY op that initializes version specific stuff drm/msm/dsi: Reset both PHYs before clock operation for dual DSI drm/msm/dsi: Udpate generated headers for 14nm PHY and PLL drm/msm/dsi: Add PHY/PLL for 8x96
Hai Li (4):
drm/msm/dsi: Return more timings from PHY to host drm/msm/dsi: Pass down use case to PHY drm/msm/dsi: Move PHY operations out of host drm/msm/dsi: Add new method to calculate 14nm PHY timings
drivers/gpu/drm/msm/Kconfig | 7 + drivers/gpu/drm/msm/Makefile | 2 + drivers/gpu/drm/msm/dsi/dsi.h | 46 +- drivers/gpu/drm/msm/dsi/dsi.xml.h | 252 ++++++ drivers/gpu/drm/msm/dsi/dsi_cfg.c | 25 + drivers/gpu/drm/msm/dsi/dsi_cfg.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 95 +- drivers/gpu/drm/msm/dsi/dsi_manager.c | 195 +++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 238 ++++- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 20 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 168 ++++ drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 5 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 6 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 5 +- drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 12 + drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 11 + drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c | 1067 +++++++++++++++++++++++ 17 files changed, 1985 insertions(+), 170 deletions(-) create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/10 drm/msm/dsi: Don't error if a DSI host doesn't have a device connected
The driver returns an error if a DSI DT node is populated, but no device is connected to it or if the data-lane map isn't present. Ideally, such a DSI node shouldn't be probed at all (i.e, its status should be set to "disabled in DT"), but there isn't any harm in registering the DSI device even if it doesn't have a bridge/panel connected to it.
--- drivers/gpu/drm/msm/dsi/dsi_host.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +5 -5
@@ -1559,8 +1559,9 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, prop =of_find_property (ep,"data-lanes" , &len);if (!prop) { -dev_dbg (dev,"failed to find data lane mapping\n" ); -return -EINVAL ; +dev_dbg (dev, +"failed to find data lane mapping, using default\n" ); +return 0 ; } num_lanes = len /sizeof (u32);
@@ -1617,7 +1618,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)struct device *dev = &msm_host->pdev->dev;struct device_node *np = dev->of_node;struct device_node *endpoint, *device_node; -int ret; +int ret =0 ;/* * Get the endpoint of the output port of the DSI host. In our case,
@@ -1641,8 +1642,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)/* Get panel node from the output port's endpoint data */ device_node =of_graph_get_remote_port_parent (endpoint);if (!device_node) { -dev_err (dev,"%s: no valid device\n" , __func__); - ret = -ENODEV ; +dev_dbg (dev,"%s: no valid device\n" , __func__); goto err; }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/10 drm/msm/dsi: Add 8x96 info in dsi_cfg
In reply to Archit TanejaAdd 8x96 DSI data in dsi_cfg. The downstream kernel's dsi_host driver enables core_mmss_clk. We're seeing some branch clock warnings on 8x96 when enabling this. There doesn't seem to be any negative effect with not enabling this clock, so use it once we figure out why we get the warnings.
--- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 25 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dsi/dsi_cfg.h | 1 + 2 files changed, 26 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_cfg.c +25 -0
@@ -94,6 +94,30 @@ .num_dsi = 2, }; +/* +* TODO: core_mmss_clk fails to enable for some reason, but things work fine +* without it too. Figure out why it doesn't enable and uncomment below +*/ +static const char *const dsi_8996_bus_clk_names[] = { +"mdp_core_clk" ,"iface_clk" ,"bus_clk" ,/* "core_mmss_clk", */ +}; + +static const struct msm_dsi_config msm8996_dsi_cfg = { + .io_offset =DSI_6G_REG_SHIFT , + .reg_cfg = { + .num =2 , + .regs = { + {"vdda" ,18160 ,1 },/* 1.25 V */ + {"vcca" ,17000 ,32 },/* 0.925 V */ + {"vddio" ,100000 ,100 },/* 1.8 V */ + }, + }, + .bus_clk_names = dsi_8996_bus_clk_names, + .num_bus_clks =ARRAY_SIZE (dsi_8996_bus_clk_names), + .io_start = {0x994000 ,0x996000 }, + .num_dsi =2 , +}; +static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { {MSM_DSI_VER_MAJOR_V2 ,MSM_DSI_V2_VER_MINOR_8064 , &apq8064_dsi_cfg}, {MSM_DSI_VER_MAJOR_6G ,MSM_DSI_6G_VER_MINOR_V1_0 ,
@@ -106,6 +130,7 @@ &msm8974_apq8084_dsi_cfg}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_3, &msm8994_dsi_cfg}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_3_1, &msm8916_dsi_cfg}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_4_1, &msm8996_dsi_cfg}, };const struct msm_dsi_cfg_handler *msm_dsi_cfg_get (u32 major,u32 minor)
drivers/gpu/drm/msm/dsi/dsi_cfg.h +1 -0
@@ -24,6 +24,7 @@#define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000#define MSM_DSI_6G_VER_MINOR_V1_3 0x10030000#define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001 +#define MSM_DSI_6G_VER_MINOR_V1_4_1 0x10040001#define MSM_DSI_V2_VER_MINOR_8064 0x0
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/10 drm/msm/dsi: Add a PHY op that initializes version specific stuff
In reply to Archit TanejaCreate an init() op for dsi_phy which sets up things specific to a given DSI PHY.
The dsi_phy driver probe expects every DSI version to get a "dsi_phy_regulator" mmio base. This isn't the case for 8x96. Creating an init() op will allow us to accommodate such differences.
--- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 33 ++++++++++++++++++------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 2 ++ drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 1 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 2 ++ drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 1 + 5 files changed, 30 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +24 -9
@@ -295,6 +295,24 @@ static int dsi_phy_get_id(struct msm_dsi_phy *phy)return -EINVAL ; } +int msm_dsi_phy_init_common (struct msm_dsi_phy *phy) +{ +struct platform_device *pdev = phy->pdev; +int ret =0 ; + + phy->reg_base =msm_ioremap (pdev,"dsi_phy_regulator" , +"DSI_PHY_REG" ); +if (IS_ERR (phy->reg_base)) { +dev_err (&pdev->dev,"%s: failed to map phy regulator base\n" , + __func__); + ret = -ENOMEM ; + goto fail; + } + +fail: +return ret; +} +static int dsi_phy_driver_probe (struct platform_device *pdev) {struct msm_dsi_phy *phy;
@@ -331,15 +349,6 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail; } - phy->reg_base =msm_ioremap (pdev,"dsi_phy_regulator" , -"DSI_PHY_REG" ); -if (IS_ERR (phy->reg_base)) { -dev_err (dev,"%s: failed to map phy regulator base\n" , - __func__); - ret = -ENOMEM ; - goto fail; - } - ret =dsi_phy_regulator_init (phy);if (ret) {dev_err (dev,"%s: failed to init regulator\n" , __func__);
@@ -353,6 +362,12 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail; } +if (phy->cfg->ops.init) { + ret = phy->cfg->ops.init (phy); +if (ret) + goto fail; + } +/* PLL init will call into clk_register which requires * register access, so we need to enable power and ahb clock. */
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +2 -0
@@ -22,6 +22,7 @@#define dsi_phy_write (offset, data) msm_writel((data), (offset))struct msm_dsi_phy_ops { +int (*init) (struct msm_dsi_phy *phy);int (*enable)(struct msm_dsi_phy *phy,int src_pll_id,const unsigned long bit_rate,const unsigned long esc_rate);void (*disable)(struct msm_dsi_phy *phy);
@@ -87,6 +88,7 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing, const unsigned long bit_rate, const unsigned long esc_rate);void msm_dsi_phy_set_src_pll (struct msm_dsi_phy *phy,int pll_id,u32 reg,u32 bit_mask); +int msm_dsi_phy_init_common (struct msm_dsi_phy *phy);#endif /* __DSI_PHY_H__ */
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +1 -0
@@ -145,6 +145,7 @@ static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) .ops = { .enable = dsi_20nm_phy_enable, .disable = dsi_20nm_phy_disable, + .init = msm_dsi_phy_init_common, }, .io_start = { 0xfd998300, 0xfd9a0300 }, .num_dsi_phy = 2,
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +2 -0
@@ -144,6 +144,7 @@ static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, + .init = msm_dsi_phy_init_common, }, .io_start = { 0xfd922b00, 0xfd923100 }, .num_dsi_phy = 2,
@@ -161,6 +162,7 @@ static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, + .init = msm_dsi_phy_init_common, }, .io_start = { 0x1a98500 }, .num_dsi_phy = 1,
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +1 -0
@@ -191,6 +191,7 @@ static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, + .init = msm_dsi_phy_init_common, }, .io_start = { 0x4700300, 0x5800300 }, .num_dsi_phy = 2,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 4/10 drm/msm/dsi: Return more timings from PHY to host
In reply to Archit TanejaFrom: Hai Li <[email protected]>
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.
--- drivers/gpu/drm/msm/dsi/dsi.h | 13 ++++++++++--- drivers/gpu/drm/msm/dsi/dsi_host.c | 20 +++++++++++++------- drivers/gpu/drm/msm/dsi/dsi_manager.c | 4 ++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 29 ++++++++++++++--------------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 2 ++ 5 files changed, 41 insertions(+), 27 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +10 -3
@@ -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 msm_dsi {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_modeset_init(struct mipi_dsi_host *host,/* 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__ */
drivers/gpu/drm/msm/dsi/dsi_host.c +13 -7
@@ -756,7 +756,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( }static void dsi_ctrl_config (struct msm_dsi_host *msm_host,bool enable, -u32 clk_pre,u32 clk_post) +struct msm_dsi_phy_shared_timings *phy_shared_timings) {u32 flags = msm_host->mode_flags;enum mipi_dsi_pixel_format mipi_fmt = msm_host->format;
@@ -819,10 +819,16 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, data |=DSI_TRIG_CTRL_BLOCK_DMA_WITHIN_FRAME ;dsi_write (msm_host,REG_DSI_TRIG_CTRL , data); - data =DSI_CLKOUT_TIMING_CTRL_T_CLK_POST (clk_post) | -DSI_CLKOUT_TIMING_CTRL_T_CLK_PRE (clk_pre); + data =DSI_CLKOUT_TIMING_CTRL_T_CLK_POST (phy_shared_timings->clk_post) | +DSI_CLKOUT_TIMING_CTRL_T_CLK_PRE (phy_shared_timings->clk_pre);dsi_write (msm_host,REG_DSI_CLKOUT_TIMING_CTRL , data); +if ((cfg_hnd->major ==MSM_DSI_VER_MAJOR_6G ) && + (cfg_hnd->minor >MSM_DSI_6G_VER_MINOR_V1_0 ) && + phy_shared_timings->clk_pre_inc_by_2) +dsi_write (msm_host,REG_DSI_T_CLK_PRE_EXTEND , +DSI_T_CLK_PRE_EXTEND_INC_BY_2_BYTECLK ); + data =0 ;if (!(flags &MIPI_DSI_MODE_EOT_PACKET )) data |=DSI_EOT_PACKET_CTRL_TX_EOT_APPEND ;
@@ -2170,7 +2176,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)int msm_dsi_host_power_on (struct mipi_dsi_host *host) {struct msm_dsi_host *msm_host =to_msm_dsi_host (host); -u32 clk_pre =0 , clk_post =0 ; +struct msm_dsi_phy_shared_timings phy_shared_timings;int ret =0 ;mutex_lock (&msm_host->dev_mutex);
@@ -2204,7 +2210,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host) ret =msm_dsi_manager_phy_enable (msm_host->id, msm_host->byte_clk_rate *8 , msm_host->esc_clk_rate, - &clk_pre, &clk_post); + &phy_shared_timings);dsi_bus_clk_disable (msm_host);if (ret) {pr_err ("%s: failed to enable phy, %d\n" , __func__, ret);
@@ -2226,7 +2232,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)dsi_timing_setup (msm_host);dsi_sw_reset (msm_host); -dsi_ctrl_config (msm_host, true, clk_pre, clk_post); +dsi_ctrl_config (msm_host, true, &phy_shared_timings);if (msm_host->disp_en_gpio)gpiod_set_value (msm_host->disp_en_gpio,1 );
@@ -2255,7 +2261,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) goto unlock_ret; } -dsi_ctrl_config (msm_host, false,0 ,0 ); +dsi_ctrl_config (msm_host, false,NULL );if (msm_host->disp_en_gpio)gpiod_set_value (msm_host->disp_en_gpio,0 );
drivers/gpu/drm/msm/dsi/dsi_manager.c +2 -2
@@ -651,7 +651,7 @@ void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)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_timings) {struct msm_dsi *msm_dsi =dsi_mgr_get_dsi (id);struct msm_dsi_phy *phy = msm_dsi->phy;
@@ -679,7 +679,7 @@ int msm_dsi_manager_phy_enable(int id, } msm_dsi->phy_enabled = true; -msm_dsi_phy_get_clk_pre_post (phy, clk_pre, clk_post); +msm_dsi_phy_get_shared_timings (phy, shared_timings);return 0 ; }
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +14 -15
@@ -115,8 +115,8 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing, temp = ((timing->hs_exit >>1 ) +1 ) *2 * ui; temp =60 * coeff +52 * ui -24 * ui - temp; tmin =S_DIV_ROUND_UP (temp,8 * ui) -1 ; - timing->clk_post =linear_inter (tmax, tmin, pcnt2,0 , false); - + timing->shared_timings.clk_post =linear_inter (tmax, tmin, pcnt2,0 , + false); tmax =63 ; temp = ((timing->clk_prepare >>1 ) +1 ) *2 * ui; temp += ((timing->clk_zero >>1 ) +1 ) *2 * ui;
@@ -124,17 +124,21 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing, tmin =S_DIV_ROUND_UP (temp,8 * ui) -1 ;if (tmin > tmax) { temp =linear_inter (2 * tmax, tmin, pcnt2,0 , false); - timing->clk_pre = temp >>1 ; + timing->shared_timings.clk_pre = temp >>1 ; + timing->shared_timings.clk_pre_inc_by_2 = true; }else { - timing->clk_pre =linear_inter (tmax, tmin, pcnt2,0 , false); + timing->shared_timings.clk_pre = +linear_inter (tmax, tmin, pcnt2,0 , false); + timing->shared_timings.clk_pre_inc_by_2 = false; } timing->ta_go =3 ; timing->ta_sure =0 ; timing->ta_get =4 ; -DBG ("PHY timings: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d" , - timing->clk_pre, timing->clk_post, timing->clk_zero, +DBG ("PHY timings: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d" , + timing->shared_timings.clk_pre, timing->shared_timings.clk_post, + timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero, timing->clk_trail, timing->clk_prepare, timing->hs_exit, timing->hs_zero, timing->hs_prepare, timing->hs_trail, timing->hs_rqst);
@@ -460,16 +464,11 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)dsi_phy_regulator_disable (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_timings) { -if (!phy) -return ; - -if (clk_pre) - *clk_pre = phy->timing.clk_pre; -if (clk_post) - *clk_post = phy->timing.clk_post; +memcpy (shared_timings, &phy->timing.shared_timings, +sizeof (*shared_timings)); }struct msm_dsi_pll *msm_dsi_phy_get_pll (struct msm_dsi_phy *phy)
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +2 -0
@@ -62,6 +62,8 @@ struct msm_dsi_dphy_timing {u32 ta_go;u32 ta_sure;u32 ta_get; + +struct msm_dsi_phy_shared_timings shared_timings; };struct msm_dsi_phy {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 5/10 drm/msm/dsi: Pass down use case to PHY
In reply to Archit TanejaFrom: Hai Li <[email protected]>
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.
--- drivers/gpu/drm/msm/dsi/dsi.h | 8 +++++++ drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 ++++++++++++----------------------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 30 +++++++++++++++++++++++- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 + 4 files changed, 52 insertions(+), 30 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +8 -0
@@ -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 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,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__ */
drivers/gpu/drm/msm/dsi/dsi_manager.c +14 -29
100 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +29 -1
@@ -451,7 +451,24 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,return ret; } -return 0 ; +/* +* Resetting DSI PHY silently changes its PLL registers to reset status, +* which will confuse clock driver and result in wrong output rate of +* link clocks. Restore PLL status if its PLL is being used as clock +* source. +*/ +if (phy->usecase !=MSM_DSI_PHY_SLAVE ) { + ret =msm_dsi_pll_restore_state (phy->pll); +if (ret) { +pr_err ("%s: failed to restore pll state\n" , __func__); +if (phy->cfg->ops.disable) + phy->cfg->ops.disable (phy); +dsi_phy_regulator_disable (phy); +return ret; + } + } + +return ret; }void msm_dsi_phy_disable (struct msm_dsi_phy *phy)
@@ -459,6 +476,10 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)if (!phy || !phy->cfg->ops.disable)return ; +/* Save PLL status if it is a clock source */ +if (phy->usecase !=MSM_DSI_PHY_SLAVE ) +msm_dsi_pll_save_state (phy->pll); + phy->cfg->ops.disable (phy);dsi_phy_regulator_disable (phy);
@@ -479,3 +500,10 @@ struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)return phy->pll; } +void msm_dsi_phy_set_usecase (struct msm_dsi_phy *phy, +enum msm_dsi_phy_usecase uc) +{ +if (phy) + phy->usecase = uc; +} +
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +1 -0
@@ -78,6 +78,7 @@ struct msm_dsi_phy {struct msm_dsi_dphy_timing timing;const struct msm_dsi_phy_cfg *cfg; +enum msm_dsi_phy_usecase usecase;bool regulator_ldo_mode;struct msm_dsi_pll *pll;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 6/10 drm/msm/dsi: Reset both PHYs before clock operation for dual DSI
In reply to Archit TanejaIn 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 <[email protected]>. Fixed up by Archit Taneja <[email protected]>]
--- drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 25 +++++++++++++------------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 15 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
@@ -166,6 +166,7 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,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);
drivers/gpu/drm/msm/dsi/dsi_host.c +13 -12
@@ -691,17 +691,6 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)return 0 ; } -static void dsi_phy_sw_reset (struct msm_dsi_host *msm_host) -{ -DBG ("" ); -dsi_write (msm_host,REG_DSI_PHY_RESET ,DSI_PHY_RESET_RESET ); -/* Make sure fully reset */ -wmb (); -udelay (1000 ); -dsi_write (msm_host,REG_DSI_PHY_RESET ,0 ); -udelay (100 ); -} -static void dsi_intr_ctrl (struct msm_dsi_host *msm_host,u32 mask,int enable) {u32 intr;
@@ -2126,6 +2115,19 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,return ret; } +void msm_dsi_host_reset_phy (struct mipi_dsi_host *host) +{ +struct msm_dsi_host *msm_host =to_msm_dsi_host (host); + +DBG ("" ); +dsi_write (msm_host,REG_DSI_PHY_RESET ,DSI_PHY_RESET_RESET ); +/* Make sure fully reset */ +wmb (); +udelay (1000 ); +dsi_write (msm_host,REG_DSI_PHY_RESET ,0 ); +udelay (100 ); +} +int msm_dsi_host_enable (struct mipi_dsi_host *host) {struct msm_dsi_host *msm_host =to_msm_dsi_host (host);
@@ -2206,7 +2208,6 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host) goto fail_disable_reg; } -dsi_phy_sw_reset (msm_host); ret = msm_dsi_manager_phy_enable(msm_host->id, msm_host->byte_clk_rate * 8, msm_host->esc_clk_rate,
drivers/gpu/drm/msm/dsi/dsi_manager.c +29 -3
@@ -660,13 +660,39 @@ int msm_dsi_manager_phy_enable(int id, struct msm_dsi_phy_shared_timings *shared_timings) {struct msm_dsi *msm_dsi =dsi_mgr_get_dsi (id); +struct msm_dsi *mdsi =dsi_mgr_get_dsi (DSI_CLOCK_MASTER ); +struct msm_dsi *sdsi =dsi_mgr_get_dsi (DSI_CLOCK_SLAVE );struct msm_dsi_phy *phy = msm_dsi->phy;int src_pll_id =IS_DUAL_DSI () ?DSI_CLOCK_MASTER : id;int ret; - ret =msm_dsi_phy_enable (phy, src_pll_id, bit_rate, esc_rate); -if (ret) -return ret; +/* In case of dual DSI, some registers in PHY1 have been programmed +* during PLL0 clock's set_rate. The PHY1 reset called by host1 here +* will silently reset those PHY1 registers. Therefore we need to reset +* and enable both PHYs before any PLL clock operation. +*/ +if (IS_DUAL_DSI () && mdsi && sdsi) { +if (!mdsi->phy_enabled && !sdsi->phy_enabled) { +msm_dsi_host_reset_phy (mdsi->host); +msm_dsi_host_reset_phy (sdsi->host); + ret =msm_dsi_phy_enable (mdsi->phy, src_pll_id, + bit_rate, esc_rate); +if (ret) +return ret; + ret =msm_dsi_phy_enable (sdsi->phy, src_pll_id, + bit_rate, esc_rate); +if (ret) { +msm_dsi_phy_disable (mdsi->phy); +return ret; + } + } + }else { +msm_dsi_host_reset_phy (msm_dsi->host); + ret =msm_dsi_phy_enable (msm_dsi->phy, src_pll_id, bit_rate, + esc_rate); +if (ret) +return ret; + } msm_dsi->phy_enabled = true;msm_dsi_phy_get_shared_timings (phy, shared_timings);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 7/10 drm/msm/dsi: Move PHY operations out of host
In reply to Archit TanejaFrom: Hai Li <[email protected]>
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.
--- drivers/gpu/drm/msm/dsi/dsi.h | 18 ++- drivers/gpu/drm/msm/dsi/dsi_host.c | 46 +++--- drivers/gpu/drm/msm/dsi/dsi_manager.c | 178 ++++++++++++++---------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 39 ++++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 4 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 4 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 4 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 4 +- 8 files changed, 172 insertions(+), 125 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +12 -6
@@ -28,6 +28,7 @@#define DSI_MAX 2struct 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 msm_dsi {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 @@ struct drm_panel *msm_dsi_host_get_panel(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);
drivers/gpu/drm/msm/dsi/dsi_host.c +19 -27
96 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/dsi_manager.c +105 -73
228 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +28 -11
@@ -54,8 +54,10 @@ static void dsi_dphy_timing_calc_clk_zero(struct msm_dsi_dphy_timing *timing, }int msm_dsi_dphy_timing_calc (struct msm_dsi_dphy_timing *timing, -const unsigned long bit_rate,const unsigned long esc_rate) +struct msm_dsi_phy_clk_request *clk_req) { +const unsigned long bit_rate = clk_req->bitclk_rate; +const unsigned long esc_rate = clk_req->escclk_rate;s32 ui, lpx;s32 tmax, tmin;s32 pcnt0 =10 ;
@@ -429,7 +431,7 @@ void __exit 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) {struct device *dev = &phy->pdev->dev;int ret;
@@ -437,18 +439,24 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,if (!phy || !phy->cfg->ops.enable)return -EINVAL ; + ret =dsi_phy_enable_resource (phy); +if (ret) { +dev_err (dev,"%s: resource enable failed, %d\n" , + __func__, ret); + goto res_en_fail; + } + ret =dsi_phy_regulator_enable (phy);if (ret) {dev_err (dev,"%s: regulator enable failed, %d\n" , __func__, ret); -return ret; + goto reg_en_fail; } - ret = phy->cfg->ops.enable (phy, src_pll_id, bit_rate, esc_rate); + ret = phy->cfg->ops.enable (phy, src_pll_id, clk_req);if (ret) {dev_err (dev,"%s: phy enable failed, %d\n" , __func__, ret); -dsi_phy_regulator_disable (phy); -return ret; + goto phy_en_fail; }/*
@@ -460,14 +468,22 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,if (phy->usecase !=MSM_DSI_PHY_SLAVE ) { ret =msm_dsi_pll_restore_state (phy->pll);if (ret) { -pr_err ("%s: failed to restore pll state\n" , __func__); -if (phy->cfg->ops.disable) - phy->cfg->ops.disable (phy); -dsi_phy_regulator_disable (phy); -return ret; +dev_err (dev,"%s: failed to restore pll state, %d\n" , + __func__, ret); + goto pll_restor_fail; } } +return 0 ; + +pll_restor_fail: +if (phy->cfg->ops.disable) + phy->cfg->ops.disable (phy); +phy_en_fail: +dsi_phy_regulator_disable (phy); +reg_en_fail: +dsi_phy_disable_resource (phy); +res_en_fail:return ret; }
@@ -483,6 +499,7 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy) phy->cfg->ops.disable (phy);dsi_phy_regulator_disable (phy); +dsi_phy_disable_resource (phy); } void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +2 -2
@@ -24,7 +24,7 @@struct msm_dsi_phy_ops {int (*init) (struct msm_dsi_phy *phy);int (*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 (*disable)(struct msm_dsi_phy *phy); };
@@ -88,7 +88,7 @@ struct msm_dsi_phy {* PHY internal functions */ int msm_dsi_dphy_timing_calc (struct msm_dsi_dphy_timing *timing, -const unsigned long bit_rate,const unsigned long esc_rate); +struct msm_dsi_phy_clk_request *clk_req);void msm_dsi_phy_set_src_pll (struct msm_dsi_phy *phy,int pll_id,u32 reg,u32 bit_mask);int msm_dsi_phy_init_common (struct msm_dsi_phy *phy);
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +2 -2
@@ -72,7 +72,7 @@ static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) }static int dsi_20nm_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) {struct msm_dsi_dphy_timing *timing = &phy->timing;int i;
@@ -81,7 +81,7 @@ static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,DBG ("" ); -if (msm_dsi_dphy_timing_calc (timing, bit_rate, esc_rate)) { +if (msm_dsi_dphy_timing_calc (timing, clk_req)) {dev_err (&phy->pdev->dev,"%s: D-PHY timing calculation failed\n" , __func__);return -EINVAL ;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +2 -2
@@ -67,7 +67,7 @@ static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) }static int dsi_28nm_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) {struct msm_dsi_dphy_timing *timing = &phy->timing;int i;
@@ -75,7 +75,7 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,DBG ("" ); -if (msm_dsi_dphy_timing_calc (timing, bit_rate, esc_rate)) { +if (msm_dsi_dphy_timing_calc (timing, clk_req)) {dev_err (&phy->pdev->dev,"%s: D-PHY timing calculation failed\n" , __func__);return -EINVAL ;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +2 -2
@@ -124,14 +124,14 @@ static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy) }static int dsi_28nm_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) {struct msm_dsi_dphy_timing *timing = &phy->timing;void __iomem *base = phy->base;DBG ("" ); -if (msm_dsi_dphy_timing_calc (timing, bit_rate, esc_rate)) { +if (msm_dsi_dphy_timing_calc (timing, clk_req)) {dev_err (&phy->pdev->dev,"%s: D-PHY timing calculation failed\n" , __func__);return -EINVAL ;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 8/10 drm/msm/dsi: Udpate generated headers for 14nm PHY and PLL
In reply to Archit Taneja--- drivers/gpu/drm/msm/dsi/dsi.xml.h | 252 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+)
drivers/gpu/drm/msm/dsi/dsi.xml.h +252 -0
@@ -1304,5 +1304,257 @@ static inline uint32_t DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)#define REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG 0x00000018 +#define REG_DSI_14nm_PHY_CMN_REVISION_ID0 0x00000000 + +#define REG_DSI_14nm_PHY_CMN_REVISION_ID1 0x00000004 + +#define REG_DSI_14nm_PHY_CMN_REVISION_ID2 0x00000008 + +#define REG_DSI_14nm_PHY_CMN_REVISION_ID3 0x0000000c + +#define REG_DSI_14nm_PHY_CMN_CLK_CFG0 0x00000010 +#define DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK 0x0000000f +#define DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0 (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__SHIFT) & DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK; +} +#define DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK 0x000000f0 +#define DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT 4 +static inline uint32_t DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4 (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT) & DSI_14nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK; +} + +#define REG_DSI_14nm_PHY_CMN_CLK_CFG1 0x00000014 +#define DSI_14nm_PHY_CMN_CLK_CFG1_DSICLK_SEL 0x00000001 + +#define REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL 0x00000018 +#define DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL 0x00000004 + +#define REG_DSI_14nm_PHY_CMN_CTRL_0 0x0000001c + +#define REG_DSI_14nm_PHY_CMN_CTRL_1 0x00000020 + +#define REG_DSI_14nm_PHY_CMN_HW_TRIGGER 0x00000024 + +#define REG_DSI_14nm_PHY_CMN_SW_CFG0 0x00000028 + +#define REG_DSI_14nm_PHY_CMN_SW_CFG1 0x0000002c + +#define REG_DSI_14nm_PHY_CMN_SW_CFG2 0x00000030 + +#define REG_DSI_14nm_PHY_CMN_HW_CFG0 0x00000034 + +#define REG_DSI_14nm_PHY_CMN_HW_CFG1 0x00000038 + +#define REG_DSI_14nm_PHY_CMN_HW_CFG2 0x0000003c + +#define REG_DSI_14nm_PHY_CMN_HW_CFG3 0x00000040 + +#define REG_DSI_14nm_PHY_CMN_HW_CFG4 0x00000044 + +#define REG_DSI_14nm_PHY_CMN_PLL_CNTRL 0x00000048 +#define DSI_14nm_PHY_CMN_PLL_CNTRL_PLL_START 0x00000001 + +#define REG_DSI_14nm_PHY_CMN_LDO_CNTRL 0x0000004c +#define DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL__MASK 0x0000003f +#define DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL__SHIFT) & DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN (uint32_t i0) {return 0x00000000 +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_CFG0 (uint32_t i0) {return 0x00000000 +0x80 *i0; } +#define DSI_14nm_PHY_LN_CFG0_PREPARE_DLY__MASK 0x000000c0 +#define DSI_14nm_PHY_LN_CFG0_PREPARE_DLY__SHIFT 6 +static inline uint32_t DSI_14nm_PHY_LN_CFG0_PREPARE_DLY (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_CFG0_PREPARE_DLY__SHIFT) & DSI_14nm_PHY_LN_CFG0_PREPARE_DLY__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_CFG1 (uint32_t i0) {return 0x00000004 +0x80 *i0; } +#define DSI_14nm_PHY_LN_CFG1_HALFBYTECLK_EN 0x00000001 + +static inline uint32_t REG_DSI_14nm_PHY_LN_CFG2 (uint32_t i0) {return 0x00000008 +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_CFG3 (uint32_t i0) {return 0x0000000c +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_TEST_DATAPATH (uint32_t i0) {return 0x00000010 +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_TEST_STR (uint32_t i0) {return 0x00000014 +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_4 (uint32_t i0) {return 0x00000018 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_5 (uint32_t i0) {return 0x0000001c +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_6 (uint32_t i0) {return 0x00000020 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_7 (uint32_t i0) {return 0x00000024 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_8 (uint32_t i0) {return 0x00000028 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_9 (uint32_t i0) {return 0x0000002c +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO__MASK 0x00000007 +#define DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO__MASK; +} +#define DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE__MASK 0x00000070 +#define DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE__SHIFT 4 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_10 (uint32_t i0) {return 0x00000030 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET__MASK 0x00000007 +#define DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_TIMING_CTRL_11 (uint32_t i0) {return 0x00000034 +0x80 *i0; } +#define DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD__MASK 0x000000ff +#define DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD__SHIFT 0 +static inline uint32_t DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD (uint32_t val) +{ +return ((val) << DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD__SHIFT) & DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD__MASK; +} + +static inline uint32_t REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_0 (uint32_t i0) {return 0x00000038 +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_1 (uint32_t i0) {return 0x0000003c +0x80 *i0; } + +static inline uint32_t REG_DSI_14nm_PHY_LN_VREG_CNTRL (uint32_t i0) {return 0x00000064 +0x80 *i0; } + +#define REG_DSI_14nm_PHY_PLL_IE_TRIM 0x00000000 + +#define REG_DSI_14nm_PHY_PLL_IP_TRIM 0x00000004 + +#define REG_DSI_14nm_PHY_PLL_IPTAT_TRIM 0x00000010 + +#define REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN 0x0000001c + +#define REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET 0x00000028 + +#define REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL 0x0000002c + +#define REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2 0x00000030 + +#define REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL3 0x00000034 + +#define REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL4 0x00000038 + +#define REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5 0x0000003c + +#define REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1 0x00000040 + +#define REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2 0x00000044 + +#define REG_DSI_14nm_PHY_PLL_KVCO_COUNT1 0x00000048 + +#define REG_DSI_14nm_PHY_PLL_KVCO_COUNT2 0x0000004c + +#define REG_DSI_14nm_PHY_PLL_VREF_CFG1 0x0000005c + +#define REG_DSI_14nm_PHY_PLL_KVCO_CODE 0x00000058 + +#define REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1 0x0000006c + +#define REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2 0x00000070 + +#define REG_DSI_14nm_PHY_PLL_VCO_COUNT1 0x00000074 + +#define REG_DSI_14nm_PHY_PLL_VCO_COUNT2 0x00000078 + +#define REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1 0x0000007c + +#define REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2 0x00000080 + +#define REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3 0x00000084 + +#define REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN 0x00000088 + +#define REG_DSI_14nm_PHY_PLL_PLL_VCO_TUNE 0x0000008c + +#define REG_DSI_14nm_PHY_PLL_DEC_START 0x00000090 + +#define REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER 0x00000094 + +#define REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1 0x00000098 + +#define REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2 0x0000009c + +#define REG_DSI_14nm_PHY_PLL_SSC_PER1 0x000000a0 + +#define REG_DSI_14nm_PHY_PLL_SSC_PER2 0x000000a4 + +#define REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1 0x000000a8 + +#define REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2 0x000000ac + +#define REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1 0x000000b4 + +#define REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2 0x000000b8 + +#define REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3 0x000000bc + +#define REG_DSI_14nm_PHY_PLL_TXCLK_EN 0x000000c0 + +#define REG_DSI_14nm_PHY_PLL_PLL_CRCTRL 0x000000c4 + +#define REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS 0x000000cc + +#define REG_DSI_14nm_PHY_PLL_PLL_MISC1 0x000000e8 + +#define REG_DSI_14nm_PHY_PLL_CP_SET_CUR 0x000000f0 + +#define REG_DSI_14nm_PHY_PLL_PLL_ICPMSET 0x000000f4 + +#define REG_DSI_14nm_PHY_PLL_PLL_ICPCSET 0x000000f8 + +#define REG_DSI_14nm_PHY_PLL_PLL_ICP_SET 0x000000fc + +#define REG_DSI_14nm_PHY_PLL_PLL_LPF1 0x00000100 + +#define REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV 0x00000104 + +#define REG_DSI_14nm_PHY_PLL_PLL_BANDGAP 0x00000108 +#endif /* DSI_XML */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 9/10 drm/msm/dsi: Add new method to calculate 14nm PHY timings
In reply to Archit TanejaFrom: Hai Li <[email protected]>
The 14nm DSI PHY on 8x96 (called PHY v2 downstream) requires a different set of calculations for computing D-PHY timing params. Create a timing_calc_v2 func for the newer v2 PHYs.
--- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 117 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 11 +++- 2 files changed, 127 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +117 -0
@@ -148,6 +148,123 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,return 0 ; } +int msm_dsi_dphy_timing_calc_v2 (struct msm_dsi_dphy_timing *timing, +struct msm_dsi_phy_clk_request *clk_req) +{ +const unsigned long bit_rate = clk_req->bitclk_rate; +const unsigned long esc_rate = clk_req->escclk_rate; +s32 ui, ui_x8, lpx; +s32 tmax, tmin; +s32 pcnt0 =50 ; +s32 pcnt1 =50 ; +s32 pcnt2 =10 ; +s32 pcnt3 =30 ; +s32 pcnt4 =10 ; +s32 pcnt5 =2 ; +s32 coeff =1000 ;/* Precision, should avoid overflow */ +s32 hb_en, hb_en_ckln, pd_ckln, pd; +s32 val, val_ckln; +s32 temp; + +if (!bit_rate || !esc_rate) +return -EINVAL ; + + timing->hs_halfbyte_en =0 ; + hb_en =0 ; + timing->hs_halfbyte_en_ckln =0 ; + hb_en_ckln =0 ; + timing->hs_prep_dly_ckln = (bit_rate >100000000 ) ?0 :3 ; + pd_ckln = timing->hs_prep_dly_ckln; + timing->hs_prep_dly = (bit_rate >120000000 ) ?0 :1 ; + pd = timing->hs_prep_dly; + + val = (hb_en <<2 ) + (pd <<1 ); + val_ckln = (hb_en_ckln <<2 ) + (pd_ckln <<1 ); + + ui =mult_frac (NSEC_PER_MSEC , coeff, bit_rate /1000 ); + ui_x8 = ui <<3 ; + lpx =mult_frac (NSEC_PER_MSEC , coeff, esc_rate /1000 ); + + temp =S_DIV_ROUND_UP (38 * coeff - val_ckln * ui, ui_x8); + tmin =max_t (s32, temp,0 ); + temp = (95 * coeff - val_ckln * ui) / ui_x8; + tmax =max_t (s32, temp,0 ); + timing->clk_prepare =linear_inter (tmax, tmin, pcnt0,0 , false); + + temp =300 * coeff - ((timing->clk_prepare <<3 ) + val_ckln) * ui; + tmin =S_DIV_ROUND_UP (temp -11 * ui, ui_x8) -3 ; + tmax = (tmin >255 ) ?511 :255 ; + timing->clk_zero =linear_inter (tmax, tmin, pcnt5,0 , false); + + tmin =DIV_ROUND_UP (60 * coeff +3 * ui, ui_x8); + temp =105 * coeff +12 * ui -20 * coeff; + tmax = (temp +3 * ui) / ui_x8; + timing->clk_trail =linear_inter (tmax, tmin, pcnt3,0 , false); + + temp =S_DIV_ROUND_UP (40 * coeff +4 * ui - val * ui, ui_x8); + tmin =max_t (s32, temp,0 ); + temp = (85 * coeff +6 * ui - val * ui) / ui_x8; + tmax =max_t (s32, temp,0 ); + timing->hs_prepare =linear_inter (tmax, tmin, pcnt1,0 , false); + + temp =145 * coeff +10 * ui - ((timing->hs_prepare <<3 ) + val) * ui; + tmin =S_DIV_ROUND_UP (temp -11 * ui, ui_x8) -3 ; + tmax =255 ; + timing->hs_zero =linear_inter (tmax, tmin, pcnt4,0 , false); + + tmin =DIV_ROUND_UP (60 * coeff +4 * ui +3 * ui, ui_x8); + temp =105 * coeff +12 * ui -20 * coeff; + tmax = (temp +3 * ui) / ui_x8; + timing->hs_trail =linear_inter (tmax, tmin, pcnt3,0 , false); + + temp =50 * coeff + ((hb_en <<2 ) -8 ) * ui; + timing->hs_rqst =S_DIV_ROUND_UP (temp, ui_x8); + + tmin =DIV_ROUND_UP (100 * coeff, ui_x8) -1 ; + tmax =255 ; + timing->hs_exit =linear_inter (tmax, tmin, pcnt2,0 , false); + + temp =50 * coeff + ((hb_en_ckln <<2 ) -8 ) * ui; + timing->hs_rqst_ckln =S_DIV_ROUND_UP (temp, ui_x8); + + temp =60 * coeff +52 * ui -43 * ui; + tmin =DIV_ROUND_UP (temp, ui_x8) -1 ; + tmax =63 ; + timing->shared_timings.clk_post = +linear_inter (tmax, tmin, pcnt2,0 , false); + + temp =8 * ui + ((timing->clk_prepare <<3 ) + val_ckln) * ui; + temp += (((timing->clk_zero +3 ) <<3 ) +11 - (pd_ckln <<1 )) * ui; + temp += hb_en_ckln ? (((timing->hs_rqst_ckln <<3 ) +4 ) * ui) : + (((timing->hs_rqst_ckln <<3 ) +8 ) * ui); + tmin =S_DIV_ROUND_UP (temp, ui_x8) -1 ; + tmax =63 ; +if (tmin > tmax) { + temp =linear_inter (tmax <<1 , tmin, pcnt2,0 , false); + timing->shared_timings.clk_pre = temp >>1 ; + timing->shared_timings.clk_pre_inc_by_2 =1 ; + }else { + timing->shared_timings.clk_pre = +linear_inter (tmax, tmin, pcnt2,0 , false); + timing->shared_timings.clk_pre_inc_by_2 =0 ; + } + + timing->ta_go =3 ; + timing->ta_sure =0 ; + timing->ta_get =4 ; + +DBG ("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d" , + timing->shared_timings.clk_pre, timing->shared_timings.clk_post, + timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero, + timing->clk_trail, timing->clk_prepare, timing->hs_exit, + timing->hs_zero, timing->hs_prepare, timing->hs_trail, + timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en, + timing->hs_halfbyte_en_ckln, timing->hs_prep_dly, + timing->hs_prep_dly_ckln); + +return 0 ; +} +void msm_dsi_phy_set_src_pll (struct msm_dsi_phy *phy,int pll_id,u32 reg,u32 bit_mask) {
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +10 -1
@@ -64,6 +64,13 @@ struct msm_dsi_dphy_timing {u32 ta_get;struct msm_dsi_phy_shared_timings shared_timings; + +/* For PHY v2 only */ +u32 hs_rqst_ckln; +u32 hs_prep_dly; +u32 hs_prep_dly_ckln; +u8 hs_halfbyte_en; +u8 hs_halfbyte_en_ckln; };struct msm_dsi_phy {
@@ -88,7 +95,9 @@ struct msm_dsi_phy {* PHY internal functions */ int msm_dsi_dphy_timing_calc (struct msm_dsi_dphy_timing *timing, -struct msm_dsi_phy_clk_request *clk_req); +struct msm_dsi_phy_clk_request *clk_req); +int msm_dsi_dphy_timing_calc_v2 (struct msm_dsi_dphy_timing *timing, +struct msm_dsi_phy_clk_request *clk_req);void msm_dsi_phy_set_src_pll (struct msm_dsi_phy *phy,int pll_id,u32 reg,u32 bit_mask);int msm_dsi_phy_init_common (struct msm_dsi_phy *phy);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 10/10 drm/msm/dsi: Add PHY/PLL for 8x96
In reply to Archit TanejaExtend 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.
--- drivers/gpu/drm/msm/Kconfig | 7 + drivers/gpu/drm/msm/Makefile | 2 + drivers/gpu/drm/msm/dsi/dsi.h | 8 + drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 2 + drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 2 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 168 +++++ drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 12 + drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 11 + drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c | 1067 ++++++++++++++++++++++++++++ 9 files changed, 1279 insertions(+) create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
drivers/gpu/drm/msm/Kconfig +7 -0
@@ -71,3 +71,10 @@ config DRM_MSM_DSI_28NM_8960_PHY help Choose this option if the 28nm DSI PHY 8960 variant is used on the platform. + +config DRM_MSM_DSI_14NM_PHY + bool "Enable DSI 14NM PHY driver in MSM DRM (used in MSM8996)" + depends on DRM_MSM_DSI + default y + help + Choose this option if DSI PHY on 8996 is used on the platform.
drivers/gpu/drm/msm/Makefile +2 -0
@@ -74,11 +74,13 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o +obj-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y) msm-y += dsi/pll/dsi_pll.o msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o +obj-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o endif obj-$(CONFIG_DRM_MSM) += msm.o
drivers/gpu/drm/msm/dsi/dsi.h +8 -0
@@ -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 */
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +2 -0
@@ -391,6 +391,8 @@ static void dsi_phy_disable_resource(struct msm_dsi_phy *phy) { .compatible = "qcom,dsi-phy-28nm-8960", .data = &dsi_phy_28nm_8960_cfgs }, #endif + { .compatible = "qcom,dsi-phy-14nm", + .data = &dsi_phy_14nm_cfgs }, {} };
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +2 -0
@@ -47,6 +47,7 @@ struct msm_dsi_phy_cfg {extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;struct msm_dsi_dphy_timing {u32 clk_pre;
@@ -77,6 +78,7 @@ struct msm_dsi_phy {struct platform_device *pdev;void __iomem *base;void __iomem *reg_base; +void __iomem *lane_base;int id;struct clk *ahb_clk;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c new file +168 -0
168 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +12 -0
@@ -140,6 +140,15 @@ int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll)return 0 ; } +int msm_dsi_pll_set_usecase (struct msm_dsi_pll *pll, +enum msm_dsi_phy_usecase uc) +{ +if (pll->set_usecase) +return pll->set_usecase (pll, uc); + +return 0 ; +} +struct msm_dsi_pll *msm_dsi_pll_init (struct platform_device *pdev,enum msm_dsi_phy_type type,int id) {
@@ -154,6 +163,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,case MSM_DSI_PHY_28NM_8960 : pll =msm_dsi_pll_28nm_8960_init (pdev, id);break ; +case MSM_DSI_PHY_14NM : + pll =msm_dsi_pll_14nm_init (pdev, id); +break ;default : pll =ERR_PTR (-ENXIO );break ;
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +11 -0
@@ -41,6 +41,8 @@ struct msm_dsi_pll {void (*destroy)(struct msm_dsi_pll *pll);void (*save_state)(struct msm_dsi_pll *pll);int (*restore_state)(struct msm_dsi_pll *pll); +int (*set_usecase)(struct msm_dsi_pll *pll, +enum msm_dsi_phy_usecase uc); };#define hw_clk_to_pll (x) container_of(x, struct msm_dsi_pll, clk_hw)
@@ -104,5 +106,14 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init( }#endif +#ifdef CONFIG_DRM_MSM_DSI_14NM_PHY +struct msm_dsi_pll *msm_dsi_pll_14nm_init (struct platform_device *pdev,int id); +#else +static inline struct msm_dsi_pll * +msm_dsi_pll_14nm_init (struct platform_device *pdev,int id) +{ +return ERR_PTR (-ENODEV ); +} +#endif #endif /* __DSI_PLL_H__ */
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +1067 -0
1,067 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 10/10] drm/msm/dsi: Add PHY/PLL for 8x96
Quoted 20 lines · Archit Taneja
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +20
-0+ +static struct clk *pll_14nm_postdiv_register (struct dsi_pll_14nm *pll_14nm, +const char *name, +const char *parent_name, +unsigned long flags, +u8 shift) +{ +struct dsi_pll_14nm_postdiv *pll_postdiv; +struct device *dev = &pll_14nm->pdev->dev; +struct clk_init_data postdiv_init = { + .parent_names = (const char *[]) { parent_name }, + .num_parents =1 , + .name = name, + .flags = flags, + .ops = &clk_ops_dsi_pll_14nm_postdiv, + }; + + pll_postdiv =devm_kzalloc (dev,sizeof (*pll_postdiv),GFP_KERNEL ); +if (!pll_postdiv) +return ERR_PTR (-ENOMEM );
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c line 935
Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +10
-0+ + pll_postdiv->pll = pll_14nm; + pll_postdiv->shift = shift; +/* both N1 and N2 postdividers are 4 bits wide */ + pll_postdiv->width =4 ; +/* range of each divider is from 1 to 15 */ + pll_postdiv->flags =CLK_DIVIDER_ONE_BASED ; + pll_postdiv->hw.init = &postdiv_init; + +return clk_register (dev, &pll_postdiv->hw);
Can you use clk_hw_register() and the variants instead? Same for the clk_provider calls in this patch.
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 10/10] drm/msm/dsi: Add PHY/PLL for 8x96
Quoted 26 lines · Stephen Boyd
Quoted 25 lines · Archit Taneja
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +25
-0+ +static struct clk *pll_14nm_postdiv_register (struct dsi_pll_14nm *pll_14nm, +const char *name, +const char *parent_name, +unsigned long flags, +u8 shift) +{ +struct dsi_pll_14nm_postdiv *pll_postdiv; +struct device *dev = &pll_14nm->pdev->dev; +struct clk_init_data postdiv_init = { + .parent_names = (const char *[]) { parent_name }, + .num_parents =1 , + .name = name, + .flags = flags, + .ops = &clk_ops_dsi_pll_14nm_postdiv, + }; + + pll_postdiv =devm_kzalloc (dev,sizeof (*pll_postdiv),GFP_KERNEL ); +if (!pll_postdiv) +return ERR_PTR (-ENOMEM ); + + pll_postdiv->pll = pll_14nm; + pll_postdiv->shift = shift; +/* both N1 and N2 postdividers are 4 bits wide */ + pll_postdiv->width =4 ;
Quoted 8 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c line 935
Quoted 5 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +5
-0+/* range of each divider is from 1 to 15 */ + pll_postdiv->flags =CLK_DIVIDER_ONE_BASED ; + pll_postdiv->hw.init = &postdiv_init; + +return clk_register (dev, &pll_postdiv->hw);Can you use
clk_hw_register()and the variants instead? Same for theclk_providercalls in this patch.
Will do.
Thanks,
Archit
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 10/10 drm/msm/dsi: Add PHY/PLL for 8x96
In reply to Archit TanejaExtend 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.
---
v2:
- Use clk_hw_register/add_hw_provider funcs instead
- Fix some build warnings on arm32 caught by kbuild
drivers/gpu/drm/msm/Kconfig | 7 + drivers/gpu/drm/msm/Makefile | 2 + drivers/gpu/drm/msm/dsi/dsi.h | 8 + drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 4 + drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 2 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 169 +++++ drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 12 + drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 11 + drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c | 1104 ++++++++++++++++++++++++++++ 9 files changed, 1319 insertions(+) create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
drivers/gpu/drm/msm/Kconfig +7 -0
@@ -72,3 +72,10 @@ config DRM_MSM_DSI_28NM_8960_PHY help Choose this option if the 28nm DSI PHY 8960 variant is used on the platform. + +config DRM_MSM_DSI_14NM_PHY + bool "Enable DSI 14nm PHY driver in MSM DRM (used by MSM8996/APQ8096)" + depends on DRM_MSM_DSI + default y + help + Choose this option if DSI PHY on 8996 is used on the platform.
drivers/gpu/drm/msm/Makefile +2 -0
@@ -76,11 +76,13 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o +msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y) msm-y += dsi/pll/dsi_pll.o msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o +msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o endif obj-$(CONFIG_DRM_MSM) += msm.o
drivers/gpu/drm/msm/dsi/dsi.h +8 -0
@@ -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 */
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +4 -0
@@ -391,6 +391,10 @@ static const struct of_device_id dsi_phy_dt_match[] = { { .compatible = "qcom,dsi-phy-28nm-8960", .data = &dsi_phy_28nm_8960_cfgs }, #endif +#ifdef CONFIG_DRM_MSM_DSI_14NM_PHY + { .compatible = "qcom,dsi-phy-14nm", + .data = &dsi_phy_14nm_cfgs }, +#endif {} };
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +2 -0
@@ -47,6 +47,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;struct msm_dsi_dphy_timing {u32 clk_pre;
@@ -77,6 +78,7 @@ struct msm_dsi_phy {struct platform_device *pdev;void __iomem *base;void __iomem *reg_base; +void __iomem *lane_base;int id;struct clk *ahb_clk;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c new file +169 -0
169 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +12 -0
@@ -140,6 +140,15 @@ int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll)return 0 ; } +int msm_dsi_pll_set_usecase (struct msm_dsi_pll *pll, +enum msm_dsi_phy_usecase uc) +{ +if (pll->set_usecase) +return pll->set_usecase (pll, uc); + +return 0 ; +} +struct msm_dsi_pll *msm_dsi_pll_init (struct platform_device *pdev,enum msm_dsi_phy_type type,int id) {
@@ -154,6 +163,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,case MSM_DSI_PHY_28NM_8960 : pll =msm_dsi_pll_28nm_8960_init (pdev, id);break ; +case MSM_DSI_PHY_14NM : + pll =msm_dsi_pll_14nm_init (pdev, id); +break ;default : pll =ERR_PTR (-ENXIO );break ;
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +11 -0
@@ -41,6 +41,8 @@ struct msm_dsi_pll {void (*destroy)(struct msm_dsi_pll *pll);void (*save_state)(struct msm_dsi_pll *pll);int (*restore_state)(struct msm_dsi_pll *pll); +int (*set_usecase)(struct msm_dsi_pll *pll, +enum msm_dsi_phy_usecase uc); };#define hw_clk_to_pll (x) container_of(x, struct msm_dsi_pll, clk_hw)
@@ -104,5 +106,14 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init( }#endif +#ifdef CONFIG_DRM_MSM_DSI_14NM_PHY +struct msm_dsi_pll *msm_dsi_pll_14nm_init (struct platform_device *pdev,int id); +#else +static inline struct msm_dsi_pll * +msm_dsi_pll_14nm_init (struct platform_device *pdev,int id) +{ +return ERR_PTR (-ENODEV ); +} +#endif #endif /* __DSI_PLL_H__ */
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c new file +1104 -0
1,104 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation