Skip to content

Commit b62aa70

Browse files
Hai Lirobclark
authored andcommitted
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 <[email protected]> Signed-off-by: Archit Taneja <[email protected]> Signed-off-by: Rob Clark <[email protected]>
1 parent 34d9545 commit b62aa70

File tree

8 files changed

+172
-125
lines changed

8 files changed

+172
-125
lines changed

drivers/gpu/drm/msm/dsi/dsi.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define DSI_MAX 2
2929

3030
struct msm_dsi_phy_shared_timings;
31+
struct msm_dsi_phy_clk_request;
3132

3233
enum msm_dsi_phy_type {
3334
MSM_DSI_PHY_28NM_HPM,
@@ -92,10 +93,6 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id);
9293
void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge);
9394
struct drm_connector *msm_dsi_manager_connector_init(u8 id);
9495
struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id);
95-
int msm_dsi_manager_phy_enable(int id,
96-
const unsigned long bit_rate, const unsigned long esc_rate,
97-
struct msm_dsi_phy_shared_timings *shared_timing);
98-
void msm_dsi_manager_phy_disable(int id);
9996
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
10097
bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
10198
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,
155152
u32 dma_base, u32 len);
156153
int msm_dsi_host_enable(struct mipi_dsi_host *host);
157154
int msm_dsi_host_disable(struct mipi_dsi_host *host);
158-
int msm_dsi_host_power_on(struct mipi_dsi_host *host);
155+
int msm_dsi_host_power_on(struct mipi_dsi_host *host,
156+
struct msm_dsi_phy_shared_timings *phy_shared_timings);
159157
int msm_dsi_host_power_off(struct mipi_dsi_host *host);
160158
int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
161159
struct drm_display_mode *mode);
@@ -167,6 +165,8 @@ void msm_dsi_host_unregister(struct mipi_dsi_host *host);
167165
int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
168166
struct msm_dsi_pll *src_pll);
169167
void msm_dsi_host_reset_phy(struct mipi_dsi_host *host);
168+
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
169+
struct msm_dsi_phy_clk_request *clk_req);
170170
void msm_dsi_host_destroy(struct mipi_dsi_host *host);
171171
int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
172172
struct drm_device *dev);
@@ -179,10 +179,16 @@ struct msm_dsi_phy_shared_timings {
179179
u32 clk_pre;
180180
bool clk_pre_inc_by_2;
181181
};
182+
183+
struct msm_dsi_phy_clk_request {
184+
unsigned long bitclk_rate;
185+
unsigned long escclk_rate;
186+
};
187+
182188
void msm_dsi_phy_driver_register(void);
183189
void msm_dsi_phy_driver_unregister(void);
184190
int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
185-
const unsigned long bit_rate, const unsigned long esc_rate);
191+
struct msm_dsi_phy_clk_request *clk_req);
186192
void msm_dsi_phy_disable(struct msm_dsi_phy *phy);
187193
void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
188194
struct msm_dsi_phy_shared_timings *shared_timing);

drivers/gpu/drm/msm/dsi/dsi_host.c

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,6 +2128,15 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host)
21282128
udelay(100);
21292129
}
21302130

2131+
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
2132+
struct msm_dsi_phy_clk_request *clk_req)
2133+
{
2134+
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
2135+
2136+
clk_req->bitclk_rate = msm_host->byte_clk_rate * 8;
2137+
clk_req->escclk_rate = msm_host->esc_clk_rate;
2138+
}
2139+
21312140
int msm_dsi_host_enable(struct mipi_dsi_host *host)
21322141
{
21332142
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2175,10 +2184,10 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
21752184
SFPB_GPREG_MASTER_PORT_EN(en));
21762185
}
21772186

