Thread (22 messages) 22 messages, 6 authors, 2020-04-10

Re: [PATCH v5 1/5] drm: bridge: dw_mipi_dsi: add initial regmap infrastructure

From: Adrian Ratiu <hidden>
Date: 2020-03-30 21:15:52
Also in: dri-devel, linux-devicetree, linux-rockchip, lkml

On Mon, 30 Mar 2020, adrian61 [off-list ref] wrote:
Hello Adrian, 

I am testing hese changes on my STM32F769-DISCO and i found 
that: 

On Mon, Mar 30, 2020 at 2:35 PM Adrian Ratiu 
[off-list ref] wrote: 
quoted
In order to support multiple versions of the Synopsis MIPI DSI 
host controller, which have different register layouts but 
almost identical HW protocols, we add a regmap infrastructure 
which can abstract away register accesses for platform drivers 
using the bridge. 

The controller HW revision is detected during bridge probe 
which will be used in future commits to load the relevant 
register layout which the bridge will use transparently to the 
platform drivers. 

Signed-off-by: Adrian Ratiu <redacted> --- 
New in v5.  --- 
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 208 
 ++++++++++-------- 1 file changed, 117 insertions(+), 91 
 deletions(-) 
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 
5ef0f154aa7b..6d9e2f21c9cc 100644 --- 
a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -15,6 +15,7 
@@ 
 #include <linux/module.h> #include <linux/of_device.h> 
 #include <linux/pm_runtime.h> 
+#include <linux/regmap.h> 
 #include <linux/reset.h> 

 #include <video/mipi_display.h> 
