Skip to content

Commit e596d70

Browse files
njhollinghurstpelwell
authored andcommitted
drivers: drm: rp1-dsi: Implement more DSI options and flags
Now implementing: - Per-command selection of LP or HS for commands (previously LP) - EoTp transmission option (previously EoTp was always disabled) - Non-continuous clock option (previously always continuous) - Per-command enabling of ACK request (in command mode only) Make a plausible (and possibly correct) attempt to measure the longest LP command that will fit into vertical blanking lines. DON'T set both "Burst Mode" and "Sync Events" flags together. This is redundant in the standard IP; in this RP1 variant it would enable Sync Pulses but may break with some video timings. Signed-off-by: Nick Hollinghurst <[email protected]>
1 parent ba0f221 commit e596d70

File tree

3 files changed

+91
-23
lines changed

3 files changed

+91
-23
lines changed

drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,10 @@ ssize_t rp1dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_m
396396
return ret;
397397
}
398398

399-
rp1dsi_dsi_send(dsi, *(u32 *)(&packet.header), packet.payload_length, packet.payload);
399+
rp1dsi_dsi_send(dsi, *(u32 *)(&packet.header),
400+
packet.payload_length, packet.payload,
401+
!!(msg->flags & MIPI_DSI_MSG_USE_LPM),
402+
!!(msg->flags & MIPI_DSI_MSG_REQ_ACK));
400403

401404
/* Optional read back */
402405
if (msg->rx_len && msg->rx_buf)

drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi);
8686
/* Functions to control the SNPS D-PHY and DSI block setup */
8787

8888
void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode);
89-
void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 header, int len, const u8 *buf);
89+
void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 header, int len, const u8 *buf,
90+
bool use_lpm, bool req_ack);
9091
int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf);
9192
void rp1dsi_dsi_set_cmdmode(struct rp1_dsi *dsi, int cmd_mode);
9293
void rp1dsi_dsi_stop(struct rp1_dsi *dsi);

drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@
103103

104104
/* And some bitfield definitions */
105105

106+
#define DSI_PCKHDL_EOTP_TX_EN BIT(0)
107+
#define DSI_PCKHDL_BTA_EN BIT(2)
108+
109+
#define DSI_VID_MODE_LP_CMD_EN BIT(15)
110+
#define DSI_VID_MODE_FRAME_BTA_ACK_EN BIT(14)
111+
#define DSI_VID_MODE_LP_HFP_EN BIT(13)
112+
#define DSI_VID_MODE_LP_HBP_EN BIT(12)
113+
#define DSI_VID_MODE_LP_VACT_EN BIT(11)
114+
#define DSI_VID_MODE_LP_VFP_EN BIT(10)
115+
#define DSI_VID_MODE_LP_VBP_EN BIT(9)
116+
#define DSI_VID_MODE_LP_VSA_EN BIT(8)
117+
#define DSI_VID_MODE_SYNC_PULSES 0
118+
#define DSI_VID_MODE_SYNC_EVENTS 1
119+
#define DSI_VID_MODE_BURST 2
120+
121+
#define DSI_CMD_MODE_ALL_LP 0x10f7f00
122+
#define DSI_CMD_MODE_ACK_RQST_EN BIT(1)
123+
106124
#define DPHY_PWR_UP_SHUTDOWNZ_LSB 0
107125
#define DPHY_PWR_UP_SHUTDOWNZ_BITS BIT(DPHY_PWR_UP_SHUTDOWNZ_LSB)
108126

@@ -1252,8 +1270,8 @@ static u32 dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk, u32 vco_freq)
12521270
vco_freq, actual_vco_freq, m, refclk, n,
12531271
hsfreq_table[dsi->hsfreq_index].hsfreqrange);
12541272
} else {
1255-
drm_warn(dsi->drm,
1256-
"rp1dsi: Error configuring DPHY PLL %uHz\n", vco_freq);
1273+
drm_err(dsi->drm,
1274+
"rp1dsi: Error configuring DPHY PLL %uHz\n", vco_freq);
12571275
}
12581276

12591277
return actual_vco_freq;
@@ -1321,7 +1339,7 @@ static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, u32 byte_clock,
13211339
clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * byte_clock) / (bpp >> 1));
13221340
clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]);
13231341
drm_info(dsi->drm,
1324-
"rp1dsi: Nominal Byte clock %u DPI clock %lu (parent rate %lu)",
1342+
"rp1dsi: Nominal Byte clock %u DPI clock %lu (parent rate %lu)\n",
13251343
byte_clock,
13261344
clk_get_rate(dsi->clocks[RP1DSI_CLOCK_DPI]),
13271345
clk_get_rate(clk_get_parent(dsi->clocks[RP1DSI_CLOCK_DPI])));
@@ -1365,7 +1383,8 @@ static u32 get_colorcode(enum mipi_dsi_pixel_format fmt)
13651383