2178-
int msm_dsi_host_power_on(struct mipi_dsi_host *host)
2187+
int msm_dsi_host_power_on(struct mipi_dsi_host *host,
2188+
struct msm_dsi_phy_shared_timings *phy_shared_timings)
21792189
{
21802190
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
2181-
struct msm_dsi_phy_shared_timings phy_shared_timings;
21822191
int ret = 0;
21832192

21842193
mutex_lock(&msm_host->dev_mutex);
@@ -2189,35 +2198,13 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
21892198

21902199
msm_dsi_sfpb_config(msm_host, true);
21912200

2192-
ret = dsi_calc_clk_rate(msm_host);
2193-
if (ret) {
2194-
pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
2195-
goto unlock_ret;
2196-
}
2197-
21982201
ret = dsi_host_regulator_enable(msm_host);
21992202
if (ret) {
22002203
pr_err("%s:Failed to enable vregs.ret=%d\n",
22012204
__func__, ret);
22022205
goto unlock_ret;
22032206
}
22042207

2205-
ret = dsi_bus_clk_enable(msm_host);
2206-
if (ret) {
2207-
pr_err("%s: failed to enable bus clocks, %d\n", __func__, ret);
2208-
goto fail_disable_reg;
2209-
}
2210-
2211-
ret = msm_dsi_manager_phy_enable(msm_host->id,
2212-
msm_host->byte_clk_rate * 8,
2213-
msm_host->esc_clk_rate,
2214-
&phy_shared_timings);
2215-
dsi_bus_clk_disable(msm_host);
2216-
if (ret) {
2217-
pr_err("%s: failed to enable phy, %d\n", __func__, ret);
2218-
goto fail_disable_reg;
2219-
}
2220-
22212208
ret = dsi_clk_ctrl(msm_host, 1);
22222209
if (ret) {
22232210
pr_err("%s: failed to enable clocks. ret=%d\n", __func__, ret);
@@ -2233,7 +2220,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
22332220

22342221
dsi_timing_setup(msm_host);
22352222
dsi_sw_reset(msm_host);
2236-
dsi_ctrl_config(msm_host, true, &phy_shared_timings);
2223+
dsi_ctrl_config(msm_host, true, phy_shared_timings);
22372224

22382225
if (msm_host->disp_en_gpio)
22392226
gpiod_set_value(msm_host->disp_en_gpio, 1);
@@ -2269,8 +2256,6 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
22692256

22702257
pinctrl_pm_select_sleep_state(&msm_host->pdev->dev);
22712258

2272-
msm_dsi_manager_phy_disable(msm_host->id);
2273-
22742259
dsi_clk_ctrl(msm_host, 0);
22752260

22762261
dsi_host_regulator_disable(msm_host);
@@ -2290,6 +2275,7 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
22902275
struct drm_display_mode *mode)
22912276
{
22922277
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
2278+
int ret;
22932279

22942280
if (msm_host->mode) {
22952281
drm_mode_destroy(msm_host->dev, msm_host->mode);
@@ -2302,6 +2288,12 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
23022288
return -ENOMEM;
23032289
}
23042290

2291+
ret = dsi_calc_clk_rate(msm_host);
2292+
if (ret) {
2293+
pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
2294+
return ret;
2295+
}
2296+
23052297
return 0;
23062298
}
23072299

drivers/gpu/drm/msm/dsi/dsi_manager.c

Lines changed: 105 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,84 @@ static int dsi_mgr_setup_components(int id)
125125
return ret;
126126
}
127127

128+
static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id,
129+
struct msm_dsi_phy_shared_timings *shared_timings)
130+
{
131+
struct msm_dsi_phy_clk_request clk_req;
132+
int ret;
133+
134+
msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req);
135+
136+
ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req);
137+
msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings);
138+
139+
return ret;
140+
}
141+
142+
static int
143+
dsi_mgr_phy_enable(int id,
144+
struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
145+
{
146+
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
147+
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
148+
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
149+
int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
150+
int ret;
151+
152+
/* In case of dual DSI, some registers in PHY1 have been programmed
153+
* during PLL0 clock's set_rate. The PHY1 reset called by host1 here
154+
* will silently reset those PHY1 registers. Therefore we need to reset
155+
* and enable both PHYs before any PLL clock operation.
156+
*/
157+
if (IS_DUAL_DSI() && mdsi && sdsi) {
158+
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
159+
msm_dsi_host_reset_phy(mdsi->host);
160+
msm_dsi_host_reset_phy(sdsi->host);
161+
162+
ret = enable_phy(mdsi, src_pll_id,
163+
&shared_timings[DSI_CLOCK_MASTER]);
164+
if (ret)
165+
return ret;
166+
ret = enable_phy(sdsi, src_pll_id,
167+
&shared_timings[DSI_CLOCK_SLAVE]);
168+
if (ret) {
169+
msm_dsi_phy_disable(mdsi->phy);
170+
return ret;
171+
}
172+
}
173+
} else {
174+
msm_dsi_host_reset_phy(mdsi->host);
175+
ret = enable_phy(msm_dsi, src_pll_id, &shared_timings[id]);
176+
if (ret)
177+
return ret;
178+
}
179+
180+
msm_dsi->phy_enabled = true;
181+
182+
return 0;
183+
}
184+
185+
static void dsi_mgr_phy_disable(int id)
186+
{
187+
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
188+
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
189+
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
190+
191+
/* disable DSI phy
192+
* In dual-dsi configuration, the phy should be disabled for the
193+
* first controller only when the second controller is disabled.
194+
*/
195+
msm_dsi->phy_enabled = false;
196+
if (IS_DUAL_DSI() && mdsi && sdsi) {
197+
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
198+
msm_dsi_phy_disable(sdsi->phy);
199+
msm_dsi_phy_disable(mdsi->phy);
200+
}
201+
} else {
202+
msm_dsi_phy_disable(msm_dsi->phy);
203+
}
204+
}
205+
128206
struct dsi_connector {
129207
struct drm_connector base;
130208
int id;
@@ -360,22 +438,31 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
360438
struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
361439
struct mipi_dsi_host *host = msm_dsi->host;
362440
struct drm_panel *panel = msm_dsi->panel;
441+
struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
363442
bool is_dual_dsi = IS_DUAL_DSI();
364443
int ret;
365444

366445
DBG("id=%d", id);
367-
if (!msm_dsi_device_connected(msm_dsi) ||
368-
(is_dual_dsi && (DSI_1 == id)))
446+
if (!msm_dsi_device_connected(msm_dsi))
369447
return;
370448

371-
ret = msm_dsi_host_power_on(host);
449+
ret = dsi_mgr_phy_enable(id, phy_shared_timings);
450+
if (ret)
451+
goto phy_en_fail;
452+
453+
/* Do nothing with the host if it is DSI 1 in case of dual DSI */
454+
if (is_dual_dsi && (DSI_1 == id))
455+
return;
456+
457+
ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]);
372458
if (ret) {
373459
pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
374460
goto host_on_fail;
375461
}
376462