@@ -227,6 +228,7 @@ struct dw_mipi_dsi { 
        struct drm_bridge *panel_bridge; struct device *dev; 
        void __iomem *base; 
+       struct regmap *regs; 

        struct clk *pclk; 
@@ -235,6 +237,7 @@ struct dw_mipi_dsi { 
        u32 lanes; u32 format; unsigned long mode_flags; 
+       u32 hw_version; 

 #ifdef CONFIG_DEBUG_FS 
        struct dentry *debugfs; 
@@ -249,6 +252,13 @@ struct dw_mipi_dsi { 
        const struct dw_mipi_dsi_plat_data *plat_data; 
 }; 

+static const struct regmap_config dw_mipi_dsi_regmap_cfg = { + 
.reg_bits = 32, +       .val_bits = 32, +       .reg_stride = 
4, +       .name = "dw-mipi-dsi", +}; + 
 /* 
  * Check if either a link to a master or slave is present */ 
@@ -280,16 +290,6 @@ static inline struct dw_mipi_dsi 
*bridge_to_dsi(struct drm_bridge *bridge) 
        return container_of(bridge, struct dw_mipi_dsi, 
        bridge); 
 } 

-static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, 
u32 val) -{ -       writel(val, dsi->base + reg); -} - -static 
inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg) -{ - 
return readl(dsi->base + reg); -} - 
 static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, 
                                   struct mipi_dsi_device 
                                   *device) 
 { 
@@ -366,29 +366,29 @@ static void dw_mipi_message_config(struct 
dw_mipi_dsi *dsi, 
        if (lpm) 
                val |= CMD_MODE_ALL_LP; 

-       dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : 
PHY_TXREQUESTCLKHS); -       dsi_write(dsi, DSI_CMD_MODE_CFG, 
val); +       regmap_write(dsi->regs, DSI_LPCLK_CTRL, lpm ? 0 : 
PHY_TXREQUESTCLKHS); +       regmap_write(dsi->regs, 
DSI_CMD_MODE_CFG, val); 
 } 

 static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi 
 *dsi, u32 hdr_val) { 
        int ret; 
-       u32 val, mask; +       u32 val = 0, mask; 

-       ret = readl_poll_timeout(dsi->base + 
DSI_CMD_PKT_STATUS, -                                val, !(val 
& GEN_CMD_FULL), 1000, - 
CMD_PKT_STATUS_TIMEOUT_US); +       ret = 
regmap_read_poll_timeout(dsi->regs, DSI_CMD_PKT_STATUS, + 
val, !(val & GEN_CMD_FULL), 1000, + 
CMD_PKT_STATUS_TIMEOUT_US); 
        if (ret) { 
                dev_err(dsi->dev, "failed to get available 
                command FIFO\n"); return ret; 
        } 

-       dsi_write(dsi, DSI_GEN_HDR, hdr_val); + 
regmap_write(dsi->regs, DSI_GEN_HDR, hdr_val); 

        mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY; 
-       ret = readl_poll_timeout(dsi->base + 
DSI_CMD_PKT_STATUS, -                                val, (val 
& mask) == mask, -                                1000, 
CMD_PKT_STATUS_TIMEOUT_US); +       ret = 
regmap_read_poll_timeout(dsi->regs, DSI_CMD_PKT_STATUS, + 
val, (val & mask) == mask, + 
1000, CMD_PKT_STATUS_TIMEOUT_US); 
        if (ret) { 
                dev_err(dsi->dev, "failed to write command 
                FIFO\n"); return ret; 
@@ -403,24 +403,26 @@ static int dw_mipi_dsi_write(struct 
dw_mipi_dsi *dsi, 
        const u8 *tx_buf = packet->payload; int len = 
        packet->payload_length, pld_data_bytes = sizeof(u32), 
        ret; __le32 word; 
-       u32 val; +       u32 val = 0; 

        while (len) { 
                if (len < pld_data_bytes) { 
                        word = 0; memcpy(&word, tx_buf, len); 
-                       dsi_write(dsi, DSI_GEN_PLD_DATA, 
le32_to_cpu(word)); + 
regmap_write(dsi->regs, DSI_GEN_PLD_DATA, + 
le32_to_cpu(word)); 
                        len = 0; 
                } else { 
                        memcpy(&word, tx_buf, pld_data_bytes); 
-                       dsi_write(dsi, DSI_GEN_PLD_DATA, 
le32_to_cpu(word)); + 
regmap_write(dsi->regs, DSI_GEN_PLD_DATA, + 
le32_to_cpu(word)); 
                        tx_buf += pld_data_bytes; len -= 
                        pld_data_bytes; 
                } 

-               ret = readl_poll_timeout(dsi->base + 
DSI_CMD_PKT_STATUS, - 
val, !(val & GEN_PLD_W_FULL), 1000, - 
CMD_PKT_STATUS_TIMEOUT_US); +               ret = 
regmap_read_poll_timeout(dsi->regs, DSI_CMD_PKT_STATUS, + 
val, !(val & GEN_PLD_W_FULL), + 
1000, CMD_PKT_STATUS_TIMEOUT_US); 
                if (ret) { 
                        dev_err(dsi->dev, 
                                "failed to get available write 
                                payload FIFO\n"); 
@@ -438,12 +440,12 @@ static int dw_mipi_dsi_read(struct 
dw_mipi_dsi *dsi, 
 { 
        int i, j, ret, len = msg->rx_len; u8 *buf = 
        msg->rx_buf; 
-       u32 val; +       u32 val = 0; 

        /* Wait end of the read operation */ 
-       ret = readl_poll_timeout(dsi->base + 
DSI_CMD_PKT_STATUS, -                                val, !(val 
& GEN_RD_CMD_BUSY), -                                1000, 
CMD_PKT_STATUS_TIMEOUT_US); +       ret = 
regmap_read_poll_timeout(dsi->regs, DSI_CMD_PKT_STATUS, + 
val, !(val & GEN_RD_CMD_BUSY), + 
1000, CMD_PKT_STATUS_TIMEOUT_US); 
        if (ret) { 
                dev_err(dsi->dev, "Timeout during read 
                operation\n"); return ret; 
@@ -451,15 +453,15 @@ static int dw_mipi_dsi_read(struct 
dw_mipi_dsi *dsi, 

        for (i = 0; i < len; i += 4) { 
                /* Read fifo must not be empty before all bytes 
                are read */ 
-               ret = readl_poll_timeout(dsi->base + 
DSI_CMD_PKT_STATUS, - 
val, !(val & GEN_PLD_R_EMPTY), - 
1000, CMD_PKT_STATUS_TIMEOUT_US); +               ret = 
regmap_read_poll_timeout(dsi->regs, DSI_CMD_PKT_STATUS, + 
val, !(val & GEN_PLD_R_EMPTY), + 
1000, CMD_PKT_STATUS_TIMEOUT_US); 
                if (ret) { 
                        dev_err(dsi->dev, "Read payload FIFO is 
                        empty\n"); return ret; 
                } 

-               val = dsi_read(dsi, DSI_GEN_PLD_DATA); + 
regmap_read(dsi->regs, DSI_GEN_PLD_DATA, &val); 
                for (j = 0; j < 4 && j + i < len; j++) 
                        buf[i + j] = val >> (8 * j); 
        } 
@@ -536,29 +538,29 @@ static void 
dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) 
        } 
 #endif /* CONFIG_DEBUG_FS */ 

-       dsi_write(dsi, DSI_VID_MODE_CFG, val); + 
regmap_write(dsi->regs, DSI_VID_MODE_CFG, val); 
 } 

 static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi, 
                                 unsigned long mode_flags) 
 { 
-       dsi_write(dsi, DSI_PWR_UP, RESET); + 
regmap_write(dsi->regs, DSI_PWR_UP, RESET); 

        if (mode_flags & MIPI_DSI_MODE_VIDEO) { 
-               dsi_write(dsi, DSI_MODE_CFG, 
ENABLE_VIDEO_MODE); +               regmap_write(dsi->regs, 
DSI_MODE_CFG, ENABLE_VIDEO_MODE); 
                dw_mipi_dsi_video_mode_config(dsi); 
-               dsi_write(dsi, DSI_LPCLK_CTRL, 
PHY_TXREQUESTCLKHS); +               regmap_write(dsi->regs, 
DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS); 
        } else { 
-               dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); 
+               regmap_write(dsi->regs, DSI_MODE_CFG, 
ENABLE_CMD_MODE); 
        } 

-       dsi_write(dsi, DSI_PWR_UP, POWERUP); + 
regmap_write(dsi->regs, DSI_PWR_UP, POWERUP); 
 } 

 static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi) { 
-       dsi_write(dsi, DSI_PWR_UP, RESET); - 
dsi_write(dsi, DSI_PHY_RSTZ, PHY_RSTZ); + 
regmap_write(dsi->regs, DSI_PWR_UP, RESET); + 
regmap_write(dsi->regs, DSI_PHY_RSTZ, PHY_RSTZ); 
 } 

 static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) 
@@ -573,14 +575,14 @@ static void dw_mipi_dsi_init(struct 
dw_mipi_dsi *dsi) 
         */ 
        u32 esc_clk_division = (dsi->lane_mbps >> 3) / 20 + 1; 

-       dsi_write(dsi, DSI_PWR_UP, RESET); + 
regmap_write(dsi->regs, DSI_PWR_UP, RESET); 

        /* 
         * TODO dw drv improvements * timeout clock division 
         should be computed with the * high speed transmission 
         counter timeout and byte lane...  */ 
-       dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) | + 
regmap_write(dsi->regs, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) | 
                  TX_ESC_CLK_DIVISION(esc_clk_division)); 
 } 
@@ -609,22 +611,22 @@ static void dw_mipi_dsi_dpi_config(struct 
dw_mipi_dsi *dsi, 
        if (mode->flags & DRM_MODE_FLAG_NHSYNC) 
                val |= HSYNC_ACTIVE_LOW; 

-       dsi_write(dsi, DSI_DPI_VCID, DPI_VCID(dsi->channel)); - 
dsi_write(dsi, DSI_DPI_COLOR_CODING, color); - 
dsi_write(dsi, DSI_DPI_CFG_POL, val); + 
regmap_write(dsi->regs, DSI_DPI_VCID, DPI_VCID(dsi->channel)); 
+       regmap_write(dsi->regs, DSI_DPI_COLOR_CODING, color); + 
regmap_write(dsi->regs, DSI_DPI_CFG_POL, val); 
        /* 
         * TODO dw drv improvements * largest packet sizes 
         during hfp or during vsa/vpb/vfp * should be computed 
         according to byte lane, lane number and only * if 
         sending lp cmds in high speed is enable 
         (PHY_TXREQUESTCLKHS) */ 
-       dsi_write(dsi, DSI_DPI_LP_CMD_TIM, 
OUTVACT_LPCMD_TIME(4) +       regmap_write(dsi->regs, 
DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(4) 
                  | INVACT_LPCMD_TIME(4)); 
 } 

 static void dw_mipi_dsi_packet_handler_config(struct 
 dw_mipi_dsi *dsi) { 
-       dsi_write(dsi, DSI_PCKHDL_CFG, CRC_RX_EN | ECC_RX_EN | 
BTA_EN); +       regmap_write(dsi->regs, DSI_PCKHDL_CFG, 
CRC_RX_EN | ECC_RX_EN | BTA_EN); 
 } 

 static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi 
 *dsi, 
@@ -638,7 +640,7 @@ static void 
dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi, 
         * non-burst video modes, see 
         dw_mipi_dsi_video_mode_config()...  */ 

-       dsi_write(dsi, DSI_VID_PKT_SIZE, + 
regmap_write(dsi->regs, DSI_VID_PKT_SIZE, 
                       dw_mipi_is_dual_mode(dsi) ? 
                                VID_PKT_SIZE(mode->hdisplay / 
                                2) : 
                                VID_PKT_SIZE(mode->hdisplay)); 
@@ -651,14 +653,15 @@ static void 
dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) 
         * compute high speed transmission counter timeout 
         according * to the timeout clock division 
         (TO_CLK_DIVISION) and byte lane...  */ 
-       dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | 
LPRX_TO_CNT(1000)); +       regmap_write(dsi->regs, 
DSI_TO_CNT_CFG, +                    HSTX_TO_CNT(1000) | 
LPRX_TO_CNT(1000)); 
        /* 
         * TODO dw drv improvements * the Bus-Turn-Around 
         Timeout Counter should be computed * according to byte 
         lane...  */ 
-       dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00); - 
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); + 
regmap_write(dsi->regs, DSI_BTA_TO_CNT, 0xd00); + 
regmap_write(dsi->regs, DSI_MODE_CFG, ENABLE_CMD_MODE); 
 } 

 /* Get lane byte clock cycles. */ 
@@ -692,13 +695,13 @@ static void 
dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi, 
         * computations below may be improved...  */ 
        lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, 
        htotal); 
