[PATCH v9 10/18] drm: bridge: samsung-dsim: Init exynos host for first DSI transfer
Marek Szyprowski
m.szyprowski at samsung.com
Tue Dec 13 15:41:29 UTC 2022
On 13.12.2022 16:15, Jagan Teki wrote:
> On Tue, Dec 13, 2022 at 8:24 PM Marek Szyprowski
> <m.szyprowski at samsung.com> wrote:
>> On 13.12.2022 15:18, Jagan Teki wrote:
>>> On Tue, Dec 13, 2022 at 7:31 PM Marek Szyprowski
>>> <m.szyprowski at samsung.com> wrote:
>>>> On 13.12.2022 13:20, Marek Szyprowski wrote:
>>>>> On 13.12.2022 11:40, Jagan Teki wrote:
>>>>>> On Tue, Dec 13, 2022 at 2:28 PM Marek Szyprowski
>>>>>> <m.szyprowski at samsung.com> wrote:
>>>>>>> On 12.12.2022 16:33, Jagan Teki wrote:
>>>>>>>
>>>>>>> On Mon, Dec 12, 2022 at 8:52 PM Marek Szyprowski
>>>>>>> <m.szyprowski at samsung.com> wrote:
>>>>>>>
>>>>>>> On 12.12.2022 09:43, Marek Szyprowski wrote:
>>>>>>>
>>>>>>> On 12.12.2022 09:32, Jagan Teki wrote:
>>>>>>>
>>>>>>> On Mon, Dec 12, 2022 at 1:56 PM Marek Szyprowski
>>>>>>> <m.szyprowski at samsung.com> wrote:
>>>>>>>
>>>>>>> Hi Jagan,
>>>>>>>
>>>>>>> On 09.12.2022 16:23, Jagan Teki wrote:
>>>>>>>
>>>>>>> The existing drm panels and bridges in Exynos required host
>>>>>>> initialization during the first DSI command transfer even though
>>>>>>> the initialization was done before.
>>>>>>>
>>>>>>> This host reinitialization is handled via DSIM_STATE_REINITIALIZED
>>>>>>> flag and triggers from host transfer.
>>>>>>>
>>>>>>> Do this exclusively for Exynos.
>>>>>>>
>>>>>>> Initial logic is derived from Marek Szyprowski changes.
>>>>>>>
>>>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>>>>>> Signed-off-by: Jagan Teki <jagan at amarulasolutions.com>
>>>>>>> ---
>>>>>>> Changes from v9:
>>>>>>> - derived from v8
>>>>>>> - added comments
>>>>>>>
>>>>>>> drivers/gpu/drm/bridge/samsung-dsim.c | 15 ++++++++++++++-
>>>>>>> include/drm/bridge/samsung-dsim.h | 5 +++--
>>>>>>> 2 files changed, 17 insertions(+), 3 deletions(-)
>>>>>>>
>>>>>>> The following chunk is missing compared to v8:
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> index 6e9ad955ebd3..6a9403cb92ae 100644
>>>>>>> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> @@ -1315,7 +1315,9 @@ static int samsung_dsim_init(struct samsung_dsim
>>>>>>> *dsi, unsigned int flag)
>>>>>>> return 0;
>>>>>>>
>>>>>>> samsung_dsim_reset(dsi);
>>>>>>> - samsung_dsim_enable_irq(dsi);
>>>>>>> +
>>>>>>> + if (!(dsi->state & DSIM_STATE_INITIALIZED))
>>>>>>> + samsung_dsim_enable_irq(dsi);
>>>>>>>
>>>>>>> Is this really required? does it make sure that the IRQ does not
>>>>>>> enable twice?
>>>>>>>
>>>>>>> That's what that check does. Without the 'if (!(dsi->state &
>>>>>>> DSIM_STATE_INITIALIZED))' check, the irqs will be enabled twice (first
>>>>>>> from pre_enable, then from the first transfer), what leads to a
>>>>>>> warning from irq core.
>>>>>>>
>>>>>>> I've just noticed that we also would need to clear the
>>>>>>> DSIM_STATE_REINITIALIZED flag in dsim_suspend.
>>>>>>>
>>>>>>> However I've found that a bit simpler patch would keep the current code
>>>>>>> flow for Exynos instead of this reinitialization hack. This can be
>>>>>>> applied on the "[PATCH v9 09/18] drm: bridge: samsung-dsim: Add host
>>>>>>> init in pre_enable" patch:
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> index 0b2e52585485..acc95c61ae45 100644
>>>>>>> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>>>>> @@ -1291,9 +1291,11 @@ static void
>>>>>>> samsung_dsim_atomic_pre_enable(struct
>>>>>>> drm_bridge *bridge,
>>>>>>>
>>>>>>> dsi->state |= DSIM_STATE_ENABLED;
>>>>>>>
>>>>>>> - ret = samsung_dsim_init(dsi, DSIM_STATE_INITIALIZED);
>>>>>>> - if (ret)
>>>>>>> - return;
>>>>>>> + if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
>>>>>>> + ret = samsung_dsim_init(dsi, DSIM_STATE_INITIALIZED);
>>>>>>> + if (ret)
>>>>>>> + return;
>>>>>>> + }
>>>>>>>
>>>>>>> Sorry, I don't understand this. Does it mean Exynos doesn't need to
>>>>>>> init host in pre_enable? If I remember correctly even though the host
>>>>>>> is initialized it has to reinitialize during the first transfer - This
>>>>>>> is what the Exynos requirement is. Please correct or explain here.
>>>>>>>
>>>>>>> This is a matter of enabling power regulator(s) in the right order
>>>>>>> and doing the host initialization in the right moment. It was never
>>>>>>> a matter of re-initialization. See the current code for the
>>>>>>> reference (it uses the same approach as my above change). I've
>>>>>>> already explained that here:
>>>>>>>
>>>>>>> https://lore.kernel.org/all/e96197f9-948a-997e-5453-9f9d179b5f5a@samsung.com/
>>>>>>>
>>>>>>>
>>>>>>> If you would like to see the exact proper moment of the dsi host
>>>>>>> initialization on the Exynos see the code here:
>>>>>>>
>>>>>>> https://protect2.fireeye.com/v1/url?k=5dc33900-0258001f-5dc2b24f-000babdfecba-f7c1a2a1905c83ca&q=1&e=f086bfdb-9055-48bd-b9c2-5dffb6c0d558&u=https%3A%2F%2Fgithub.com%2Fmszyprow%2Flinux%2Ftree%2Fv5.18-next-20220511-dsi-rework
>>>>>>> and patches adding mipi_dsi_host_init() to panel/bridge drivers.
>>>>>> As I said before, the downstream bridge needs an explicit call to host
>>>>>> init via mipi_dsi_host_init - this is indeed not a usual use-case
>>>>>> scenario. Let's handle this with a REINIT fix and see if we can update
>>>>>> this later to handle both scenarios.
>>>>>>
>>>>>> Would you please test this repo, I have included all.
>>>>>>
>>>>>> https://gitlab.com/openedev/kernel/-/commits/imx8mm-dsi-v10
>>>>> This doesn't work on TM2e board. Give me some time to find why...
>>>>>
>>>> The following change is missing in "drm: bridge: Generalize Exynos-DSI
>>>> driver into a Samsung DSIM bridge" patch:
>>>>
>>>> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>> b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>> index 1dbff2bee93f..81828b5ee0ac 100644
>>>> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
>>>> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
>>>> @@ -1745,6 +1745,7 @@ int samsung_dsim_probe(struct platform_device *pdev)
>>>> dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
>>>> dsi->bridge.of_node = dev->of_node;
>>>> dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>>>> + dsi->bridge.pre_enable_prev_first = true;
>>> Can you check this and confirm, I keep this in exynos side.
>>> https://gitlab.com/openedev/kernel/-/commit/ccb02df7a313fdf91d8e116b0ec3d6c945fbb6fd#c93f0ce4d81b854fbde970e341fb307f1be78c16_1865_189
>> This one is fine!
>>
>>>> /* DE_LOW: i.MX8M Mini/Nano LCDIF-DSIM glue logic inverts
>>>> HS/VS/DE */
>>>> if (dsi->plat_data->hw_type == DSIM_TYPE_IMX8MM)
>>>>
>>>>
>>>> After adding the above, all my test platform works fine.
>>>>
>>>> BTW, I still think that it is worth replacing the "drm: exynos: dsi: Add
>>>> host initialization in pre_enable" patch with the following simple
>>>> change and propagate it to bridge/samsung-dsim.c:
>>>>
>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> index fdaf514b39f2..071b74d60dcb 100644
>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> @@ -254,6 +254,9 @@ struct exynos_dsi_transfer {
>>>> #define DSIM_STATE_CMD_LPM BIT(2)
>>>> #define DSIM_STATE_VIDOUT_AVAILABLE BIT(3)
>>>>
>>>> +#define exynos_dsi_hw_is_exynos(hw) \
>>>> + ((hw) >= DSIM_TYPE_EXYNOS3250 && (hw) <= DSIM_TYPE_EXYNOS5433)
>>>> +
>>>> enum exynos_dsi_type {
>>>> DSIM_TYPE_EXYNOS3250,
>>>> DSIM_TYPE_EXYNOS4210,
>>>> @@ -1344,6 +1347,9 @@ static int exynos_dsi_init(struct exynos_dsi *dsi)
>>>> {
>>>> const struct exynos_dsi_driver_data *driver_data =
>>>> dsi->driver_data;
>>>>
>>>> + if (dsi->state & DSIM_STATE_INITIALIZED)
>>>> + return 0;
>>>> +
>>>> exynos_dsi_reset(dsi);
>>>> exynos_dsi_enable_irq(dsi);
>>>>
>>>> @@ -1356,6 +1362,8 @@ static int exynos_dsi_init(struct exynos_dsi *dsi)
>>>> exynos_dsi_set_phy_ctrl(dsi);
>>>> exynos_dsi_init_link(dsi);
>>>>
>>>> + dsi->state |= DSIM_STATE_INITIALIZED;
>>>> +
>>>> return 0;
>>>> }
>>>>
>>>> @@ -1411,6 +1419,12 @@ static void exynos_dsi_atomic_pre_enable(struct
>>>> drm_bridge *bridge,
>>>> }
>>>>
>>>> dsi->state |= DSIM_STATE_ENABLED;
>>>> +
>>>> + if (!exynos_dsi_hw_is_exynos(dsi->plat_data->hw_type)) {
>>>> + ret = exynos_dsi_init(dsi);
>>>> + if (ret)
>>>> + return;
>>>> + }
>>>> }
>>>>
>>>> static void exynos_dsi_atomic_enable(struct drm_bridge *bridge,
>>>> @@ -1557,12 +1571,9 @@ static ssize_t exynos_dsi_host_transfer(struct
>>>> mipi_dsi_host *host,
>>>> if (!(dsi->state & DSIM_STATE_ENABLED))
>>>> return -EINVAL;
>>>>
>>>> - if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
>>>> - ret = exynos_dsi_init(dsi);
>>>> - if (ret)
>>>> - return ret;
>>>> - dsi->state |= DSIM_STATE_INITIALIZED;
>>>> - }
>>>> + ret = exynos_dsi_init(dsi);
>>>> + if (ret)
>>>> + return ret;
>>> Below patch handling similar behavior by checking exynos hw_type at
>>> exynos_dsi_init, isn't it? Please check and let me know if I missing
>>> anything.
>>>
>>> https://gitlab.com/openedev/kernel/-/commit/d19d491eef92b92e12a26265697274ce666eddb5
>> You don't miss anything. Your version also works, but I just proposed a
>> bit simpler code.
> Do your changes don't need a DSIM_STATE_REINITIALIZED flag? would you
> please share the change on top of this commit?
> https://gitlab.com/openedev/kernel/-/commit/d19d491eef92b92e12a26265697274ce666eddb5
It doesn't need the DSIM_STATE_REINITIALIZED flag because the
initialization is done only once - in pre_enable for non-Exynos case and
on the first transfer for the Exynos case. In both cases the same flag
(DSIM_STATE_INITIALIZED) is used.
See the attached patch.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
-------------- next part --------------
From ba5fe3c792a2b0c232bc38f52a0b61a89512460f Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski at samsung.com>
Date: Tue, 13 Dec 2022 16:40:13 +0100
Subject: [PATCH] fixup! drm: exynos: dsi: Handle proper host initialization
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
---
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 39 ++++++++-----------------
1 file changed, 12 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 0657f6655bc6..071b74d60dcb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -251,9 +251,8 @@ struct exynos_dsi_transfer {
#define DSIM_STATE_ENABLED BIT(0)
#define DSIM_STATE_INITIALIZED BIT(1)
-#define DSIM_STATE_REINITIALIZED BIT(2)
-#define DSIM_STATE_CMD_LPM BIT(3)
-#define DSIM_STATE_VIDOUT_AVAILABLE BIT(4)
+#define DSIM_STATE_CMD_LPM BIT(2)
+#define DSIM_STATE_VIDOUT_AVAILABLE BIT(3)
#define exynos_dsi_hw_is_exynos(hw) \
((hw) >= DSIM_TYPE_EXYNOS3250 && (hw) <= DSIM_TYPE_EXYNOS5433)
@@ -1344,30 +1343,15 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
disable_irq(dsi->irq);
}
-static int exynos_dsi_init(struct exynos_dsi *dsi, unsigned int flag)
+static int exynos_dsi_init(struct exynos_dsi *dsi)
{
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
- /*
- * FIXME:
- * The existing drm panels and bridges in Exynos required host
- * initialization during the first DSI command transfer even though
- * the initialization was done before.
- *
- * This host reinitialization is handled via DSIM_STATE_REINITIALIZED
- * flag and triggers from host transfer. Do this exclusively for Exynos.
- */
- if (!exynos_dsi_hw_is_exynos(dsi->plat_data->hw_type) &&
- dsi->state & DSIM_STATE_REINITIALIZED)
- return 0;
-
- if (dsi->state & flag)
+ if (dsi->state & DSIM_STATE_INITIALIZED)
return 0;
exynos_dsi_reset(dsi);
-
- if (!(dsi->state & DSIM_STATE_INITIALIZED))
- exynos_dsi_enable_irq(dsi);
+ exynos_dsi_enable_irq(dsi);
if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
@@ -1378,7 +1362,7 @@ static int exynos_dsi_init(struct exynos_dsi *dsi, unsigned int flag)
exynos_dsi_set_phy_ctrl(dsi);
exynos_dsi_init_link(dsi);
- dsi->state |= flag;
+ dsi->state |= DSIM_STATE_INITIALIZED;
return 0;
}
@@ -1436,9 +1420,11 @@ static void exynos_dsi_atomic_pre_enable(struct drm_bridge *bridge,
dsi->state |= DSIM_STATE_ENABLED;
- ret = exynos_dsi_init(dsi, DSIM_STATE_INITIALIZED);
- if (ret)
- return;
+ if (!exynos_dsi_hw_is_exynos(dsi->plat_data->hw_type)) {
+ ret = exynos_dsi_init(dsi);
+ if (ret)
+ return;
+ }
}
static void exynos_dsi_atomic_enable(struct drm_bridge *bridge,
@@ -1585,7 +1571,7 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
if (!(dsi->state & DSIM_STATE_ENABLED))
return -EINVAL;
- ret = exynos_dsi_init(dsi, DSIM_STATE_REINITIALIZED);
+ ret = exynos_dsi_init(dsi);
if (ret)
return ret;
@@ -1791,7 +1777,6 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
if (dsi->state & DSIM_STATE_INITIALIZED) {
dsi->state &= ~DSIM_STATE_INITIALIZED;
- dsi->state &= ~DSIM_STATE_REINITIALIZED;
exynos_dsi_disable_clock(dsi);
--
2.38.1
More information about the dri-devel
mailing list