Skip to content

Commit 418bb3a

Browse files
bijudasLaurent Pinchart
authored andcommitted
drm: rcar-du: rzg2l_mipi_dsi: Enhance device lanes check
Enhance device lanes check by reading TXSETR register at probe(), and enforced in rzg2l_mipi_dsi_host_attach(). As per HW manual, we can read TXSETR register only after DPHY initialization. Suggested-by: Laurent Pinchart <[email protected]> Signed-off-by: Biju Das <[email protected]> Reviewed-by: Laurent Pinchart <[email protected]> Signed-off-by: Laurent Pinchart <[email protected]>
1 parent 7a043f9 commit 418bb3a

File tree

1 file changed

+88
-34
lines changed

1 file changed

+88
-34
lines changed

drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@ static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 d
171171
iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
172172
}
173173

174+
static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
175+
{
176+
return ioread32(dsi->mmio + reg);
177+
}
178+
174179
static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
175180
{
176181
return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
@@ -180,52 +185,25 @@ static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
180185
* Hardware Setup
181186
*/
182187

183-
static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
184-
const struct drm_display_mode *mode)
188+
static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
189+
unsigned long hsfreq)
185190
{
186191
const struct rzg2l_mipi_dsi_timings *dphy_timings;
187-
unsigned long hsfreq;
188-
unsigned int i, bpp;
189-
u32 txsetr;
190-
u32 clstptsetr;
191-
u32 lptrnstsetr;
192-
u32 clkkpt;
193-
u32 clkbfht;
194-
u32 clkstpt;
195-
u32 golpbkt;
192+
unsigned int i;
196193
u32 dphyctrl0;
197194
u32 dphytim0;
198195
u32 dphytim1;
199196
u32 dphytim2;
200197
u32 dphytim3;
201198
int ret;
202199

203-
/*
204-
* Relationship between hsclk and vclk must follow
205-
* vclk * bpp = hsclk * 8 * lanes
206-
* where vclk: video clock (Hz)
207-
* bpp: video pixel bit depth
208-
* hsclk: DSI HS Byte clock frequency (Hz)
209-
* lanes: number of data lanes
210-
*
211-
* hsclk(bit) = hsclk(byte) * 8
212-
*/
213-
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
214-
hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
215-
216200
/* All DSI global operation timings are set with recommended setting */
217201
for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
218202
dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
219203
if (hsfreq <= dphy_timings->hsfreq_max)
220204
break;
221205
}
222206

223-
ret = pm_runtime_resume_and_get(dsi->dev);
224-
if (ret < 0)
225-
return ret;
226-
227-
clk_set_rate(dsi->vclk, mode->clock * 1000);
228-
229207
/* Initializing DPHY before accessing LINK */
230208
dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
231209
DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
@@ -259,10 +237,62 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
259237

260238
ret = reset_control_deassert(dsi->rstc);
261239
if (ret < 0)
262-
goto err_pm_put;
240+
return ret;
263241

264242
udelay(1);
265243

244+
return 0;
245+
}
246+
247+
static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
248+
{
249+
u32 dphyctrl0;
250+
251+
dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
252+
253+
dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
254+
rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
255+
256+
reset_control_assert(dsi->rstc);
257+
}
258+
259+
static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
260+
const struct drm_display_mode *mode)
261+
{
262+
unsigned long hsfreq;
263+
unsigned int bpp;
264+
u32 txsetr;
265+
u32 clstptsetr;
266+
u32 lptrnstsetr;
267+
u32 clkkpt;
268+
u32 clkbfht;
269+
u32 clkstpt;
270+
u32 golpbkt;
271+
int ret;
272+
273+
/*
274+
* Relationship between hsclk and vclk must follow
275+
* vclk * bpp = hsclk * 8 * lanes
276+
* where vclk: video clock (Hz)
277+
* bpp: video pixel bit depth
278+
* hsclk: DSI HS Byte clock frequency (Hz)
279+
* lanes: number of data lanes
280+
*
281+
* hsclk(bit) = hsclk(byte) * 8
282+
*/
283+
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
284+
hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
285+
286+
ret = pm_runtime_resume_and_get(dsi->dev);
287+
if (ret < 0)
288+
return ret;
289+
290+
clk_set_rate(dsi->vclk, mode->clock * 1000);
291+
292+
ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
293+
if (ret < 0)
294+
goto err_phy;
295+
266296
/* Enable Data lanes and Clock lanes */
267297
txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
268298
rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
@@ -301,15 +331,16 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
301331

302332
return 0;
303333

304-
err_pm_put:
334+
err_phy:
335+
rzg2l_mipi_dsi_dphy_exit(dsi);
305336
pm_runtime_put(dsi->dev);
306337

307338
return ret;
308339
}
309340

310341
static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
311342
{
312-
reset_control_assert(dsi->rstc);
343+
rzg2l_mipi_dsi_dphy_exit(dsi);
313344
pm_runtime_put(dsi->dev);
314345
}
315346

@@ -666,7 +697,9 @@ static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
666697

667698
static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
668699
{
700+
unsigned int num_data_lanes;
669701
struct rzg2l_mipi_dsi *dsi;
702+
u32 txsetr;
670703
int ret;
671704

672705
dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
@@ -681,7 +714,7 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
681714
return dev_err_probe(dsi->dev, ret,
682715
"missing or invalid data-lanes property\n");
683716

684-
dsi->num_data_lanes = ret;
717+
num_data_lanes = ret;
685718

686719
dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
687720
if (IS_ERR(dsi->mmio))
@@ -710,6 +743,24 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
710743

711744
pm_runtime_enable(dsi->dev);
712745

746+
ret = pm_runtime_resume_and_get(dsi->dev);
747+
if (ret < 0)
748+
goto err_pm_disable;
749+
750+
/*
751+
* TXSETR register can be read only after DPHY init. But during probe
752+
* mode->clock and format are not available. So initialize DPHY with
753+
* timing parameters for 80Mbps.
754+
*/
755+
ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
756+
if (ret < 0)
757+
goto err_phy;
758+
759+
txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
760+
dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
761+
rzg2l_mipi_dsi_dphy_exit(dsi);
762+
pm_runtime_put(dsi->dev);
763+
713764
/* Initialize the DRM bridge. */
714765
dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
715766
dsi->bridge.of_node = dsi->dev->of_node;
@@ -723,6 +774,9 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
723774

724775
return 0;
725776

777+
err_phy:
778+
rzg2l_mipi_dsi_dphy_exit(dsi);
779+
pm_runtime_put(dsi->dev);
726780
err_pm_disable:
727781
pm_runtime_disable(dsi->dev);
728782
return ret;

0 commit comments

Comments
 (0)