-       dsi_write(dsi, DSI_VID_HLINE_TIME, lbcc); + 
regmap_write(dsi->regs, DSI_VID_HLINE_TIME, lbcc); 

        lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hsa); 
-       dsi_write(dsi, DSI_VID_HSA_TIME, lbcc); + 
regmap_write(dsi->regs, DSI_VID_HSA_TIME, lbcc); 

        lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hbp); 
-       dsi_write(dsi, DSI_VID_HBP_TIME, lbcc); + 
regmap_write(dsi->regs, DSI_VID_HBP_TIME, lbcc); 
 } 

 static void dw_mipi_dsi_vertical_timing_config(struct 
 dw_mipi_dsi *dsi, 
@@ -711,10 +714,10 @@ static void 
dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi, 
        vfp = mode->vsync_start - mode->vdisplay; vbp = 
        mode->vtotal - mode->vsync_end; 

-       dsi_write(dsi, DSI_VID_VACTIVE_LINES, vactive); - 
dsi_write(dsi, DSI_VID_VSA_LINES, vsa); -       dsi_write(dsi, 
DSI_VID_VFP_LINES, vfp); -       dsi_write(dsi, 
DSI_VID_VBP_LINES, vbp); +       regmap_write(dsi->regs, 
DSI_VID_VACTIVE_LINES, vactive); + 
regmap_write(dsi->regs, DSI_VID_VSA_LINES, vsa); + 
regmap_write(dsi->regs, DSI_VID_VFP_LINES, vfp); + 
regmap_write(dsi->regs, DSI_VID_VBP_LINES, vbp); 
 } 

 static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi 
 *dsi) 