13661384
void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
13671385
{
1368-
u32 timeout, mask, vid_mode_cfg;
1386+
int cmdtim;
1387+
u32 timeout, mask, clkdiv;
13691388
unsigned int bpp = mipi_dsi_pixel_format_to_bpp(dsi->display_format);
13701389
u32 byte_clock = clamp((bpp * 125 * min(mode->clock, RP1DSI_DPI_MAX_KHZ)) / dsi->lanes,
13711390
RP1DSI_BYTE_CLK_MIN, RP1DSI_BYTE_CLK_MAX);
@@ -1374,19 +1393,31 @@ void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
13741393
DSI_WRITE(DSI_DPI_CFG_POL, 0);
13751394
DSI_WRITE(DSI_GEN_VCID, dsi->vc);
13761395
DSI_WRITE(DSI_DPI_COLOR_CODING, get_colorcode(dsi->display_format));
1377-
/* a conservative guess (LP escape is slow!) */
1378-
DSI_WRITE(DSI_DPI_LP_CMD_TIM, 0x00100000);
13791396

1380-
/* Drop to LP where possible; use LP Escape for all commands */
1381-
vid_mode_cfg = 0xbf00;
1382-
if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
1383-
vid_mode_cfg |= 0x01;
1384-
else if (8 * dsi->lanes > bpp)
1385-
vid_mode_cfg &= ~0x400; /* PULSE && inexact DPICLK => fix HBP time */
1397+
/*
1398+
* Flags to configure use of LP, EoTp, Burst Mode, Sync Events/Pulses.
1399+
* Note that Burst Mode implies Sync Events; the two flags need not be
1400+
* set concurrently, and in this RP1 variant *should not* both be set:
1401+
* doing so would (counter-intuitively) enable Sync Pulses and may fail
1402+
* if there is not sufficient time to return to LP11 state during HBP.
1403+
*/
1404+
mask = DSI_VID_MODE_LP_HFP_EN | DSI_VID_MODE_LP_HBP_EN |
1405+
DSI_VID_MODE_LP_VACT_EN | DSI_VID_MODE_LP_VFP_EN |
1406+
DSI_VID_MODE_LP_VBP_EN | DSI_VID_MODE_LP_VSA_EN;
1407+
if (dsi->display_flags & MIPI_DSI_MODE_LPM)
1408+
mask |= DSI_VID_MODE_LP_CMD_EN;
13861409
if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_BURST)
1387-
vid_mode_cfg |= 0x02;
1388-
DSI_WRITE(DSI_VID_MODE_CFG, vid_mode_cfg);
1389-
DSI_WRITE(DSI_CMD_MODE_CFG, 0x10F7F00);
1410+
mask |= DSI_VID_MODE_BURST;
1411+
else if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
1412+
mask |= DSI_VID_MODE_SYNC_EVENTS;
1413+
else if (8 * dsi->lanes > bpp)
1414+
mask &= ~DSI_VID_MODE_LP_HBP_EN; /* PULSE && inexact DPICLK => fix HBP time */
1415+
DSI_WRITE(DSI_VID_MODE_CFG, mask);
1416+
DSI_WRITE(DSI_CMD_MODE_CFG,
1417+
(dsi->display_flags & MIPI_DSI_MODE_LPM) ? DSI_CMD_MODE_ALL_LP : 0);
1418+
DSI_WRITE(DSI_PCKHDL_CFG,
1419+
DSI_PCKHDL_BTA_EN |
1420+
((dsi->display_flags & MIPI_DSI_MODE_NO_EOT_PACKET) ? 0 : DSI_PCKHDL_EOTP_TX_EN));
13901421

13911422
/* Select Command Mode */
13921423
DSI_WRITE(DSI_MODE_CFG, 1);
@@ -1397,9 +1428,9 @@ void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
13971428
timeout = 0;
13981429
DSI_WRITE(DSI_TO_CNT_CFG, (timeout << 16) | RP1DSI_LPRX_TO_VAL);
13991430
DSI_WRITE(DSI_BTA_TO_CNT, RP1DSI_BTA_TO_VAL);
1431+
clkdiv = max(2u, 1u + byte_clock / RP1DSI_ESC_CLK_MAX); /* byte clocks per escape clock */
14001432
DSI_WRITE(DSI_CLKMGR_CFG,
1401-
(RP1DSI_TO_CLK_DIV << 8) |
1402-
max(2u, 1u + byte_clock / RP1DSI_ESC_CLK_MAX));
1433+
(RP1DSI_TO_CLK_DIV << 8) | clkdiv);
14031434

