Re: [PATCH] drm/bridge/synopsys: dsi: Add 1.31 version support

From: Philippe CORNU
Date: Sun Feb 04 2018 - 15:35:23 EST


Hi Archit,

and many thanks for your comments

On 02/04/2018 04:13 PM, Archit wrote:
> Hi Phillipe,
>
> On Saturday 03 February 2018 03:49 AM, Philippe CORNU wrote:
>> Hi Archit, Andrzej, Laurent & Brian,
>>
>> What is your opinion regarding this patch? Do you have any advice for
>> handling hw versions?
>>
>> Do not hesitate to comment.
>
> The patch looks mostly good to me. One query below.
>
>>
>> Many thanks,
>> Philippe :-)
>>
>>
>> On 01/22/2018 04:08 PM, Philippe Cornu wrote:
>>> From: Philippe CORNU <philippe.cornu@xxxxxx>
>>>
>>> Add support for the Synopsys DesignWare MIPI DSI version 1.31
>>> Two registers need to be updated/added for supporting 1.31:
>>> * PHY_TMR_CFG 0x9c (updated)
>>> ÂÂÂ 1.30 [31:24] phy_hs2lp_time
>>> ÂÂÂÂÂÂÂÂ [23:16] phy_lp2hs_time
>>> ÂÂÂÂÂÂÂÂ [14: 0] max_rd_time
>>>
>>> ÂÂÂ 1.31 [25:16] phy_hs2lp_time
>>> ÂÂÂÂÂÂÂÂ [ 9: 0] phy_lp2hs_time
>>>
>>> * PHY_TMR_RD_CFG 0xf4 (new)
>>> ÂÂÂ 1.31 [14: 0] max_rd_time
>>>
>>> Signed-off-by: Philippe Cornu <philippe.cornu@xxxxxx>
>>> ---
>>> ÂÂ drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 52
>>> +++++++++++++++++++++++----
>>> ÂÂ 1 file changed, 46 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
>>> b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
>>> index 735f38429c06..20a2ca14a7ad 100644
>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
>>> @@ -25,7 +25,13 @@
>>> ÂÂ #include <drm/bridge/dw_mipi_dsi.h>
>>> ÂÂ #include <video/mipi_display.h>
>>> +#define HWVER_130ÂÂÂÂÂÂÂÂÂÂÂ 0x31333000ÂÂÂ /* IP version 1.30 */
>>> +#define HWVER_131ÂÂÂÂÂÂÂÂÂÂÂ 0x31333100ÂÂÂ /* IP version 1.31 */
>>> +#define HWVER_OLDESTÂÂÂÂÂÂÂÂÂÂÂ HWVER_130
>>> +#define HWVER_NEWESTÂÂÂÂÂÂÂÂÂÂÂ HWVER_131
>>> +
>>> ÂÂ #define DSI_VERSIONÂÂÂÂÂÂÂÂÂÂÂ 0x00
>>> +#define VERSIONÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ GENMASK(31, 8)
>>> ÂÂ #define DSI_PWR_UPÂÂÂÂÂÂÂÂÂÂÂ 0x04
>>> ÂÂ #define RESETÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ 0
>>> @@ -161,11 +167,12 @@
>>> ÂÂ #define PHY_CLKHS2LP_TIME(lbcc)ÂÂÂÂÂÂÂ (((lbcc) & 0x3ff) << 16)
>>> ÂÂ #define PHY_CLKLP2HS_TIME(lbcc)ÂÂÂÂÂÂÂ ((lbcc) & 0x3ff)
>>> -/* TODO Next register is slightly different between 1.30 & 1.31 IP
>>> version */
>>> ÂÂ #define DSI_PHY_TMR_CFGÂÂÂÂÂÂÂÂÂÂÂ 0x9c
>>> -#define PHY_HS2LP_TIME(lbcc)ÂÂÂÂÂÂÂ (((lbcc) & 0xff) << 24)
>>> -#define PHY_LP2HS_TIME(lbcc)ÂÂÂÂÂÂÂ (((lbcc) & 0xff) << 16)
>>> -#define MAX_RD_TIME(lbcc)ÂÂÂÂÂÂÂ ((lbcc) & 0x7fff)
>>> +#define PHY_HS2LP_TIME_V130(lbcc)ÂÂÂ (((lbcc) & 0xff) << 24)
>>> +#define PHY_LP2HS_TIME_V130(lbcc)ÂÂÂ (((lbcc) & 0xff) << 16)
>>> +#define MAX_RD_TIME_V130(lbcc)ÂÂÂÂÂÂÂ ((lbcc) & 0x7fff)
>>> +#define PHY_HS2LP_TIME_V131(lbcc)ÂÂÂ (((lbcc) & 0x3ff) << 16)
>>> +#define PHY_LP2HS_TIME_V131(lbcc)ÂÂÂ ((lbcc) & 0x3ff)
>>> ÂÂ #define DSI_PHY_RSTZÂÂÂÂÂÂÂÂÂÂÂ 0xa0
>>> ÂÂ #define PHY_DISFORCEPLLÂÂÂÂÂÂÂÂÂÂÂ 0
>>> @@ -204,7 +211,9 @@
>>> ÂÂ #define DSI_INT_ST1ÂÂÂÂÂÂÂÂÂÂÂ 0xc0
>>> ÂÂ #define DSI_INT_MSK0ÂÂÂÂÂÂÂÂÂÂÂ 0xc4
>>> ÂÂ #define DSI_INT_MSK1ÂÂÂÂÂÂÂÂÂÂÂ 0xc8
>>> +
>>> ÂÂ #define DSI_PHY_TMR_RD_CFGÂÂÂÂÂÂÂ 0xf4
>>> +#define MAX_RD_TIME_V131(lbcc)ÂÂÂÂÂÂÂ ((lbcc) & 0x7fff)
>>> ÂÂ #define PHY_STATUS_TIMEOUT_USÂÂÂÂÂÂÂ 10000
>>> ÂÂ #define CMD_PKT_STATUS_TIMEOUT_USÂÂÂ 20000
>>> @@ -215,6 +224,7 @@ struct dw_mipi_dsi {
>>> ÂÂÂÂÂÂ struct drm_bridge *panel_bridge;
>>> ÂÂÂÂÂÂ struct device *dev;
>>> ÂÂÂÂÂÂ void __iomem *base;
>>> +ÂÂÂ u32 hw_version;
>>> ÂÂÂÂÂÂ struct clk *pclk;
>>> ÂÂÂÂÂÂ struct clk *px_clk;
>>> @@ -616,8 +626,14 @@ static void
>>> dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
>>> ÂÂÂÂÂÂÂ * note: DSI_PHY_TMR_CFG.MAX_RD_TIME should be in line with
>>> ÂÂÂÂÂÂÂ * DSI_CMD_MODE_CFG.MAX_RD_PKT_SIZE_LP (see CMD_MODE_ALL_LP)
>>> ÂÂÂÂÂÂÂ */
>>> -ÂÂÂ dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40)
>>> -ÂÂÂÂÂÂÂÂÂ | PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000));
>>> +ÂÂÂ if (dsi->hw_version == HWVER_131) {
>>> +ÂÂÂÂÂÂÂ dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V131(0x40) |
>>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂ PHY_LP2HS_TIME_V131(0x40));
>>> +ÂÂÂÂÂÂÂ dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000));
>>> +ÂÂÂ } else {
>>> +ÂÂÂÂÂÂÂ dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V130(0x40) |
>>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂ PHY_LP2HS_TIME_V130(0x40) | MAX_RD_TIME_V130(10000));
>>> +ÂÂÂ }
>>> ÂÂÂÂÂÂ dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40)
>>> ÂÂÂÂÂÂÂÂÂÂÂÂ | PHY_CLKLP2HS_TIME(0x40));
>>> @@ -791,6 +807,28 @@ static const struct drm_bridge_funcs
>>> dw_mipi_dsi_bridge_funcs = {
>>> ÂÂÂÂÂÂ .attachÂÂÂÂÂÂÂÂÂ = dw_mipi_dsi_bridge_attach,
>>> ÂÂ };
>>> +static void dsi_get_version(struct dw_mipi_dsi *dsi)
>>> +{
>>> +ÂÂÂ u32 hw_version;
>>> +
>>> +ÂÂÂ clk_prepare_enable(dsi->pclk);
>>> +ÂÂÂ hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
>>> +ÂÂÂ clk_disable_unprepare(dsi->pclk);
>>> +
>>> +ÂÂÂ if (hw_version > HWVER_NEWEST) {
>>> +ÂÂÂÂÂÂÂ DRM_DEBUG("hw version: use 0x%08x for this recent 0x%08x\n",
>>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂ HWVER_NEWEST, hw_version);
>>> +ÂÂÂÂÂÂÂ hw_version = HWVER_NEWEST;
>>> +
>>> +ÂÂÂ } else if (hw_version < HWVER_OLDEST) {
>>> +ÂÂÂÂÂÂÂ DRM_DEBUG("hw version: use 0x%08x for this old 0x%08x\n",
>>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂ HWVER_OLDEST, hw_version);
>>> +ÂÂÂÂÂÂÂ hw_version = HWVER_OLDEST;
>
> I didn't understand the point of HWVER_NEWEST and HWVWER_OLDEST. We're
> not going to have a huge number of hw versions that we need to check if
> our version lies within a range. We should rather have a switch case
> which explicitly sets the hw_version vale based on what we read from
> the DSI_VERSION register.
>

I totally understand your comment : )

My first implementation used a switch case with the 1.30 and 1.31
versions (the 2 versions use by stm32). But default case was difficult
to choose... Moreover, this patch with switch cases may be not
compatible with rockchip if rockchip chipsets have older version than
1.30 and I really did not want to push a patch that could break rockchip
driver!
I do not know the dw dsi versions of rockchip, neither those of
hisilicon nor those of imx... Anyway, I put the 1.30 version into the
default case... But then I did not know how to manage newer versions
(after 1.31)...
At the end, I pushed this patch with version number comparisons and
oldest/newest stuffs because I am sure Rockchip driver will continue to
work with it : )

If you prefer and as you suggested, I can push a patch with switch cases
using 1.30 as the default version, it will work with actual rockchip
driver too.

I will wait for more feedbacks (especially from Brian & Rockchip team)
and do not hesitate to comment my comments.

Many thanks,
Philippe :-)


> The patch looks fine otherwise.
>
> Thanks,
> Archit
>
>>> +ÂÂÂ }
>>> +
>>> +ÂÂÂ dsi->hw_version = hw_version;
>>> +}
>>> +
>>> ÂÂ static struct dw_mipi_dsi *
>>> ÂÂ __dw_mipi_dsi_probe(struct platform_device *pdev,
>>> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ const struct dw_mipi_dsi_plat_data *plat_data)
>>> @@ -870,6 +908,8 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
>>> ÂÂÂÂÂÂÂÂÂÂ clk_disable_unprepare(dsi->pclk);
>>> ÂÂÂÂÂÂ }
>>> +ÂÂÂ dsi_get_version(dsi);
>>> +
>>> ÂÂÂÂÂÂ pm_runtime_enable(dev);
>>> ÂÂÂÂÂÂ dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;