377463
if (is_dual_dsi && msm_dsi1) {
378-
ret = msm_dsi_host_power_on(msm_dsi1->host);
464+
ret = msm_dsi_host_power_on(msm_dsi1->host,
465+
&phy_shared_timings[DSI_1]);
379466
if (ret) {
380467
pr_err("%s: power on host1 failed, %d\n",
381468
__func__, ret);
@@ -434,6 +521,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
434521
host1_on_fail:
435522
msm_dsi_host_power_off(host);
436523
host_on_fail:
524+
dsi_mgr_phy_disable(id);
525+
phy_en_fail:
437526
return;
438527
}
439528

@@ -459,10 +548,17 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
459548

460549
DBG("id=%d", id);
461550

462-
if (!msm_dsi_device_connected(msm_dsi) ||
463-
(is_dual_dsi && (DSI_1 == id)))
551+
if (!msm_dsi_device_connected(msm_dsi))
464552
return;
465553

554+
/*
555+
* Do nothing with the host if it is DSI 1 in case of dual DSI.
556+
* It is safe to call dsi_mgr_phy_disable() here because a single PHY
557+
* won't be diabled until both PHYs request disable.
558+
*/
559+
if (is_dual_dsi && (DSI_1 == id))
560+
goto disable_phy;
561+
466562
if (panel) {
467563
ret = drm_panel_disable(panel);
468564
if (ret)
@@ -497,6 +593,9 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
497593
pr_err("%s: host1 power off failed, %d\n",
498594
__func__, ret);
499595
}
596+
597+
disable_phy:
598+
dsi_mgr_phy_disable(id);
500599
}
501600

502601
static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
@@ -664,73 +763,6 @@ void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
664763
{
665764
}
666765

667-
int msm_dsi_manager_phy_enable(int id,
668-
const unsigned long bit_rate, const unsigned long esc_rate,
669-
struct msm_dsi_phy_shared_timings *shared_timings)
670-
{
671-
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
672-
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
673-
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
674-
struct msm_dsi_phy *phy = msm_dsi->phy;
675-
int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
676-
int ret;
677-
678-
/* In case of dual DSI, some registers in PHY1 have been programmed
679-
* during PLL0 clock's set_rate. The PHY1 reset called by host1 here
680-
* will silently reset those PHY1 registers. Therefore we need to reset
681-
* and enable both PHYs before any PLL clock operation.
682-
*/
683-
if (IS_DUAL_DSI() && mdsi && sdsi) {
684-
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
685-
msm_dsi_host_reset_phy(mdsi->host);
686-
msm_dsi_host_reset_phy(sdsi->host);
687-
ret = msm_dsi_phy_enable(mdsi->phy, src_pll_id,
688-
bit_rate, esc_rate);
689-
if (ret)
690-
return ret;
691-
ret = msm_dsi_phy_enable(sdsi->phy, src_pll_id,
692-
bit_rate, esc_rate);
693-
if (ret) {
694-
msm_dsi_phy_disable(mdsi->phy);
695-
return ret;
696-
}
697-
}
698-
} else {
699-
msm_dsi_host_reset_phy(msm_dsi->host);
700-
ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, bit_rate,
701-
esc_rate);
702-
if (ret)
703-
return ret;
704-
}
705-
706-
msm_dsi->phy_enabled = true;
707-
msm_dsi_phy_get_shared_timings(phy, shared_timings);
708-
709-
return 0;
710-
}
711-
712-
void msm_dsi_manager_phy_disable(int id)
713-
{
714-
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
715-
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
716-
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
717-
struct msm_dsi_phy *phy = msm_dsi->phy;
718-
719-
/* disable DSI phy
720-
* In dual-dsi configuration, the phy should be disabled for the
721-
* first controller only when the second controller is disabled.
722-
*/
723-
msm_dsi->phy_enabled = false;
724-
if (IS_DUAL_DSI() && mdsi && sdsi) {
725-
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
726-
msm_dsi_phy_disable(sdsi->phy);
727-
msm_dsi_phy_disable(mdsi->phy);
728-
}
729-
} else {
730-
msm_dsi_phy_disable(phy);
731-
}
732-
}
733-
734766
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
735767
{
736768
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);

0 commit comments

Comments
 (0)