@@ -737,23 +740,25 @@ static void 
dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi) 
         * DSI_CMD_MODE_CFG.MAX_RD_PKT_SIZE_LP (see 
         CMD_MODE_ALL_LP) */ 

-       hw_version = dsi_read(dsi, DSI_VERSION) & VERSION; + 
regmap_read(dsi->regs, DSI_VERSION, &hw_version); + 
hw_version &= VERSION; 

        if (hw_version >= HWVER_131) { 
-               dsi_write(dsi, DSI_PHY_TMR_CFG, - 
PHY_HS2LP_TIME_V131(timing.data_hs2lp) | - 
PHY_LP2HS_TIME_V131(timing.data_lp2hs)); - 
dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000)); + 
regmap_write(dsi->regs, DSI_PHY_TMR_CFG, + 
PHY_HS2LP_TIME_V131(timing.data_hs2lp) | + 
PHY_LP2HS_TIME_V131(timing.data_lp2hs)); + 
regmap_write(dsi->regs, DSI_PHY_TMR_RD_CFG, + 
MAX_RD_TIME_V131(10000)); 
        } else { 
-               dsi_write(dsi, DSI_PHY_TMR_CFG, - 
PHY_HS2LP_TIME(timing.data_hs2lp) | - 
PHY_LP2HS_TIME(timing.data_lp2hs) | - 
MAX_RD_TIME(10000)); +               regmap_write(dsi->regs, 
DSI_PHY_TMR_CFG, + 
PHY_HS2LP_TIME(timing.data_hs2lp) | + 
PHY_LP2HS_TIME(timing.data_lp2hs) | + 
MAX_RD_TIME(10000)); 
        } 

