Skip to content

Commit 5e338ed

Browse files
xubilvrkhuangtao
authored andcommitted
drm/rockchip: dw-mipi-dsi: organize dw_mipi_dsi_host_transfer function
Change-Id: I2a9bf2f21950f9fffc89d244308d6270663d5ef2 Signed-off-by: xubilv <xbl@rock-chips.com>
1 parent dc8edea commit 5e338ed

1 file changed

Lines changed: 103 additions & 92 deletions

File tree

drivers/gpu/drm/rockchip/dw-mipi-dsi.c

Lines changed: 103 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <drm/drm_panel.h>
2626
#include <drm/drmP.h>
2727
#include <video/mipi_display.h>
28+
#include <asm/unaligned.h>
2829

2930
#include "rockchip_drm_drv.h"
3031
#include "rockchip_drm_vop.h"
@@ -376,6 +377,56 @@ static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg)
376377
return readl(dsi->base + reg);
377378
}
378379

380+
static int rockchip_wait_w_pld_fifo_not_full(struct dw_mipi_dsi *dsi)
381+
{
382+
u32 sts;
383+
int ret;
384+
385+
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
386+
sts, !(sts & GEN_PLD_W_FULL), 10,
387+
CMD_PKT_STATUS_TIMEOUT_US);
388+
if (ret < 0) {
389+
dev_err(dsi->dev, "generic write payload fifo is full\n");
390+
return ret;
391+
}
392+
393+
return 0;
394+
}
395+
396+
static int rockchip_wait_cmd_fifo_not_full(struct dw_mipi_dsi *dsi)
397+
{
398+
u32 sts;
399+
int ret;
400+
401+
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
402+
sts, !(sts & GEN_CMD_FULL), 10,
403+
CMD_PKT_STATUS_TIMEOUT_US);
404+
if (ret < 0) {
405+
dev_err(dsi->dev, "generic write cmd fifo is full\n");
406+
return ret;
407+
}
408+
409+
return 0;
410+
}
411+
412+
static int rockchip_wait_write_fifo_empty(struct dw_mipi_dsi *dsi)
413+
{
414+
u32 sts;
415+
u32 mask;
416+
int ret;
417+
418+
mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY;
419+
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
420+
sts, (sts & mask) == mask, 10,
421+
CMD_PKT_STATUS_TIMEOUT_US);
422+
if (ret < 0) {
423+
dev_err(dsi->dev, "generic write fifo is full\n");
424+
return ret;
425+
}
426+
427+
return 0;
428+
}
429+
379430
static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
380431
u8 test_data)
381432
{
@@ -568,113 +619,74 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,
568619
return 0;
569620
}
570621

571-
static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)
622+
static void rockchip_set_transfer_mode(struct dw_mipi_dsi *dsi, int flags)
572623
{
573-
int ret;
574-
int sts = 0;
575-
576-
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
577-
sts, !(sts & GEN_CMD_FULL), 1000,
578-
CMD_PKT_STATUS_TIMEOUT_US);
579-
580-
if (ret < 0) {
581-
dev_err(dsi->dev, "failed to get available command FIFO\n");
582-
return ret;
583-
}
584-
585-
dsi_write(dsi, DSI_GEN_HDR, val);
586-
587-
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
588-
sts, sts & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
589-
1000, CMD_PKT_STATUS_TIMEOUT_US);
590-
591-
if (ret < 0) {
592-
dev_err(dsi->dev, "failed to write command FIFO\n");
593-
return ret;
594-
}
595-
596-
return 0;
624+
if (flags & MIPI_DSI_MSG_USE_LPM)
625+
dsi_write(dsi, DSI_CMD_MODE_CFG, CMD_MODE_ALL_LP);
626+
else
627+
dsi_write(dsi, DSI_CMD_MODE_CFG, 0);
597628
}
598629

599-
static int dw_mipi_dsi_short_write(struct dw_mipi_dsi *dsi,
600-
const struct mipi_dsi_msg *msg)
630+
static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
631+
const struct mipi_dsi_msg *msg)
601632
{
602-
const u16 *tx_buf = msg->tx_buf;
603-
u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type);
633+
struct dw_mipi_dsi *dsi = host_to_dsi(host);
634+
struct mipi_dsi_packet packet;
635+
int ret;
636+
int val;
637+
int len = msg->tx_len;
604638