14041435
/* Configure video timings */
14051436
DSI_WRITE(DSI_VID_PKT_SIZE, mode->hdisplay);
@@ -1425,6 +1456,18 @@ void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
14251456
(hsfreq_table[dsi->hsfreq_index].data_lp2hs << DSI_PHY_TMR_LP2HS_LSB) |
14261457
(hsfreq_table[dsi->hsfreq_index].data_hs2lp << DSI_PHY_TMR_HS2LP_LSB));
14271458

1459+
/* Estimate how many LP bytes can be sent during vertical blanking (Databook 3.6.2.1) */
1460+
cmdtim = mode->htotal;
1461+
if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
1462+
cmdtim -= mode->hsync_end - mode->hsync_start;
1463+
cmdtim = (bpp * cmdtim - 64) / (8 * dsi->lanes); /* byte clocks after HSS and EoTp */
1464+
cmdtim -= hsfreq_table[dsi->hsfreq_index].data_hs2lp;
1465+
cmdtim -= hsfreq_table[dsi->hsfreq_index].data_lp2hs;
1466+
cmdtim = (cmdtim / clkdiv) - 24; /* escape clocks for commands */
1467+
cmdtim = max(0, cmdtim >> 4); /* bytes (at 2 clocks per bit) */
1468+
drm_info(dsi->drm, "rp1dsi: Command time (outvact): %d\n", cmdtim);
1469+
DSI_WRITE(DSI_DPI_LP_CMD_TIM, cmdtim << 16);
1470+
14281471
/* Wait for PLL lock */
14291472
for (timeout = (1 << 14); timeout != 0; --timeout) {
14301473
usleep_range(10, 50);
@@ -1434,9 +1477,9 @@ void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
14341477
if (timeout == 0)
14351478
drm_err(dsi->drm, "RP1DSI: Time out waiting for PLL\n");
14361479

1437-
DSI_WRITE(DSI_LPCLK_CTRL, 0x1); /* configure the requesthsclk */
1480+
DSI_WRITE(DSI_LPCLK_CTRL,
1481+
(dsi->display_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? 0x3 : 0x1);
14381482
DSI_WRITE(DSI_PHY_TST_CTRL0, 0x2);
1439-
DSI_WRITE(DSI_PCKHDL_CFG, 1 << 2); /* allow bus turnaround */
14401483
DSI_WRITE(DSI_PWR_UP, 0x1); /* power up */
14411484

14421485
/* Now it should be safe to start the external DPI clock divider */
@@ -1460,7 +1503,8 @@ void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
14601503
mask, DSI_READ(DSI_PHY_STATUS));
14611504
}
14621505

1463-
void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 hdr, int len, const u8 *buf)
1506+
void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 hdr, int len, const u8 *buf,
1507+
bool use_lpm, bool req_ack)
14641508
{
14651509
u32 val;
14661510

@@ -1471,6 +1515,24 @@ void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 hdr, int len, const u8 *buf)
14711515
usleep_range(100, 150);
14721516
}
14731517

1518+
/*
1519+
* Update global configuration flags for LP/HS and ACK options.
1520+
* XXX It's not clear if having empty FIFOs (checked above and below) guarantees that
1521+
* the last command has completed and been ACKed, or how closely these control registers
1522+
* align with command/payload FIFO writes (as each is an independent clock-crossing)?
1523+
*/
1524+
val = DSI_READ(DSI_VID_MODE_CFG);
1525+
if (use_lpm)
1526+
val |= DSI_VID_MODE_LP_CMD_EN;
1527+
else
1528+
val &= ~DSI_VID_MODE_LP_CMD_EN;
1529+
DSI_WRITE(DSI_VID_MODE_CFG, val);
1530+
val = (use_lpm) ? DSI_CMD_MODE_ALL_LP : 0;
1531+
if (req_ack)
1532+
val |= DSI_CMD_MODE_ACK_RQST_EN;
1533+
DSI_WRITE(DSI_CMD_MODE_CFG, val);
1534+
(void)DSI_READ(DSI_CMD_MODE_CFG);
1535+
14741536
/* Write payload (in 32-bit words) and header */
14751537
for (; len > 0; len -= 4) {
14761538
val = *buf++;
@@ -1504,8 +1566,10 @@ int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf)
15041566
break;
15051567
usleep_range(100, 150);
15061568
}
1507-
if (i == 0)
1569+
if (!i) {
1570+
drm_warn(dsi->drm, "Receive failed\n");
15081571
return -EIO;
1572+
}
15091573

15101574
for (i = 0; i < len; i += 4) {
15111575
/* Read fifo must not be empty before all bytes are read */

0 commit comments

Comments
 (0)