-       dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, - 
PHY_CLKHS2LP_TIME(timing.clk_hs2lp) | - 
PHY_CLKLP2HS_TIME(timing.clk_lp2hs)); + 
regmap_write(dsi->regs, DSI_PHY_TMR_LPCLK_CFG, + 
PHY_CLKHS2LP_TIME(timing.clk_hs2lp) | + 
PHY_CLKLP2HS_TIME(timing.clk_lp2hs)); 
 } 

 static void dw_mipi_dsi_dphy_interface_config(struct 
 dw_mipi_dsi *dsi) 
@@ -763,46 +768,49 @@ static void 
dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi) 
         * stop wait time should be the maximum between host 
         dsi * and panel stop wait times */ 
-       dsi_write(dsi, DSI_PHY_IF_CFG, PHY_STOP_WAIT_TIME(0x20) 
| -                 N_LANES(dsi->lanes)); + 
regmap_write(dsi->regs, DSI_PHY_IF_CFG, + 
PHY_STOP_WAIT_TIME(0x20) | N_LANES(dsi->lanes)); 
 } 

 static void dw_mipi_dsi_dphy_init(struct dw_mipi_dsi *dsi) { 
        /* Clear PHY state */ 
-       dsi_write(dsi, DSI_PHY_RSTZ, PHY_DISFORCEPLL | 
PHY_DISABLECLK -                 | PHY_RSTZ | PHY_SHUTDOWNZ); - 
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); - 
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR); - 
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); + 
regmap_write(dsi->regs, DSI_PHY_RSTZ, PHY_DISFORCEPLL | 
PHY_DISABLECLK +                    | PHY_RSTZ | 
PHY_SHUTDOWNZ); +       regmap_write(dsi->regs, 
DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); + 
regmap_write(dsi->regs, DSI_PHY_TST_CTRL0, PHY_TESTCLR); + 
regmap_write(dsi->regs, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); 
 } 

 static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi) { 
-       u32 val; +       u32 val = 0; 
        int ret; 

-       dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | 
PHY_ENABLECLK | -                 PHY_UNRSTZ | 
PHY_UNSHUTDOWNZ); +       regmap_write(dsi->regs, DSI_PHY_RSTZ, 
PHY_ENFORCEPLL | PHY_ENABLECLK | + 
PHY_UNRSTZ | PHY_UNSHUTDOWNZ); 