605-
if (msg->tx_len > 2) {
606-
dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
607-
msg->tx_len);
608-
return -EINVAL;
639+
/* create a packet to the DSI protocol */
640+
ret = mipi_dsi_create_packet(&packet, msg);
641+
if (ret) {
642+
dev_err(dsi->dev, "failed to create packet: %d\n", ret);
643+
return ret;
609644
}
610645

611-
return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
612-
}
646+
rockchip_set_transfer_mode(dsi, msg->flags);
613647

614-
static int dw_mipi_dsi_long_write(struct dw_mipi_dsi *dsi,
615-
const struct mipi_dsi_msg *msg)
616-
{
617-
const u32 *tx_buf = msg->tx_buf;
618-
int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret;
619-
u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
620-
u32 remainder = 0;
621-
u32 sts = 0;
622-
623-
if (msg->tx_len < 3) {
624-
dev_err(dsi->dev, "wrong tx buf length %zu for long write\n",
625-
msg->tx_len);
626-
return -EINVAL;
627-
}
648+
/* Send payload, */
649+
while (DIV_ROUND_UP(packet.payload_length, 4)) {
650+
/*
651+
* Alternatively, you can always keep the FIFO
652+
* nearly full by monitoring the FIFO state until
653+
* it is not full, and then writea single word of data.
654+
* This solution is more resource consuming
655+
* but it simultaneously avoids FIFO starvation,
656+
* making it possible to use FIFO sizes smaller than
657+
* the amount of data of the longest packet to be written.
658+
*/
659+
ret = rockchip_wait_w_pld_fifo_not_full(dsi);
660+
if (ret)
661+
return ret;
628662

629-
while (DIV_ROUND_UP(len, pld_data_bytes)) {
630-
if (len < pld_data_bytes) {
631-
memcpy(&remainder, tx_buf, len);
632-
dsi_write(dsi, DSI_GEN_PLD_DATA, remainder);
633-
len = 0;
663+
if (packet.payload_length < 4) {
664+
/* send residu payload */
665+
val = 0;
666+
memcpy(&val, packet.payload, packet.payload_length);
667+
dsi_write(dsi, DSI_GEN_PLD_DATA, val);
668+
packet.payload_length = 0;
634669
} else {
635-
dsi_write(dsi, DSI_GEN_PLD_DATA, *tx_buf);
636-
tx_buf++;
637-
len -= pld_data_bytes;
638-
}
639-
640-
ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
641-
sts, !(sts & GEN_PLD_W_FULL), 1000,
642-
CMD_PKT_STATUS_TIMEOUT_US);
643-
if (ret < 0) {
644-
dev_err(dsi->dev,
645-
"failed to get available write payload FIFO\n");
646-
return ret;
670+
val = get_unaligned_le32(packet.payload);
671+
dsi_write(dsi, DSI_GEN_PLD_DATA, val);
672+
packet.payload += 4;
673+
packet.payload_length -= 4;
647674
}
648675
}
649676

650-
return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
651-
}
677+
ret = rockchip_wait_cmd_fifo_not_full(dsi);
678+
if (ret)
679+
return ret;
652680

653-
static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
654-
const struct mipi_dsi_msg *msg)
655-
{
656-
struct dw_mipi_dsi *dsi = host_to_dsi(host);
657-
int ret;
681+
/* Send packet header */
682+
val = get_unaligned_le32(packet.header);
683+
dsi_write(dsi, DSI_GEN_HDR, val);
658684

659-
switch (msg->type) {
660-
case MIPI_DSI_DCS_SHORT_WRITE:
661-
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
662-
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
663-
case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
664-
case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
665-
case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
666-
ret = dw_mipi_dsi_short_write(dsi, msg);
667-
break;
668-
case MIPI_DSI_DCS_LONG_WRITE:
669-
case MIPI_DSI_GENERIC_LONG_WRITE:
670-
ret = dw_mipi_dsi_long_write(dsi, msg);
671-
break;
672-
default:
673-
dev_err(dsi->dev, "unsupported message type\n");
674-
ret = -EINVAL;
675-
}
685+
ret = rockchip_wait_write_fifo_empty(dsi);
686+
if (ret)
687+
return ret;
676688

677-
return ret;
689+
return len;
678690
}
679691

680692
static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = {
@@ -770,7 +782,6 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
770782
{
771783
dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
772784
dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00);
773-
dsi_write(dsi, DSI_CMD_MODE_CFG, CMD_MODE_ALL_LP);
774785
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
775786
}
776787

0 commit comments

Comments
 (0)