-       ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, 
val, -                                val & PHY_LOCK, 1000, 
PHY_STATUS_TIMEOUT_US); +       ret = 
regmap_read_poll_timeout(dsi->regs, DSI_PHY_STATUS, + 
val, val & PHY_LOCK, + 
1000, PHY_STATUS_TIMEOUT_US); 
        if (ret) 
                DRM_DEBUG_DRIVER("failed to wait phy lock 
                state\n"); 

-       ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, - 
val, val & PHY_STOP_STATE_CLK_LANE, 1000, - 
PHY_STATUS_TIMEOUT_US); +       ret = 
regmap_read_poll_timeout(dsi->regs, DSI_PHY_STATUS, + 
val, val & PHY_STOP_STATE_CLK_LANE, 1000, + 
PHY_STATUS_TIMEOUT_US); 
        if (ret) 
                DRM_DEBUG_DRIVER("failed to wait phy clk lane 
                stop state\n"); 
 } 

 static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi) { 
-       dsi_read(dsi, DSI_INT_ST0); -       dsi_read(dsi, 
DSI_INT_ST1); -       dsi_write(dsi, DSI_INT_MSK0, 0); - 
dsi_write(dsi, DSI_INT_MSK1, 0); +       u32 val; + + 
regmap_read(dsi->regs, DSI_INT_ST0, &val); + 
regmap_read(dsi->regs, DSI_INT_ST1, &val); + 
regmap_write(dsi->regs, DSI_INT_MSK0, 0); + 
regmap_write(dsi->regs, DSI_INT_MSK1, 0); 
 } 

 static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge 
 *bridge) 
@@ -989,6 +997,14 @@ static void 
dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { } 

 #endif /* CONFIG_DEBUG_FS */ 

+static void dw_mipi_dsi_get_hw_version(struct dw_mipi_dsi 
*dsi) +{ +       regmap_read(dsi->regs, DSI_VERSION, 
&dsi->hw_version); +       dsi->hw_version &= VERSION; + 
if (!dsi->hw_version) 
Here, this is 0 on my board. 
So we did a live debugging session on the STM board and managed to 
root cause this. The regmap series uncovered a bug introduced by 
the upstream commit fa6251a747b7 ("drm/stm: dsi: check hardware 
version") which disables the peripheral clock immediately after 
reading the version, but it appears that clock is still required 
for the other reads to succeed, otherwise 0 values are read and 
register writes have no effect (display
remains black).

This obviously only happens on the stm driver, will post a fix in 
v6.

Thanks Adrian, much appreciated!
quoted
+               dev_err(dsi->dev, "Failed to read DSI hw version register\n");
+}
+
 static struct dw_mipi_dsi *
 __dw_mipi_dsi_probe(struct platform_device *pdev,
                    const struct dw_mipi_dsi_plat_data *plat_data)
@@ -1020,6 +1036,14 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
                dsi->base = plat_data->base;
        }

+       dsi->regs = devm_regmap_init_mmio(dev, dsi->base,
+                                         &dw_mipi_dsi_regmap_cfg);
+       if (IS_ERR(dsi->regs)) {
+               ret = PTR_ERR(dsi->regs);
+               DRM_ERROR("Failed to create DW MIPI DSI regmap: %d\n", ret);
+               return ERR_PTR(ret);
+       }
+
        dsi->pclk = devm_clk_get(dev, "pclk");
        if (IS_ERR(dsi->pclk)) {
                ret = PTR_ERR(dsi->pclk);
@@ -1055,6 +1079,8 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
                clk_disable_unprepare(dsi->pclk);
        }

+       dw_mipi_dsi_get_hw_version(dsi);
+
        dw_mipi_dsi_debugfs_init(dsi);
        pm_runtime_enable(dev);

--
2.26.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Best regards,
Adrian

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help