This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs? Jagan.
Jagan Teki (17): drm/exynos: dsi: Convert to bridge driver drm/exynos: dsi: Handle drm_device for bridge drm/exynos: dsi: Use the drm_panel_bridge API drm/exynos: dsi: Create bridge connector for encoder drm/exynos: dsi: Get the mode from bridge drm/exynos: dsi: Handle exynos specifics via driver_data drm: bridge: Move exynos_drm_dsi into bridges dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge drm: bridge: samsung-dsim: Add module init, exit drm: bridge: samsung-dsim: Update the of_node for port(s) drm: bridge: samsung-dsim: Find the possible DSI devices dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support drm: bridge: samsung-dsim: Add i.MX8MM support drm: bridge: samsung-dsim: Add input_bus_flags drm: bridge: samsung-dsim: Move DSI init in bridge enable drm: bridge: samsung-dsim: Fix PLL_P offset drm: bridge: samsung-dsim: Add bridge mode_fixup
.../display/bridge/samsung,mipi-dsim.yaml | 360 +++++++++ .../bindings/display/exynos/exynos_dsim.txt | 90 --- MAINTAINERS | 12 + drivers/gpu/drm/bridge/Kconfig | 15 + drivers/gpu/drm/bridge/Makefile | 1 + .../samsung-dsim.c} | 758 ++++++++++-------- drivers/gpu/drm/exynos/Kconfig | 9 - drivers/gpu/drm/exynos/Makefile | 1 - 8 files changed, 795 insertions(+), 451 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt rename drivers/gpu/drm/{exynos/exynos_drm_dsi.c => bridge/samsung-dsim.c} (69%)
DRM bridge drivers have built-in handling of treating all display pipeline components as bridges.
Convert exynos_drm_dsi to a bridge driver with built-in encoder support for compatibility with existing component drivers.
This keeps switching the driver into the bridge in a more feasible manner.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 57 +++++++++++++++++-------- 1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 1d777d8c1a83..90d2ce2c3055 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -257,6 +257,7 @@ struct exynos_dsi { struct drm_connector connector; struct drm_panel *panel; struct list_head bridge_chain; + struct drm_bridge bridge; struct drm_bridge *out_bridge; struct device *dev;
@@ -287,9 +288,9 @@ struct exynos_dsi { #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
-static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e) +static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) { - return container_of(e, struct exynos_dsi, encoder); + return container_of(b, struct exynos_dsi, bridge); }
enum reg_idx { @@ -1374,9 +1375,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) } }
-static void exynos_dsi_enable(struct drm_encoder *encoder) +static void exynos_dsi_bridge_enable(struct drm_bridge *bridge) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter; int ret;
@@ -1429,9 +1430,9 @@ static void exynos_dsi_enable(struct drm_encoder *encoder) pm_runtime_put(dsi->dev); }
-static void exynos_dsi_disable(struct drm_encoder *encoder) +static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED)) @@ -1494,9 +1495,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs .get_modes = exynos_dsi_get_modes, };
-static int exynos_dsi_create_connector(struct drm_encoder *encoder) +static int exynos_dsi_create_connector(struct exynos_dsi *dsi) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct drm_encoder *encoder = &dsi->encoder; struct drm_connector *connector = &dsi->connector; struct drm_device *drm = encoder->dev; int ret; @@ -1522,9 +1523,16 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) return 0; }
-static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { - .enable = exynos_dsi_enable, - .disable = exynos_dsi_disable, +static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + return 0; +} + +static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { + .enable = exynos_dsi_bridge_enable, + .disable = exynos_dsi_bridge_disable, + .attach = exynos_dsi_bridge_attach, };
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); @@ -1543,7 +1551,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else { - int ret = exynos_dsi_create_connector(encoder); + int ret = exynos_dsi_create_connector(dsi);
if (ret) { DRM_DEV_ERROR(dsi->dev, @@ -1596,7 +1604,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
if (dsi->panel) { mutex_lock(&drm->mode_config.mutex); - exynos_dsi_disable(&dsi->encoder); + exynos_dsi_bridge_disable(&dsi->bridge); dsi->panel = NULL; dsi->connector.status = connector_status_disconnected; mutex_unlock(&drm->mode_config.mutex); @@ -1702,12 +1710,16 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
- drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); - ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD); if (ret < 0) return ret;
+ ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0); + if (ret) { + drm_encoder_cleanup(&dsi->encoder); + return ret; + } + in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0); if (in_bridge_node) { in_bridge = of_drm_find_bridge(in_bridge_node); @@ -1723,10 +1735,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data) { struct exynos_dsi *dsi = dev_get_drvdata(dev); - struct drm_encoder *encoder = &dsi->encoder; - - exynos_dsi_disable(encoder);
+ exynos_dsi_bridge_disable(&dsi->bridge); + drm_encoder_cleanup(&dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host); }
@@ -1821,6 +1832,12 @@ static int exynos_dsi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
+ dsi->bridge.funcs = &exynos_dsi_bridge_funcs; + dsi->bridge.of_node = dev->of_node; + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; + + drm_bridge_add(&dsi->bridge); + ret = component_add(dev, &exynos_dsi_component_ops); if (ret) goto err_disable_runtime; @@ -1835,6 +1852,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
static int exynos_dsi_remove(struct platform_device *pdev) { + struct exynos_dsi *dsi = platform_get_drvdata(pdev); + + drm_bridge_remove(&dsi->bridge); + pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &exynos_dsi_component_ops);
Hi Jagan,
See a few comments below.
Sam
On Sun, Jul 04, 2021 at 02:32:14PM +0530, Jagan Teki wrote:
DRM bridge drivers have built-in handling of treating all display pipeline components as bridges.
Convert exynos_drm_dsi to a bridge driver with built-in encoder support for compatibility with existing component drivers.
This keeps switching the driver into the bridge in a more feasible manner.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 57 +++++++++++++++++-------- 1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 1d777d8c1a83..90d2ce2c3055 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -257,6 +257,7 @@ struct exynos_dsi { struct drm_connector connector; struct drm_panel *panel; struct list_head bridge_chain;
- struct drm_bridge bridge; struct drm_bridge *out_bridge; struct device *dev;
@@ -287,9 +288,9 @@ struct exynos_dsi { #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
-static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e) +static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) {
- return container_of(e, struct exynos_dsi, encoder);
- return container_of(b, struct exynos_dsi, bridge);
}
enum reg_idx { @@ -1374,9 +1375,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) } }
-static void exynos_dsi_enable(struct drm_encoder *encoder) +static void exynos_dsi_bridge_enable(struct drm_bridge *bridge) {
- struct exynos_dsi *dsi = encoder_to_dsi(encoder);
- struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter; int ret;
@@ -1429,9 +1430,9 @@ static void exynos_dsi_enable(struct drm_encoder *encoder) pm_runtime_put(dsi->dev); }
-static void exynos_dsi_disable(struct drm_encoder *encoder) +static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) {
- struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED))
@@ -1494,9 +1495,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs .get_modes = exynos_dsi_get_modes, };
-static int exynos_dsi_create_connector(struct drm_encoder *encoder) +static int exynos_dsi_create_connector(struct exynos_dsi *dsi) {
- struct exynos_dsi *dsi = encoder_to_dsi(encoder);
- struct drm_encoder *encoder = &dsi->encoder; struct drm_connector *connector = &dsi->connector; struct drm_device *drm = encoder->dev; int ret;
@@ -1522,9 +1523,16 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) return 0; }
-static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
- .enable = exynos_dsi_enable,
- .disable = exynos_dsi_disable,
+static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
+{
- return 0;
+}
+static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
- .enable = exynos_dsi_bridge_enable,
- .disable = exynos_dsi_bridge_disable,
- .attach = exynos_dsi_bridge_attach,
};
For new bridge drivers please use atomic_{enable,disable}. The non-atomic variants are deprecated and it is now also documneted. It was not documented when you wrote this patch!
Sam
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); @@ -1543,7 +1551,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else {
int ret = exynos_dsi_create_connector(encoder);
int ret = exynos_dsi_create_connector(dsi);
if (ret) { DRM_DEV_ERROR(dsi->dev,
@@ -1596,7 +1604,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
if (dsi->panel) { mutex_lock(&drm->mode_config.mutex);
exynos_dsi_disable(&dsi->encoder);
dsi->panel = NULL; dsi->connector.status = connector_status_disconnected; mutex_unlock(&drm->mode_config.mutex);exynos_dsi_bridge_disable(&dsi->bridge);
@@ -1702,12 +1710,16 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
- drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
- ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD); if (ret < 0) return ret;
- ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0);
I assume a later patch will move connector creation to the display driver.
- if (ret) {
drm_encoder_cleanup(&dsi->encoder);
return ret;
- }
- in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0); if (in_bridge_node) { in_bridge = of_drm_find_bridge(in_bridge_node);
@@ -1723,10 +1735,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data) { struct exynos_dsi *dsi = dev_get_drvdata(dev);
- struct drm_encoder *encoder = &dsi->encoder;
- exynos_dsi_disable(encoder);
- exynos_dsi_bridge_disable(&dsi->bridge);
- drm_encoder_cleanup(&dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host);
}
@@ -1821,6 +1832,12 @@ static int exynos_dsi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
- dsi->bridge.funcs = &exynos_dsi_bridge_funcs;
- dsi->bridge.of_node = dev->of_node;
- dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
- drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops); if (ret) goto err_disable_runtime;
@@ -1835,6 +1852,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
static int exynos_dsi_remove(struct platform_device *pdev) {
struct exynos_dsi *dsi = platform_get_drvdata(pdev);
drm_bridge_remove(&dsi->bridge);
pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &exynos_dsi_component_ops);
-- 2.25.1
Now the exynos dsi driver supports bridge and legacy encoder.
In order to support drm_device in both the implementations it is required to preserve the drm_device in a private structure and use it accordingly.
1. encoder case, the bind will assign the drm_device into encoder->dev, so preserve the drm_device in the bind call.
2. bridge case, the drm_bridge_attach will assign the drm_device into bridge->dev, so preserve the drm_device in the bridge_attach function call.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 90d2ce2c3055..d7d60aee465b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -259,6 +259,7 @@ struct exynos_dsi { struct list_head bridge_chain; struct drm_bridge bridge; struct drm_bridge *out_bridge; + struct drm_device *drm; struct device *dev;
void __iomem *reg_base; @@ -1495,11 +1496,11 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs .get_modes = exynos_dsi_get_modes, };
-static int exynos_dsi_create_connector(struct exynos_dsi *dsi) +static int exynos_dsi_create_connector(struct exynos_dsi *dsi, + struct drm_device *drm) { struct drm_encoder *encoder = &dsi->encoder; struct drm_connector *connector = &dsi->connector; - struct drm_device *drm = encoder->dev; int ret;
connector->polled = DRM_CONNECTOR_POLL_HPD; @@ -1526,6 +1527,10 @@ static int exynos_dsi_create_connector(struct exynos_dsi *dsi) static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { + struct exynos_dsi *dsi = bridge_to_dsi(bridge); + + dsi->drm = bridge->dev; + return 0; }
@@ -1542,7 +1547,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, { struct exynos_dsi *dsi = host_to_dsi(host); struct drm_encoder *encoder = &dsi->encoder; - struct drm_device *drm = encoder->dev; + struct drm_device *drm = dsi->drm; struct drm_bridge *out_bridge;
out_bridge = of_drm_find_bridge(device->dev.of_node); @@ -1551,7 +1556,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else { - int ret = exynos_dsi_create_connector(dsi); + int ret = exynos_dsi_create_connector(dsi, drm);
if (ret) { DRM_DEV_ERROR(dsi->dev, @@ -1600,7 +1605,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host); - struct drm_device *drm = dsi->encoder.dev; + struct drm_device *drm = dsi->drm;
if (dsi->panel) { mutex_lock(&drm->mode_config.mutex); @@ -1728,6 +1733,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, of_node_put(in_bridge_node); }
+ dsi->drm = drm_dev; + return mipi_dsi_host_register(&dsi->dsi_host); }
On Sun, Jul 04, 2021 at 02:32:15PM +0530, Jagan Teki wrote:
Now the exynos dsi driver supports bridge and legacy encoder.
In order to support drm_device in both the implementations it is required to preserve the drm_device in a private structure and use it accordingly.
encoder case, the bind will assign the drm_device into encoder->dev, so preserve the drm_device in the bind call.
bridge case, the drm_bridge_attach will assign the drm_device into bridge->dev, so preserve the drm_device in the bridge_attach function call.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
Acked-by: Sam Ravnborg sam@ravnborg.org
Use drm_panel_bridge to replace manual panel and bridge_chain handling code.
This makes the driver simpler to allow all components in the display pipeline to be treated as bridges by cleaning the way to generic connector handling.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 167 ++++-------------------- 1 file changed, 23 insertions(+), 144 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d7d60aee465b..24f0b082ac6d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -254,9 +254,6 @@ struct exynos_dsi_driver_data { struct exynos_dsi { struct drm_encoder encoder; struct mipi_dsi_host dsi_host; - struct drm_connector connector; - struct drm_panel *panel; - struct list_head bridge_chain; struct drm_bridge bridge; struct drm_bridge *out_bridge; struct drm_device *drm; @@ -287,7 +284,6 @@ struct exynos_dsi { };
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) -#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) { @@ -1379,7 +1375,6 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) static void exynos_dsi_bridge_enable(struct drm_bridge *bridge) { struct exynos_dsi *dsi = bridge_to_dsi(bridge); - struct drm_bridge *iter; int ret;
if (dsi->state & DSIM_STATE_ENABLED) @@ -1393,134 +1388,51 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
dsi->state |= DSIM_STATE_ENABLED;
- if (dsi->panel) { - ret = drm_panel_prepare(dsi->panel); - if (ret < 0) - goto err_put_sync; - } else { - list_for_each_entry_reverse(iter, &dsi->bridge_chain, - chain_node) { - if (iter->funcs->pre_enable) - iter->funcs->pre_enable(iter); - } - } - exynos_dsi_set_display_mode(dsi); exynos_dsi_set_display_enable(dsi, true);
- if (dsi->panel) { - ret = drm_panel_enable(dsi->panel); - if (ret < 0) - goto err_display_disable; - } else { - list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { - if (iter->funcs->enable) - iter->funcs->enable(iter); - } - } - dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; return; - -err_display_disable: - exynos_dsi_set_display_enable(dsi, false); - drm_panel_unprepare(dsi->panel); - -err_put_sync: - dsi->state &= ~DSIM_STATE_ENABLED; - pm_runtime_put(dsi->dev); }
static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) { struct exynos_dsi *dsi = bridge_to_dsi(bridge); - struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED)) return;
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
- drm_panel_disable(dsi->panel); - - list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { - if (iter->funcs->disable) - iter->funcs->disable(iter); - } - exynos_dsi_set_display_enable(dsi, false); - drm_panel_unprepare(dsi->panel); - - list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { - if (iter->funcs->post_disable) - iter->funcs->post_disable(iter); - }
dsi->state &= ~DSIM_STATE_ENABLED; pm_runtime_put_sync(dsi->dev); }
-static enum drm_connector_status -exynos_dsi_detect(struct drm_connector *connector, bool force) -{ - return connector->status; -} - -static void exynos_dsi_connector_destroy(struct drm_connector *connector) +static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, + struct device_node *node) { - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - connector->dev = NULL; -} - -static const struct drm_connector_funcs exynos_dsi_connector_funcs = { - .detect = exynos_dsi_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = exynos_dsi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static int exynos_dsi_get_modes(struct drm_connector *connector) -{ - struct exynos_dsi *dsi = connector_to_dsi(connector); - - if (dsi->panel) - return drm_panel_get_modes(dsi->panel, connector); - - return 0; -} + struct drm_bridge *panel_bridge; + struct drm_panel *panel;
-static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { - .get_modes = exynos_dsi_get_modes, -}; + panel_bridge = of_drm_find_bridge(node); + if (!panel_bridge) { + panel = of_drm_find_panel(node); + if (!IS_ERR(panel)) { + panel_bridge = drm_panel_bridge_add(panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + } + }
-static int exynos_dsi_create_connector(struct exynos_dsi *dsi, - struct drm_device *drm) -{ - struct drm_encoder *encoder = &dsi->encoder; - struct drm_connector *connector = &dsi->connector; - int ret; + of_node_put(node);
- connector->polled = DRM_CONNECTOR_POLL_HPD; + dsi->out_bridge = panel_bridge;
- ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs, - DRM_MODE_CONNECTOR_DSI); - if (ret) { - DRM_DEV_ERROR(dsi->dev, - "Failed to initialize connector with drm\n"); - return ret; - } + if (!dsi->out_bridge) + return -EPROBE_DEFER;
- connector->status = connector_status_disconnected; - drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); - drm_connector_attach_encoder(connector, encoder); - if (!drm->registered) - return 0; - - connector->funcs->reset(connector); - drm_connector_register(connector); return 0; }
@@ -1531,7 +1443,8 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
dsi->drm = bridge->dev;
- return 0; + return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge, + flags); }
static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { @@ -1546,32 +1459,12 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host); - struct drm_encoder *encoder = &dsi->encoder; struct drm_device *drm = dsi->drm; - struct drm_bridge *out_bridge; - - out_bridge = of_drm_find_bridge(device->dev.of_node); - if (out_bridge) { - drm_bridge_attach(encoder, out_bridge, NULL, 0); - dsi->out_bridge = out_bridge; - list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); - } else { - int ret = exynos_dsi_create_connector(dsi, drm); - - if (ret) { - DRM_DEV_ERROR(dsi->dev, - "failed to create connector ret = %d\n", - ret); - drm_encoder_cleanup(encoder); - return ret; - } + int ret;
- dsi->panel = of_drm_find_panel(device->dev.of_node); - if (IS_ERR(dsi->panel)) - dsi->panel = NULL; - else - dsi->connector.status = connector_status_connected; - } + ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node); + if (ret) + return ret;
/* * This is a temporary solution and should be made by more generic way. @@ -1607,19 +1500,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, struct exynos_dsi *dsi = host_to_dsi(host); struct drm_device *drm = dsi->drm;
- if (dsi->panel) { - mutex_lock(&drm->mode_config.mutex); - exynos_dsi_bridge_disable(&dsi->bridge); - dsi->panel = NULL; - dsi->connector.status = connector_status_disconnected; - mutex_unlock(&drm->mode_config.mutex); - } else { - if (dsi->out_bridge->funcs->detach) - dsi->out_bridge->funcs->detach(dsi->out_bridge); - dsi->out_bridge = NULL; - INIT_LIST_HEAD(&dsi->bridge_chain); - } - if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
@@ -1770,7 +1650,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) init_completion(&dsi->completed); spin_lock_init(&dsi->transfer_lock); INIT_LIST_HEAD(&dsi->transfer_list); - INIT_LIST_HEAD(&dsi->bridge_chain);
dsi->dsi_host.ops = &exynos_dsi_ops; dsi->dsi_host.dev = dev;
On 04.07.2021 11:02, Jagan Teki wrote:
Use drm_panel_bridge to replace manual panel and bridge_chain handling code.
This makes the driver simpler to allow all components in the display pipeline to be treated as bridges by cleaning the way to generic connector handling.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
This breaks Exysos DSI driver operation (Trats board worked fine with only patches 1-2):
[ 2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0 [ 2.554733] OF: graph: no port node found in /soc/fimd@11c00000 [ 2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations [ 2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops) [ 2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops exynos_dsi_component_ops): -22 [ 2.642263] exynos-drm exynos-drm: master bind failed: -22 [ 2.651017] exynos-drm: probe of exynos-drm failed with error -22
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 167 ++++-------------------- 1 file changed, 23 insertions(+), 144 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d7d60aee465b..24f0b082ac6d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -254,9 +254,6 @@ struct exynos_dsi_driver_data { struct exynos_dsi { struct drm_encoder encoder; struct mipi_dsi_host dsi_host;
- struct drm_connector connector;
- struct drm_panel *panel;
- struct list_head bridge_chain; struct drm_bridge bridge; struct drm_bridge *out_bridge; struct drm_device *drm;
@@ -287,7 +284,6 @@ struct exynos_dsi { };
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) -#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) { @@ -1379,7 +1375,6 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) static void exynos_dsi_bridge_enable(struct drm_bridge *bridge) { struct exynos_dsi *dsi = bridge_to_dsi(bridge);
struct drm_bridge *iter; int ret;
if (dsi->state & DSIM_STATE_ENABLED)
@@ -1393,134 +1388,51 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
dsi->state |= DSIM_STATE_ENABLED;
if (dsi->panel) {
ret = drm_panel_prepare(dsi->panel);
if (ret < 0)
goto err_put_sync;
} else {
list_for_each_entry_reverse(iter, &dsi->bridge_chain,
chain_node) {
if (iter->funcs->pre_enable)
iter->funcs->pre_enable(iter);
}
}
exynos_dsi_set_display_mode(dsi); exynos_dsi_set_display_enable(dsi, true);
if (dsi->panel) {
ret = drm_panel_enable(dsi->panel);
if (ret < 0)
goto err_display_disable;
} else {
list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->enable)
iter->funcs->enable(iter);
}
}
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; return;
-err_display_disable:
- exynos_dsi_set_display_enable(dsi, false);
- drm_panel_unprepare(dsi->panel);
-err_put_sync:
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put(dsi->dev); }
static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) { struct exynos_dsi *dsi = bridge_to_dsi(bridge);
struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED)) return;
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
drm_panel_disable(dsi->panel);
list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->disable)
iter->funcs->disable(iter);
}
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
if (iter->funcs->post_disable)
iter->funcs->post_disable(iter);
}
dsi->state &= ~DSIM_STATE_ENABLED; pm_runtime_put_sync(dsi->dev); }
-static enum drm_connector_status -exynos_dsi_detect(struct drm_connector *connector, bool force) -{
- return connector->status;
-}
-static void exynos_dsi_connector_destroy(struct drm_connector *connector) +static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
{struct device_node *node)
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- connector->dev = NULL;
-}
-static const struct drm_connector_funcs exynos_dsi_connector_funcs = {
- .detect = exynos_dsi_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = exynos_dsi_connector_destroy,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-static int exynos_dsi_get_modes(struct drm_connector *connector) -{
- struct exynos_dsi *dsi = connector_to_dsi(connector);
- if (dsi->panel)
return drm_panel_get_modes(dsi->panel, connector);
- return 0;
-}
- struct drm_bridge *panel_bridge;
- struct drm_panel *panel;
-static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
- .get_modes = exynos_dsi_get_modes,
-};
- panel_bridge = of_drm_find_bridge(node);
- if (!panel_bridge) {
panel = of_drm_find_panel(node);
if (!IS_ERR(panel)) {
panel_bridge = drm_panel_bridge_add(panel);
if (IS_ERR(panel_bridge))
return PTR_ERR(panel_bridge);
}
- }
-static int exynos_dsi_create_connector(struct exynos_dsi *dsi,
struct drm_device *drm)
-{
- struct drm_encoder *encoder = &dsi->encoder;
- struct drm_connector *connector = &dsi->connector;
- int ret;
- of_node_put(node);
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- dsi->out_bridge = panel_bridge;
- ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs,
DRM_MODE_CONNECTOR_DSI);
- if (ret) {
DRM_DEV_ERROR(dsi->dev,
"Failed to initialize connector with drm\n");
return ret;
- }
- if (!dsi->out_bridge)
return -EPROBE_DEFER;
- connector->status = connector_status_disconnected;
- drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
- drm_connector_attach_encoder(connector, encoder);
- if (!drm->registered)
return 0;
- connector->funcs->reset(connector);
- drm_connector_register(connector); return 0; }
@@ -1531,7 +1443,8 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
dsi->drm = bridge->dev;
- return 0;
return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge,
flags);
}
static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
@@ -1546,32 +1459,12 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host);
- struct drm_encoder *encoder = &dsi->encoder; struct drm_device *drm = dsi->drm;
- struct drm_bridge *out_bridge;
- out_bridge = of_drm_find_bridge(device->dev.of_node);
- if (out_bridge) {
drm_bridge_attach(encoder, out_bridge, NULL, 0);
dsi->out_bridge = out_bridge;
list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
- } else {
int ret = exynos_dsi_create_connector(dsi, drm);
if (ret) {
DRM_DEV_ERROR(dsi->dev,
"failed to create connector ret = %d\n",
ret);
drm_encoder_cleanup(encoder);
return ret;
}
- int ret;
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (IS_ERR(dsi->panel))
dsi->panel = NULL;
else
dsi->connector.status = connector_status_connected;
- }
ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node);
if (ret)
return ret;
/*
- This is a temporary solution and should be made by more generic way.
@@ -1607,19 +1500,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, struct exynos_dsi *dsi = host_to_dsi(host); struct drm_device *drm = dsi->drm;
- if (dsi->panel) {
mutex_lock(&drm->mode_config.mutex);
exynos_dsi_bridge_disable(&dsi->bridge);
dsi->panel = NULL;
dsi->connector.status = connector_status_disconnected;
mutex_unlock(&drm->mode_config.mutex);
- } else {
if (dsi->out_bridge->funcs->detach)
dsi->out_bridge->funcs->detach(dsi->out_bridge);
dsi->out_bridge = NULL;
INIT_LIST_HEAD(&dsi->bridge_chain);
- }
- if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
@@ -1770,7 +1650,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) init_completion(&dsi->completed); spin_lock_init(&dsi->transfer_lock); INIT_LIST_HEAD(&dsi->transfer_list);
INIT_LIST_HEAD(&dsi->bridge_chain);
dsi->dsi_host.ops = &exynos_dsi_ops; dsi->dsi_host.dev = dev;
Best regards
On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski m.szyprowski@samsung.com wrote:
On 04.07.2021 11:02, Jagan Teki wrote:
Use drm_panel_bridge to replace manual panel and bridge_chain handling code.
This makes the driver simpler to allow all components in the display pipeline to be treated as bridges by cleaning the way to generic connector handling.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
This breaks Exysos DSI driver operation (Trats board worked fine with only patches 1-2):
[ 2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0 [ 2.554733] OF: graph: no port node found in /soc/fimd@11c00000 [ 2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations [ 2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops) [ 2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops exynos_dsi_component_ops): -22 [ 2.642263] exynos-drm exynos-drm: master bind failed: -22 [ 2.651017] exynos-drm: probe of exynos-drm failed with error -22
Thanks for testing it.
Can you check Squash of 3,4 or 3,4,5 will work or not?
Thanks, Jagan.
On 05.07.2021 14:00, Jagan Teki wrote:
On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski m.szyprowski@samsung.com wrote:
On 04.07.2021 11:02, Jagan Teki wrote:
Use drm_panel_bridge to replace manual panel and bridge_chain handling code.
This makes the driver simpler to allow all components in the display pipeline to be treated as bridges by cleaning the way to generic connector handling.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
This breaks Exysos DSI driver operation (Trats board worked fine with only patches 1-2):
[ 2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0 [ 2.554733] OF: graph: no port node found in /soc/fimd@11c00000 [ 2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations [ 2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops) [ 2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops exynos_dsi_component_ops): -22 [ 2.642263] exynos-drm exynos-drm: master bind failed: -22 [ 2.651017] exynos-drm: probe of exynos-drm failed with error -22
Thanks for testing it.
Can you check Squash of 3,4 or 3,4,5 will work or not?
I've check both sets: 1-4 and 1-5 and none of them works. The result is same as above. If I remember correctly, last time when I played with that code, there was a problem with DRM core calling bridge ops in different order than when they are used by the Exynos DSI driver.
Best regards
On Mon, Jul 5, 2021 at 5:43 PM Marek Szyprowski m.szyprowski@samsung.com wrote:
On 05.07.2021 14:00, Jagan Teki wrote:
On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski m.szyprowski@samsung.com wrote:
On 04.07.2021 11:02, Jagan Teki wrote:
Use drm_panel_bridge to replace manual panel and bridge_chain handling code.
This makes the driver simpler to allow all components in the display pipeline to be treated as bridges by cleaning the way to generic connector handling.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
This breaks Exysos DSI driver operation (Trats board worked fine with only patches 1-2):
[ 2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0 [ 2.554733] OF: graph: no port node found in /soc/fimd@11c00000 [ 2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations [ 2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops) [ 2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops exynos_dsi_component_ops): -22 [ 2.642263] exynos-drm exynos-drm: master bind failed: -22 [ 2.651017] exynos-drm: probe of exynos-drm failed with error -22
Thanks for testing it.
Can you check Squash of 3,4 or 3,4,5 will work or not?
I've check both sets: 1-4 and 1-5 and none of them works. The result is same as above. If I remember correctly, last time when I played with that code, there was a problem with DRM core calling bridge ops in different order than when they are used by the Exynos DSI driver.
Okay. Let me check with sun6i-mipi-dsi as it is component_ops based.
Jagan.
Use drm_bridge_connector_init to create a connector for display pipelines that use drm_bridge for encoder implementation.
This allows splitting connector operations across multiple bridges when necessary, instead of having the last bridge in the chain creating the connector and handling all connector operations internally.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 24f0b082ac6d..d828be07c325 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -24,6 +24,7 @@ #include <video/videomode.h>
#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge_connector.h> #include <drm/drm_bridge.h> #include <drm/drm_fb_helper.h> #include <drm/drm_mipi_dsi.h> @@ -1591,6 +1592,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, struct drm_device *drm_dev = data; struct device_node *in_bridge_node; struct drm_bridge *in_bridge; + struct drm_connector *connector; int ret;
drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS); @@ -1599,12 +1601,22 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, if (ret < 0) return ret;
- ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0); + ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) { drm_encoder_cleanup(&dsi->encoder); return ret; }
+ connector = drm_bridge_connector_init(drm_dev, &dsi->encoder); + if (IS_ERR(connector)) { + DRM_DEV_ERROR(dsi->dev, "Unable to create bridge connector\n"); + drm_encoder_cleanup(&dsi->encoder); + return PTR_ERR(connector); + } + + drm_connector_attach_encoder(connector, &dsi->encoder); + in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0); if (in_bridge_node) { in_bridge = of_drm_find_bridge(in_bridge_node);
Now the exynos dsi driver is fully aware of bridge handling, so get the display mode from bridge, mode_set API instead of legacy encoder crtc.
This makes bridge usage more efficient instead of relying on encoder stack.
Add mode_set in drm_bridge_funcs.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d828be07c325..99a1b8c22313 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -275,6 +275,7 @@ struct exynos_dsi { u32 format;
int state; + struct drm_display_mode mode; struct drm_property *brightness; struct completion completed;
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) { - struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode; + struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; u32 reg;
@@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct exynos_dsi *dsi = bridge_to_dsi(bridge); + + drm_mode_copy(&dsi->mode, adjusted_mode); +} + static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, struct device_node *node) { @@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { .enable = exynos_dsi_bridge_enable, .disable = exynos_dsi_bridge_disable, + .mode_set = exynos_dsi_bridge_mode_set, .attach = exynos_dsi_bridge_attach, };
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:18PM +0530, Jagan Teki wrote:
Now the exynos dsi driver is fully aware of bridge handling, so get the display mode from bridge, mode_set API instead of legacy encoder crtc.
This makes bridge usage more efficient instead of relying on encoder stack.
Add mode_set in drm_bridge_funcs.
Based on your description I had expected to find get_modes implmneted and the flag DRM_BRIDGE_OP_MODES set.
Sam
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d828be07c325..99a1b8c22313 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -275,6 +275,7 @@ struct exynos_dsi { u32 format;
int state;
- struct drm_display_mode mode; struct drm_property *brightness; struct completion completed;
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) {
- struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
- struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; u32 reg;
@@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
+{
- struct exynos_dsi *dsi = bridge_to_dsi(bridge);
- drm_mode_copy(&dsi->mode, adjusted_mode);
+}
static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, struct device_node *node) { @@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { .enable = exynos_dsi_bridge_enable, .disable = exynos_dsi_bridge_disable,
- .mode_set = exynos_dsi_bridge_mode_set, .attach = exynos_dsi_bridge_attach,
};
-- 2.25.1
Hey Jagan,
On Sun, 4 Jul 2021 at 11:04, Jagan Teki jagan@amarulasolutions.com wrote:
Now the exynos dsi driver is fully aware of bridge handling, so get the display mode from bridge, mode_set API instead of legacy encoder crtc.
This makes bridge usage more efficient instead of relying on encoder stack.
Add mode_set in drm_bridge_funcs.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d828be07c325..99a1b8c22313 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -275,6 +275,7 @@ struct exynos_dsi { u32 format;
int state;
struct drm_display_mode mode; struct drm_property *brightness; struct completion completed;
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) {
struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; u32 reg;
@@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
+{
struct exynos_dsi *dsi = bridge_to_dsi(bridge);
drm_mode_copy(&dsi->mode, adjusted_mode);
+}
static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, struct device_node *node) { @@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { .enable = exynos_dsi_bridge_enable, .disable = exynos_dsi_bridge_disable,
.mode_set = exynos_dsi_bridge_mode_set,
As far as I understand it, .enable(), .disable() &.mode_set() are deprecated[1] and should be replaced by atomic_enable(), atomic_disable() & atomic_enable() respectively.
[1] https://lore.kernel.org/dri-devel/20210722062246.2512666-8-sam@ravnborg.org/
.attach = exynos_dsi_bridge_attach,
};
-- 2.25.1
On Thu, Jul 29, 2021 at 03:20:17PM +0200, Robert Foss wrote:
Hey Jagan,
On Sun, 4 Jul 2021 at 11:04, Jagan Teki jagan@amarulasolutions.com wrote:
Now the exynos dsi driver is fully aware of bridge handling, so get the display mode from bridge, mode_set API instead of legacy encoder crtc.
This makes bridge usage more efficient instead of relying on encoder stack.
Add mode_set in drm_bridge_funcs.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d828be07c325..99a1b8c22313 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -275,6 +275,7 @@ struct exynos_dsi { u32 format;
int state;
struct drm_display_mode mode; struct drm_property *brightness; struct completion completed;
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) {
struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; u32 reg;
@@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
+{
struct exynos_dsi *dsi = bridge_to_dsi(bridge);
drm_mode_copy(&dsi->mode, adjusted_mode);
+}
static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, struct device_node *node) { @@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { .enable = exynos_dsi_bridge_enable, .disable = exynos_dsi_bridge_disable,
.mode_set = exynos_dsi_bridge_mode_set,
As far as I understand it, .enable(), .disable() &.mode_set() are deprecated[1] and should be replaced by atomic_enable(), atomic_disable() & atomic_enable() respectively.
[1] https://lore.kernel.org/dri-devel/20210722062246.2512666-8-sam@ravnborg.org/
Correct, we are slowly moving away from the deprecated bridge functions. Need to find time to update my patchset that address some of this.
Sam
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 99a1b8c22313..53d878d4d2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data { unsigned int wait_for_reset; unsigned int num_bits_resol; const unsigned int *reg_values; + bool exynos_specific; };
struct exynos_dsi { @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values, + .exynos_specific = true, };
static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values, + .exynos_specific = true, };
static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values, + .exynos_specific = true, };
static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .wait_for_reset = 0, .num_bits_resol = 12, .reg_values = exynos5433_reg_values, + .exynos_specific = true, };
static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 12, .reg_values = exynos5422_reg_values, + .exynos_specific = true, };
static const struct of_device_id exynos_dsi_of_match[] = { @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, * If attached panel device is for command mode one, dsi should register * TE interrupt handler. */ - if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) { + if (dsi->driver_data->exynos_specific && + !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) { int ret = exynos_dsi_register_te_irq(dsi, &device->dev); if (ret) return ret; @@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags; - exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode = - !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO); + if (dsi->driver_data->exynos_specific) + exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode = + !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
- exynos_dsi_unregister_te_irq(dsi); + if (dsi->driver_data->exynos_specific) + exynos_dsi_unregister_te_irq(dsi);
return 0; } @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) return ret;
+ if (!dsi->driver_data->exynos_specific) { + ret = mipi_dsi_host_register(&dsi->dsi_host); + if (ret) { + dev_err(dev, "failed to register mipi dsi host: %d\n", + ret); + return ret; + } + } + platform_set_drvdata(pdev, dsi);
pm_runtime_enable(dev); @@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops); - if (ret) - goto err_disable_runtime; + if (dsi->driver_data->exynos_specific) { + ret = component_add(dev, &exynos_dsi_component_ops); + if (ret) + goto err_disable_runtime; + }
return 0;
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &exynos_dsi_component_ops); + if (dsi->driver_data->exynos_specific) + component_del(&pdev->dev, &exynos_dsi_component_ops);
return 0; }
On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
We really should find someone that has the time, energy, knowledge and hardware that can include device_link support once anf for all for bridges. Then we would avoid hacks like this.
I see no other options at the moment, but look forward for a better solution.
Sam
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 99a1b8c22313..53d878d4d2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data { unsigned int wait_for_reset; unsigned int num_bits_resol; const unsigned int *reg_values;
- bool exynos_specific;
};
struct exynos_dsi { @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .wait_for_reset = 0, .num_bits_resol = 12, .reg_values = exynos5433_reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 12, .reg_values = exynos5422_reg_values,
- .exynos_specific = true,
};
static const struct of_device_id exynos_dsi_of_match[] = { @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, * If attached panel device is for command mode one, dsi should register * TE interrupt handler. */
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
- if (dsi->driver_data->exynos_specific &&
int ret = exynos_dsi_register_te_irq(dsi, &device->dev); if (ret) return ret;!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
@@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags;
- exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
if (dsi->driver_data->exynos_specific)
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
- exynos_dsi_unregister_te_irq(dsi);
if (dsi->driver_data->exynos_specific)
exynos_dsi_unregister_te_irq(dsi);
return 0;
} @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) return ret;
if (!dsi->driver_data->exynos_specific) {
ret = mipi_dsi_host_register(&dsi->dsi_host);
if (ret) {
dev_err(dev, "failed to register mipi dsi host: %d\n",
ret);
return ret;
}
}
platform_set_drvdata(pdev, dsi);
pm_runtime_enable(dev);
@@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops);
- if (ret)
goto err_disable_runtime;
if (dsi->driver_data->exynos_specific) {
ret = component_add(dev, &exynos_dsi_component_ops);
if (ret)
goto err_disable_runtime;
}
return 0;
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &exynos_dsi_component_ops);
if (dsi->driver_data->exynos_specific)
component_del(&pdev->dev, &exynos_dsi_component_ops);
return 0;
}
2.25.1
On Sun, Jul 25, 2021 at 10:55 PM Sam Ravnborg sam@ravnborg.org wrote:
On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
We really should find someone that has the time, energy, knowledge and hardware that can include device_link support once anf for all for bridges. Then we would avoid hacks like this.
I see no other options at the moment, but look forward for a better solution.
The real key problem here is hardware, unfortunately I'm unable to find any proper exynos DSI hardware for myself to proceed atleast.
Thanks, Jagan.
Hi,
21. 7. 26. 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
We really should find someone that has the time, energy, knowledge and hardware that can include device_link support once anf for all for bridges. Then we would avoid hacks like this.
I see no other options at the moment, but look forward for a better solution.
Sam
I'm not sure that it's correct to share this mipi dsi driver with I.MX8MM SoC even though it's a same IP because this MIPI DSI device isn't peripheral device but in SoC. It would mean that Exynos MIPI DSI device depends on SoC architecture, and Exynos and I.MX series are totally different SoC. So if we share the same driver for the MIPI DSI device then many things we didn't predict may happen in the future. I don't want to make Jagan's efforts in vain for the community but clarify whether this is correct way or not. If this is only the way we have to go then we could more focus on actual solution not such hack. Impossible work with Jagan alone I think.
So let's get started with a question, - Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI is a Encoder device managed by atomic KMS. If MIPI-DSI should be handled as bridge device then does now drm bridge framework provide everything to share one driver with one more SoC? I mean something that drm bridge has to consider for such driver support, which is shared with one more SoC.
And Display mode - VIDEO and COMMAND mode - is generic type of MIPI DSI, and also componentised subsystem is a generic solution to resolve probing order issue not Exynos specific feature. These are driver specific ones not Exynos SoC I think. As SoC specific things should be considered, I think MIPI DSI Driver - interrupt handler and probing order things are really specific to device driver - should be separated but we could share the control part of the device.
I was busy with other projects so didn't care of Linux DRM world so there may be my missing something.
Thanks, Inki Dae
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 99a1b8c22313..53d878d4d2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data { unsigned int wait_for_reset; unsigned int num_bits_resol; const unsigned int *reg_values;
- bool exynos_specific;
};
struct exynos_dsi { @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .wait_for_reset = 0, .num_bits_resol = 12, .reg_values = exynos5433_reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 12, .reg_values = exynos5422_reg_values,
- .exynos_specific = true,
};
static const struct of_device_id exynos_dsi_of_match[] = { @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, * If attached panel device is for command mode one, dsi should register * TE interrupt handler. */
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
- if (dsi->driver_data->exynos_specific &&
int ret = exynos_dsi_register_te_irq(dsi, &device->dev); if (ret) return ret;!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
@@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags;
- exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
if (dsi->driver_data->exynos_specific)
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
- exynos_dsi_unregister_te_irq(dsi);
if (dsi->driver_data->exynos_specific)
exynos_dsi_unregister_te_irq(dsi);
return 0;
} @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) return ret;
if (!dsi->driver_data->exynos_specific) {
ret = mipi_dsi_host_register(&dsi->dsi_host);
if (ret) {
dev_err(dev, "failed to register mipi dsi host: %d\n",
ret);
return ret;
}
}
platform_set_drvdata(pdev, dsi);
pm_runtime_enable(dev);
@@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops);
- if (ret)
goto err_disable_runtime;
if (dsi->driver_data->exynos_specific) {
ret = component_add(dev, &exynos_dsi_component_ops);
if (ret)
goto err_disable_runtime;
}
return 0;
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &exynos_dsi_component_ops);
if (dsi->driver_data->exynos_specific)
component_del(&pdev->dev, &exynos_dsi_component_ops);
return 0;
}
2.25.1
Hi Inki,
On Fri, Aug 13, 2021 at 03:50:56PM +0900, Inki Dae wrote:
- 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
We really should find someone that has the time, energy, knowledge and hardware that can include device_link support once anf for all for bridges. Then we would avoid hacks like this.
I see no other options at the moment, but look forward for a better solution.
I'm not sure that it's correct to share this mipi dsi driver with I.MX8MM SoC even though it's a same IP because this MIPI DSI device isn't peripheral device but in SoC.
It would mean that Exynos MIPI DSI device depends on SoC architecture, and Exynos and I.MX series are totally different SoC. So if we share the same driver for the MIPI DSI device then many things we didn't predict may happen in the future.
Isn't that true for external components true thought ? Any driver shared by multiple systems will face this issue, where it will be developed with some use cases in mind, and regressions may happen when the driver is then extended to support other use cases not required for the original platform.
In general we don't want multiple drivers for the same IP core unless there are valid technical reasons for that. It's the whole point of the device tree, being able to describe how IP cores are integrated, so that code can be reused across platforms. Of course, integration differences between SoCs can sometimes vary wildly and require some amount of glue code.
I don't want to make Jagan's efforts in vain for the community but clarify whether this is correct way or not. If this is only the way we have to go then we could more focus on actual solution not such hack. Impossible work with Jagan alone I think.
I do agree that we need more correct solutions and less hacks in general :-) The issues faced on Exynos also exist on other platforms, so it would be much better to solve them well once that duplicating implementations with less test coverage and reviews. There have been efforts in the past to address some of these issues, which have resulted in solutions such as the component framework. However, I'd argued that we've never taken it to the last step, and have always stopped with half solutions. The component framework, for instance, is painful to use, and the handling of .remove() in most drivers is completely broken because of that (not just because of that though, we have issues in the DRM core that make hot-unplug just impossible to handle safetly).
So let's get started with a question,
- Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI
is a Encoder device managed by atomic KMS. If MIPI-DSI should be handled as bridge device then does now drm bridge framework provide everything to share one driver with one more SoC? I mean something that drm bridge has to consider for such driver support, which is shared with one more SoC.
The DRM "encoder" concept was a bit of a historical mistake that we are stuck with as drm_encoder is exposed to userspace. It comes from a time where nobody was envisioning chaining multiple encoders. DRM is moving to modelling every component after the CRTC as a bridge. This brings much more flexibility, and in that model, the drm_encoder becomes more or less a stub.
The DRM bridge API has been extended in the past to support more features, and if anything is still missing that makes it difficult to move away from drm_encoder, we can of course address the issues in drm_bridge.
And Display mode - VIDEO and COMMAND mode - is generic type of MIPI DSI, and also componentised subsystem is a generic solution to resolve probing order issue not Exynos specific feature. These are driver specific ones not Exynos SoC I think. As SoC specific things should be considered, I think MIPI DSI Driver - interrupt handler and probing order things are really specific to device driver - should be separated but we could share the control part of the device.
I was busy with other projects so didn't care of Linux DRM world so there may be my missing something.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 99a1b8c22313..53d878d4d2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data { unsigned int wait_for_reset; unsigned int num_bits_resol; const unsigned int *reg_values;
- bool exynos_specific;
};
struct exynos_dsi { @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .wait_for_reset = 0, .num_bits_resol = 12, .reg_values = exynos5433_reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 12, .reg_values = exynos5422_reg_values,
- .exynos_specific = true,
};
static const struct of_device_id exynos_dsi_of_match[] = { @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, * If attached panel device is for command mode one, dsi should register * TE interrupt handler. */
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
- if (dsi->driver_data->exynos_specific &&
int ret = exynos_dsi_register_te_irq(dsi, &device->dev); if (ret) return ret;!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
@@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags;
- exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
if (dsi->driver_data->exynos_specific)
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
- exynos_dsi_unregister_te_irq(dsi);
if (dsi->driver_data->exynos_specific)
exynos_dsi_unregister_te_irq(dsi);
return 0;
} @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) return ret;
if (!dsi->driver_data->exynos_specific) {
ret = mipi_dsi_host_register(&dsi->dsi_host);
if (ret) {
dev_err(dev, "failed to register mipi dsi host: %d\n",
ret);
return ret;
}
}
platform_set_drvdata(pdev, dsi);
pm_runtime_enable(dev);
@@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops);
- if (ret)
goto err_disable_runtime;
if (dsi->driver_data->exynos_specific) {
ret = component_add(dev, &exynos_dsi_component_ops);
if (ret)
goto err_disable_runtime;
}
return 0;
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &exynos_dsi_component_ops);
if (dsi->driver_data->exynos_specific)
component_del(&pdev->dev, &exynos_dsi_component_ops);
return 0;
}
Hi Laurent,
21. 8. 13. 오후 9:16에 Laurent Pinchart 이(가) 쓴 글:
Hi Inki,
On Fri, Aug 13, 2021 at 03:50:56PM +0900, Inki Dae wrote:
- 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
Exynos DSI driver is actually a Samsung MIPI DSIM bridge IP which is also used in i.MX8MM platforms.
Right now the existing driver has some exynos drm specific code bases like te_irq, crtc and component_ops.
In order to switch this driver into a common bridge driver We can see 2 options to handle the exynos specific code.
A. Drop the component_ops, and rework other specifics. This may lead to more foundation work as it requires more changes in exynos drm drivers stack.
B. Handle the exynos specifics via driver data, and make the common bridge work in different platforms and plan for option A in future.
So, this patch is trying to add option B) changes to handle exynos specifics via driver_data.
We really should find someone that has the time, energy, knowledge and hardware that can include device_link support once anf for all for bridges. Then we would avoid hacks like this.
I see no other options at the moment, but look forward for a better solution.
I'm not sure that it's correct to share this mipi dsi driver with I.MX8MM SoC even though it's a same IP because this MIPI DSI device isn't peripheral device but in SoC.
It would mean that Exynos MIPI DSI device depends on SoC architecture, and Exynos and I.MX series are totally different SoC. So if we share the same driver for the MIPI DSI device then many things we didn't predict may happen in the future.
Isn't that true for external components true thought ? Any driver shared by multiple systems will face this issue, where it will be developed with some use cases in mind, and regressions may happen when the driver is then extended to support other use cases not required for the original platform.
In general we don't want multiple drivers for the same IP core unless there are valid technical reasons for that. It's the whole point of the device tree, being able to describe how IP cores are integrated, so that code can be reused across platforms. Of course, integration differences between SoCs can sometimes vary wildly and require some amount of glue code.
Agree with you. It would be a good chance to clarify what we need to share same device driver without any regress in this time.
I don't want to make Jagan's efforts in vain for the community but clarify whether this is correct way or not. If this is only the way we have to go then we could more focus on actual solution not such hack. Impossible work with Jagan alone I think.
I do agree that we need more correct solutions and less hacks in general :-) The issues faced on Exynos also exist on other platforms, so it would be much better to solve them well once that duplicating implementations with less test coverage and reviews. There have been efforts in the past to address some of these issues, which have resulted in solutions such as the component framework. However, I'd argued that
Yeah, most of ARM systems have various separate devices but DRM subsytem wanted each ARM driver to work like one device driver for all of them. And the component framework has been adopted by several ARM DRM drivers for it including Exynos.
we've never taken it to the last step, and have always stopped with half solutions. The component framework, for instance, is painful to use, and the handling of .remove() in most drivers is completely broken because of that (not just because of that though, we have issues in the DRM core that make hot-unplug just impossible to handle safetly).
This may be one of what we have to clarify. I think ARM DRM drivers need component framework or similar thing to address probing order issue. So would we need to enhance existing compoent framework to be suitable for DRM subsystem, or introducing an alternative solution?
Otherwise, would there be some way to address the probing order issue without the compoment framework?
So let's get started with a question,
- Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI
is a Encoder device managed by atomic KMS. If MIPI-DSI should be handled as bridge device then does now drm bridge framework provide everything to share one driver with one more SoC? I mean something that drm bridge has to consider for such driver support, which is shared with one more SoC.
The DRM "encoder" concept was a bit of a historical mistake that we are stuck with as drm_encoder is exposed to userspace. It comes from a time where nobody was envisioning chaining multiple encoders. DRM is moving to modelling every component after the CRTC as a bridge. This brings
Thanks for explanation and seems correct direction. :) However, there would be something we have to address before changing the existing modeling because any regress shouldn't be allowed.
Thanks, Inki Dae
much more flexibility, and in that model, the drm_encoder becomes more or less a stub.
The DRM bridge API has been extended in the past to support more features, and if anything is still missing that makes it difficult to move away from drm_encoder, we can of course address the issues in drm_bridge.
And Display mode - VIDEO and COMMAND mode - is generic type of MIPI DSI, and also componentised subsystem is a generic solution to resolve probing order issue not Exynos specific feature. These are driver specific ones not Exynos SoC I think. As SoC specific things should be considered, I think MIPI DSI Driver - interrupt handler and probing order things are really specific to device driver - should be separated but we could share the control part of the device.
I was busy with other projects so didn't care of Linux DRM world so there may be my missing something.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 99a1b8c22313..53d878d4d2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data { unsigned int wait_for_reset; unsigned int num_bits_resol; const unsigned int *reg_values;
- bool exynos_specific;
};
struct exynos_dsi { @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 11, .reg_values = reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .wait_for_reset = 0, .num_bits_resol = 12, .reg_values = exynos5433_reg_values,
- .exynos_specific = true,
};
static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .wait_for_reset = 1, .num_bits_resol = 12, .reg_values = exynos5422_reg_values,
- .exynos_specific = true,
};
static const struct of_device_id exynos_dsi_of_match[] = { @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, * If attached panel device is for command mode one, dsi should register * TE interrupt handler. */
- if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
- if (dsi->driver_data->exynos_specific &&
int ret = exynos_dsi_register_te_irq(dsi, &device->dev); if (ret) return ret;!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
@@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags;
- exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
if (dsi->driver_data->exynos_specific)
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
- exynos_dsi_unregister_te_irq(dsi);
if (dsi->driver_data->exynos_specific)
exynos_dsi_unregister_te_irq(dsi);
return 0;
} @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) return ret;
if (!dsi->driver_data->exynos_specific) {
ret = mipi_dsi_host_register(&dsi->dsi_host);
if (ret) {
dev_err(dev, "failed to register mipi dsi host: %d\n",
ret);
return ret;
}
}
platform_set_drvdata(pdev, dsi);
pm_runtime_enable(dev);
@@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
drm_bridge_add(&dsi->bridge);
- ret = component_add(dev, &exynos_dsi_component_ops);
- if (ret)
goto err_disable_runtime;
if (dsi->driver_data->exynos_specific) {
ret = component_add(dev, &exynos_dsi_component_ops);
if (ret)
goto err_disable_runtime;
}
return 0;
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- component_del(&pdev->dev, &exynos_dsi_component_ops);
if (dsi->driver_data->exynos_specific)
component_del(&pdev->dev, &exynos_dsi_component_ops);
return 0;
}
The MIPI DSI IP used in Exynos and i.MX8MM are based Samsung MIPI DSIM bridge. In order to access the common bridge between platforms the ideal way to push the driver into the bridge area. So, this patch will move the exynos_drm_dsi.c driver into samsung-dsim.c and do the necessary function name changes. This would help to improve the bridge driver in future patches in order to make use of different SoC families and platforms.
The bridge now support two implementations,
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use.
Updated MAINTAINERS file for this bridge with exynos drm maintainers along with Andrzej as he is the original author.
Tomasz Figa has been not included in MAINTAINERS as he is not available via samsung.com.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- MAINTAINERS | 11 + drivers/gpu/drm/bridge/Kconfig | 15 + drivers/gpu/drm/bridge/Makefile | 1 + .../samsung-dsim.c} | 433 +++++++++--------- drivers/gpu/drm/exynos/Kconfig | 9 - drivers/gpu/drm/exynos/Makefile | 1 - 6 files changed, 246 insertions(+), 224 deletions(-) rename drivers/gpu/drm/{exynos/exynos_drm_dsi.c => bridge/samsung-dsim.c} (77%)
diff --git a/MAINTAINERS b/MAINTAINERS index cae0c6148590..733c2ebc0393 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5864,6 +5864,17 @@ T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml F: drivers/gpu/drm/panel/panel-samsung-db7430.c
+DRM DRIVER FOR SAMSUNG MIPI DSIM BRIDGE +M: Inki Dae inki.dae@samsung.com +M: Joonyoung Shim jy0922.shim@samsung.com +M: Seung-Woo Kim sw0312.kim@samsung.com +M: Kyungmin Park kyungmin.park@samsung.com +M: Andrzej Hajda a.hajda@samsung.com +M: Jagan Teki jagan@amarulasolutions.com +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/bridge/samsung-dsim.c + DRM DRIVER FOR SITRONIX ST7703 PANELS M: Guido Günther agx@sigxcpu.org R: Purism Kernel Team kernel@puri.sm diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 4de6dbb8821b..c8a3b13f730b 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -190,6 +190,21 @@ config DRM_PARADE_PS8640 The PS8640 is a high-performance and low-power MIPI DSI to eDP converter
+config DRM_SAMSUNG_DSIM + tristate "Samsung MIPI DSIM bridge driver" + depends on DRM + depends on COMMON_CLK + depends on OF && HAS_IOMEM + depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_PANEL_BRIDGE + select REGMAP_MMIO + help + This enables the Samsung MIPI DSIM bridge controller driver. + This MIPI DSIM bridge can be found it on Exynos and NXP's + i.MX8M Mini and Nano SoC's. + config DRM_SIL_SII8620 tristate "Silicon Image SII8620 HDMI/MHL bridge" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index ec2b9fa2699e..1eb04e4857e5 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o +obj-$(CONFIG_DRM_SAMSUNG_DSIM) += samsung-dsim.o obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o obj-$(CONFIG_DRM_SII902X) += sii902x.o obj-$(CONFIG_DRM_SII9234) += sii9234.o diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/bridge/samsung-dsim.c similarity index 77% rename from drivers/gpu/drm/exynos/exynos_drm_dsi.c rename to drivers/gpu/drm/bridge/samsung-dsim.c index 53d878d4d2d7..eed6b3ffdea7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Samsung SoC MIPI DSI Master driver. + * Samsung MIPI DSIM bridge driver. * + * Copyright (C) 2021 Amarula Solutions(India) * Copyright (c) 2014 Samsung Electronics Co., Ltd * - * Contacts: Tomasz Figa t.figa@samsung.com -*/ + * TODO: + * - Move or handle exynos specifics in exynos drm drivers stack. + * - Try to drop component_ops, but it indeed require to change + * exynos drm drivers stack. + */
#include <linux/clk.h> #include <linux/delay.h> @@ -33,8 +37,8 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h>
-#include "exynos_drm_crtc.h" -#include "exynos_drm_drv.h" +#include "../exynos/exynos_drm_crtc.h" +#include "../exynos/exynos_drm_drv.h"
/* returns true iff both arguments logically differs */ #define NEQV(a, b) (!(a) ^ !(b)) @@ -217,12 +221,12 @@ static const char *const clk_names[5] = { "bus_clk", "sclk_mipi", "phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0", "sclk_rgb_vclk_to_dsim0" };
-enum exynos_dsi_transfer_type { +enum samsung_dsim_transfer_type { EXYNOS_DSI_TX, EXYNOS_DSI_RX, };
-struct exynos_dsi_transfer { +struct samsung_dsim_transfer { struct list_head list; struct completion completed; int result; @@ -240,7 +244,7 @@ struct exynos_dsi_transfer { #define DSIM_STATE_CMD_LPM BIT(2) #define DSIM_STATE_VIDOUT_AVAILABLE BIT(3)
-struct exynos_dsi_driver_data { +struct samsung_dsim_driver_data { const unsigned int *reg_ofs; unsigned int plltmr_reg; unsigned int has_freqband:1; @@ -253,7 +257,7 @@ struct exynos_dsi_driver_data { bool exynos_specific; };
-struct exynos_dsi { +struct samsung_dsim { struct drm_encoder encoder; struct mipi_dsi_host dsi_host; struct drm_bridge bridge; @@ -283,14 +287,14 @@ struct exynos_dsi { spinlock_t transfer_lock; /* protects transfer_list */ struct list_head transfer_list;
- const struct exynos_dsi_driver_data *driver_data; + const struct samsung_dsim_driver_data *driver_data; };
-#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) +#define host_to_dsi(host) container_of(host, struct samsung_dsim, dsi_host)
-static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) +static inline struct samsung_dsim *bridge_to_dsi(struct drm_bridge *b) { - return container_of(b, struct exynos_dsi, bridge); + return container_of(b, struct samsung_dsim, bridge); }
enum reg_idx { @@ -318,14 +322,14 @@ enum reg_idx { NUM_REGS };
-static inline void exynos_dsi_write(struct exynos_dsi *dsi, enum reg_idx idx, - u32 val) +static inline void samsung_dsim_write(struct samsung_dsim *dsi, enum reg_idx idx, + u32 val) {
writel(val, dsi->reg_base + dsi->driver_data->reg_ofs[idx]); }
-static inline u32 exynos_dsi_read(struct exynos_dsi *dsi, enum reg_idx idx) +static inline u32 samsung_dsim_read(struct samsung_dsim *dsi, enum reg_idx idx) { return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]); } @@ -450,7 +454,7 @@ static const unsigned int exynos5433_reg_values[] = { [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c), };
-static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { +static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x50, .has_freqband = 1, @@ -463,7 +467,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .exynos_specific = true, };
-static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { +static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x50, .has_freqband = 1, @@ -476,7 +480,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .exynos_specific = true, };
-static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { +static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x58, .num_clks = 2, @@ -487,7 +491,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .exynos_specific = true, };
-static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { +static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = { .reg_ofs = exynos5433_reg_ofs, .plltmr_reg = 0xa0, .has_clklane_stop = 1, @@ -499,7 +503,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .exynos_specific = true, };
-static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { +static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = { .reg_ofs = exynos5433_reg_ofs, .plltmr_reg = 0xa0, .has_clklane_stop = 1, @@ -511,7 +515,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { .exynos_specific = true, };
-static const struct of_device_id exynos_dsi_of_match[] = { +static const struct of_device_id samsung_dsim_of_match[] = { { .compatible = "samsung,exynos3250-mipi-dsi", .data = &exynos3_dsi_driver_data }, { .compatible = "samsung,exynos4210-mipi-dsi", @@ -525,7 +529,7 @@ static const struct of_device_id exynos_dsi_of_match[] = { { } };
-static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) +static void samsung_dsim_wait_for_reset(struct samsung_dsim *dsi) { if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300))) return; @@ -533,22 +537,22 @@ static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) dev_err(dsi->dev, "timeout waiting for reset\n"); }
-static void exynos_dsi_reset(struct exynos_dsi *dsi) +static void samsung_dsim_reset(struct samsung_dsim *dsi) { u32 reset_val = dsi->driver_data->reg_values[RESET_TYPE];
reinit_completion(&dsi->completed); - exynos_dsi_write(dsi, DSIM_SWRST_REG, reset_val); + samsung_dsim_write(dsi, DSIM_SWRST_REG, reset_val); }
#ifndef MHZ #define MHZ (1000*1000) #endif
-static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, +static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi, unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s) { - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; unsigned long best_freq = 0; u32 min_delta = 0xffffffff; u8 p_min, p_max; @@ -599,10 +603,10 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, return best_freq; }
-static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, - unsigned long freq) +static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi, + unsigned long freq) { - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; unsigned long fin, fout; int timeout; u8 p, s; @@ -610,7 +614,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, u32 reg;
fin = dsi->pll_clk_rate; - fout = exynos_dsi_pll_find_pms(dsi, fin, freq, &p, &m, &s); + fout = samsung_dsim_pll_find_pms(dsi, fin, freq, &p, &m, &s); if (!fout) { dev_err(dsi->dev, "failed to find PLL PMS for requested frequency\n"); @@ -641,7 +645,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, reg |= DSIM_FREQ_BAND(band); }
- exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
timeout = 1000; do { @@ -649,19 +653,19 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, dev_err(dsi->dev, "PLL failed to stabilize\n"); return 0; } - reg = exynos_dsi_read(dsi, DSIM_STATUS_REG); + reg = samsung_dsim_read(dsi, DSIM_STATUS_REG); } while ((reg & DSIM_PLL_STABLE) == 0);
return fout; }
-static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) +static int samsung_dsim_enable_clock(struct samsung_dsim *dsi) { unsigned long hs_clk, byte_clk, esc_clk; unsigned long esc_div; u32 reg;
- hs_clk = exynos_dsi_set_pll(dsi, dsi->burst_clk_rate); + hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate); if (!hs_clk) { dev_err(dsi->dev, "failed to configure DSI PLL\n"); return -EFAULT; @@ -679,7 +683,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu, esc_clk = %lu\n", hs_clk, byte_clk, esc_clk);
- reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG); + reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG); reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS | DSIM_BYTE_CLK_SRC_MASK); @@ -689,14 +693,14 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) | DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1) | DSIM_BYTE_CLK_SRC(0) | DSIM_TX_REQUEST_HSCLK; - exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
return 0; }
-static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) +static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi) { - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; const unsigned int *reg_values = driver_data->reg_values; u32 reg;
@@ -706,7 +710,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) /* B D-PHY: D-PHY Master & Slave Analog Block control */ reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] | reg_values[PHYCTRL_SLEW_UP]; - exynos_dsi_write(dsi, DSIM_PHYCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
/* * T LPX: Transmitted length of any Low-Power state period @@ -714,7 +718,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) * burst */ reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT]; - exynos_dsi_write(dsi, DSIM_PHYTIMING_REG, reg); + samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
/* * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00 @@ -734,7 +738,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) reg_values[PHYTIMING_CLK_POST] | reg_values[PHYTIMING_CLK_TRAIL];
- exynos_dsi_write(dsi, DSIM_PHYTIMING1_REG, reg); + samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
/* * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00 @@ -747,47 +751,47 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) */ reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] | reg_values[PHYTIMING_HS_TRAIL]; - exynos_dsi_write(dsi, DSIM_PHYTIMING2_REG, reg); + samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg); }
-static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) +static void samsung_dsim_disable_clock(struct samsung_dsim *dsi) { u32 reg;
- reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG); + reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG); reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN); - exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
- reg = exynos_dsi_read(dsi, DSIM_PLLCTRL_REG); + reg = samsung_dsim_read(dsi, DSIM_PLLCTRL_REG); reg &= ~DSIM_PLL_EN; - exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg); }
-static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane) +static void samsung_dsim_enable_lane(struct samsung_dsim *dsi, u32 lane) { - u32 reg = exynos_dsi_read(dsi, DSIM_CONFIG_REG); + u32 reg = samsung_dsim_read(dsi, DSIM_CONFIG_REG); reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) | DSIM_LANE_EN_CLK | DSIM_LANE_EN(lane)); - exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg); + samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg); }
-static int exynos_dsi_init_link(struct exynos_dsi *dsi) +static int samsung_dsim_init_link(struct samsung_dsim *dsi) { - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; int timeout; u32 reg; u32 lanes_mask;
/* Initialize FIFO pointers */ - reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG); + reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG); reg &= ~0x1f; - exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg);
usleep_range(9000, 11000);
reg |= 0x1f; - exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg); + samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg); usleep_range(9000, 11000);
/* DSI configuration */ @@ -856,10 +860,10 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { reg |= DSIM_CLKLANE_STOP; } - exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg); + samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
lanes_mask = BIT(dsi->lanes) - 1; - exynos_dsi_enable_lane(dsi, lanes_mask); + samsung_dsim_enable_lane(dsi, lanes_mask);
/* Check clock and data lane state are stop state */ timeout = 100; @@ -869,24 +873,24 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) return -EFAULT; }
- reg = exynos_dsi_read(dsi, DSIM_STATUS_REG); + reg = samsung_dsim_read(dsi, DSIM_STATUS_REG); if ((reg & DSIM_STOP_STATE_DAT(lanes_mask)) != DSIM_STOP_STATE_DAT(lanes_mask)) continue; } while (!(reg & (DSIM_STOP_STATE_CLK | DSIM_TX_READY_HS_CLK)));
- reg = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); + reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); reg &= ~DSIM_STOP_STATE_CNT_MASK; reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]); - exynos_dsi_write(dsi, DSIM_ESCMODE_REG, reg); + samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff); - exynos_dsi_write(dsi, DSIM_TIMEOUT_REG, reg); + samsung_dsim_write(dsi, DSIM_TIMEOUT_REG, reg);
return 0; }
-static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) +static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi) { struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; @@ -896,42 +900,42 @@ static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) reg = DSIM_CMD_ALLOW(0xf) | DSIM_STABLE_VFP(m->vsync_start - m->vdisplay) | DSIM_MAIN_VBP(m->vtotal - m->vsync_end); - exynos_dsi_write(dsi, DSIM_MVPORCH_REG, reg); + samsung_dsim_write(dsi, DSIM_MVPORCH_REG, reg);
reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay) | DSIM_MAIN_HBP(m->htotal - m->hsync_end); - exynos_dsi_write(dsi, DSIM_MHPORCH_REG, reg); + samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start) | DSIM_MAIN_HSA(m->hsync_end - m->hsync_start); - exynos_dsi_write(dsi, DSIM_MSYNC_REG, reg); + samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg); } reg = DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) | DSIM_MAIN_VRESOL(m->vdisplay, num_bits_resol);
- exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg); + samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
dev_dbg(dsi->dev, "LCD size = %dx%d\n", m->hdisplay, m->vdisplay); }
-static void exynos_dsi_set_display_enable(struct exynos_dsi *dsi, bool enable) +static void samsung_dsim_set_display_enable(struct samsung_dsim *dsi, bool enable) { u32 reg;
- reg = exynos_dsi_read(dsi, DSIM_MDRESOL_REG); + reg = samsung_dsim_read(dsi, DSIM_MDRESOL_REG); if (enable) reg |= DSIM_MAIN_STAND_BY; else reg &= ~DSIM_MAIN_STAND_BY; - exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg); + samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg); }
-static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi) +static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi) { int timeout = 2000;
do { - u32 reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG); + u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
if (!(reg & DSIM_SFR_HEADER_FULL)) return 0; @@ -943,27 +947,27 @@ static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi) return -ETIMEDOUT; }
-static void exynos_dsi_set_cmd_lpm(struct exynos_dsi *dsi, bool lpm) +static void samsung_dsim_set_cmd_lpm(struct samsung_dsim *dsi, bool lpm) { - u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); + u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
if (lpm) v |= DSIM_CMD_LPDT_LP; else v &= ~DSIM_CMD_LPDT_LP;
- exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v); + samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v); }
-static void exynos_dsi_force_bta(struct exynos_dsi *dsi) +static void samsung_dsim_force_bta(struct samsung_dsim *dsi) { - u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); + u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); v |= DSIM_FORCE_BTA; - exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v); + samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v); }
-static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, - struct exynos_dsi_transfer *xfer) +static void samsung_dsim_send_to_fifo(struct samsung_dsim *dsi, + struct samsung_dsim_transfer *xfer) { struct device *dev = dsi->dev; struct mipi_dsi_packet *pkt = &xfer->packet; @@ -983,7 +987,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, /* Send payload */ while (length >= 4) { reg = get_unaligned_le32(payload); - exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); + samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg); payload += 4; length -= 4; } @@ -998,7 +1002,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, fallthrough; case 1: reg |= payload[0]; - exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); + samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg); break; }
@@ -1007,25 +1011,25 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, return;
reg = get_unaligned_le32(pkt->header); - if (exynos_dsi_wait_for_hdr_fifo(dsi)) { + if (samsung_dsim_wait_for_hdr_fifo(dsi)) { dev_err(dev, "waiting for header FIFO timed out\n"); return; }
if (NEQV(xfer->flags & MIPI_DSI_MSG_USE_LPM, dsi->state & DSIM_STATE_CMD_LPM)) { - exynos_dsi_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM); + samsung_dsim_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM); dsi->state ^= DSIM_STATE_CMD_LPM; }
- exynos_dsi_write(dsi, DSIM_PKTHDR_REG, reg); + samsung_dsim_write(dsi, DSIM_PKTHDR_REG, reg);
if (xfer->flags & MIPI_DSI_MSG_REQ_ACK) - exynos_dsi_force_bta(dsi); + samsung_dsim_force_bta(dsi); }
-static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, - struct exynos_dsi_transfer *xfer) +static void samsung_dsim_read_from_fifo(struct samsung_dsim *dsi, + struct samsung_dsim_transfer *xfer) { u8 *payload = xfer->rx_payload + xfer->rx_done; bool first = !xfer->rx_done; @@ -1034,7 +1038,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, u32 reg;
if (first) { - reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); + reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
switch (reg & 0x3f) { case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: @@ -1073,7 +1077,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
/* Receive payload */ while (length >= 4) { - reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); + reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG); payload[0] = (reg >> 0) & 0xff; payload[1] = (reg >> 8) & 0xff; payload[2] = (reg >> 16) & 0xff; @@ -1083,7 +1087,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, }
if (length) { - reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); + reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG); switch (length) { case 3: payload[2] = (reg >> 16) & 0xff; @@ -1102,16 +1106,16 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, clear_fifo: length = DSI_RX_FIFO_SIZE / 4; do { - reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); + reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG); if (reg == DSI_RX_FIFO_EMPTY) break; } while (--length); }
-static void exynos_dsi_transfer_start(struct exynos_dsi *dsi) +static void samsung_dsim_transfer_start(struct samsung_dsim *dsi) { unsigned long flags; - struct exynos_dsi_transfer *xfer; + struct samsung_dsim_transfer *xfer; bool start = false;
again: @@ -1123,7 +1127,7 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi) }
xfer = list_first_entry(&dsi->transfer_list, - struct exynos_dsi_transfer, list); + struct samsung_dsim_transfer, list);
spin_unlock_irqrestore(&dsi->transfer_lock, flags);
@@ -1132,7 +1136,7 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi) /* waiting for RX */ return;
- exynos_dsi_send_to_fifo(dsi, xfer); + samsung_dsim_send_to_fifo(dsi, xfer);
if (xfer->packet.payload_length || xfer->rx_len) return; @@ -1151,9 +1155,9 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi) goto again; }
-static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi) +static bool samsung_dsim_transfer_finish(struct samsung_dsim *dsi) { - struct exynos_dsi_transfer *xfer; + struct samsung_dsim_transfer *xfer; unsigned long flags; bool start = true;
@@ -1165,7 +1169,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi) }
xfer = list_first_entry(&dsi->transfer_list, - struct exynos_dsi_transfer, list); + struct samsung_dsim_transfer, list);
spin_unlock_irqrestore(&dsi->transfer_lock, flags);
@@ -1178,7 +1182,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi) return true;
if (xfer->rx_done != xfer->rx_len) - exynos_dsi_read_from_fifo(dsi, xfer); + samsung_dsim_read_from_fifo(dsi, xfer);
if (xfer->rx_done != xfer->rx_len) return true; @@ -1197,8 +1201,8 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi) return start; }
-static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi, - struct exynos_dsi_transfer *xfer) +static void samsung_dsim_remove_transfer(struct samsung_dsim *dsi, + struct samsung_dsim_transfer *xfer) { unsigned long flags; bool start; @@ -1207,12 +1211,12 @@ static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
if (!list_empty(&dsi->transfer_list) && xfer == list_first_entry(&dsi->transfer_list, - struct exynos_dsi_transfer, list)) { + struct samsung_dsim_transfer, list)) { list_del_init(&xfer->list); start = !list_empty(&dsi->transfer_list); spin_unlock_irqrestore(&dsi->transfer_lock, flags); if (start) - exynos_dsi_transfer_start(dsi); + samsung_dsim_transfer_start(dsi); return; }
@@ -1221,8 +1225,8 @@ static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi, spin_unlock_irqrestore(&dsi->transfer_lock, flags); }
-static int exynos_dsi_transfer(struct exynos_dsi *dsi, - struct exynos_dsi_transfer *xfer) +static int samsung_dsim_transfer(struct samsung_dsim *dsi, + struct samsung_dsim_transfer *xfer) { unsigned long flags; bool stopped; @@ -1240,13 +1244,13 @@ static int exynos_dsi_transfer(struct exynos_dsi *dsi, spin_unlock_irqrestore(&dsi->transfer_lock, flags);
if (stopped) - exynos_dsi_transfer_start(dsi); + samsung_dsim_transfer_start(dsi);
wait_for_completion_timeout(&xfer->completed, msecs_to_jiffies(DSI_XFER_TIMEOUT_MS)); if (xfer->result == -ETIMEDOUT) { struct mipi_dsi_packet *pkt = &xfer->packet; - exynos_dsi_remove_transfer(dsi, xfer); + samsung_dsim_remove_transfer(dsi, xfer); dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 4, pkt->header, (int)pkt->payload_length, pkt->payload); return -ETIMEDOUT; @@ -1256,25 +1260,25 @@ static int exynos_dsi_transfer(struct exynos_dsi *dsi, return xfer->result; }
-static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) +static irqreturn_t samsung_dsim_irq(int irq, void *dev_id) { - struct exynos_dsi *dsi = dev_id; + struct samsung_dsim *dsi = dev_id; u32 status;
- status = exynos_dsi_read(dsi, DSIM_INTSRC_REG); + status = samsung_dsim_read(dsi, DSIM_INTSRC_REG); if (!status) { static unsigned long int j; if (printk_timed_ratelimit(&j, 500)) dev_warn(dsi->dev, "spurious interrupt\n"); return IRQ_HANDLED; } - exynos_dsi_write(dsi, DSIM_INTSRC_REG, status); + samsung_dsim_write(dsi, DSIM_INTSRC_REG, status);
if (status & DSIM_INT_SW_RST_RELEASE) { u32 mask = ~(DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY | DSIM_INT_SFR_HDR_FIFO_EMPTY | DSIM_INT_RX_ECC_ERR | DSIM_INT_SW_RST_RELEASE); - exynos_dsi_write(dsi, DSIM_INTMSK_REG, mask); + samsung_dsim_write(dsi, DSIM_INTMSK_REG, mask); complete(&dsi->completed); return IRQ_HANDLED; } @@ -1283,15 +1287,15 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) DSIM_INT_PLL_STABLE))) return IRQ_HANDLED;
- if (exynos_dsi_transfer_finish(dsi)) - exynos_dsi_transfer_start(dsi); + if (samsung_dsim_transfer_finish(dsi)) + samsung_dsim_transfer_start(dsi);
return IRQ_HANDLED; }
-static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) +static irqreturn_t samsung_dsim_te_irq_handler(int irq, void *dev_id) { - struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id; + struct samsung_dsim *dsi = (struct samsung_dsim *)dev_id; struct drm_encoder *encoder = &dsi->encoder;
if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE) @@ -1300,7 +1304,7 @@ static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; }
-static void exynos_dsi_enable_irq(struct exynos_dsi *dsi) +static void samsung_dsim_enable_irq(struct samsung_dsim *dsi) { enable_irq(dsi->irq);
@@ -1308,7 +1312,7 @@ static void exynos_dsi_enable_irq(struct exynos_dsi *dsi) enable_irq(gpio_to_irq(dsi->te_gpio)); }
-static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) +static void samsung_dsim_disable_irq(struct samsung_dsim *dsi) { if (gpio_is_valid(dsi->te_gpio)) disable_irq(gpio_to_irq(dsi->te_gpio)); @@ -1316,27 +1320,27 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) disable_irq(dsi->irq); }
-static int exynos_dsi_init(struct exynos_dsi *dsi) +static int samsung_dsim_init(struct samsung_dsim *dsi) { - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
- exynos_dsi_reset(dsi); - exynos_dsi_enable_irq(dsi); + samsung_dsim_reset(dsi); + samsung_dsim_enable_irq(dsi);
if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST) - exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1); + samsung_dsim_enable_lane(dsi, BIT(dsi->lanes) - 1);
- exynos_dsi_enable_clock(dsi); + samsung_dsim_enable_clock(dsi); if (driver_data->wait_for_reset) - exynos_dsi_wait_for_reset(dsi); - exynos_dsi_set_phy_ctrl(dsi); - exynos_dsi_init_link(dsi); + samsung_dsim_wait_for_reset(dsi); + samsung_dsim_set_phy_ctrl(dsi); + samsung_dsim_init_link(dsi);
return 0; }
-static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi, - struct device *panel) +static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi, + struct device *panel) { int ret; int te_gpio_irq; @@ -1359,7 +1363,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
te_gpio_irq = gpio_to_irq(dsi->te_gpio);
- ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL, + ret = request_threaded_irq(te_gpio_irq, samsung_dsim_te_irq_handler, NULL, IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, "TE", dsi); if (ret) { dev_err(dsi->dev, "request interrupt failed with %d\n", ret); @@ -1371,7 +1375,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi, return ret; }
-static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) +static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi) { if (gpio_is_valid(dsi->te_gpio)) { free_irq(gpio_to_irq(dsi->te_gpio), dsi); @@ -1380,9 +1384,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) } }
-static void exynos_dsi_bridge_enable(struct drm_bridge *bridge) +static void samsung_dsim_bridge_enable(struct drm_bridge *bridge) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct samsung_dsim *dsi = bridge_to_dsi(bridge); int ret;
if (dsi->state & DSIM_STATE_ENABLED) @@ -1396,39 +1400,39 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
dsi->state |= DSIM_STATE_ENABLED;
- exynos_dsi_set_display_mode(dsi); - exynos_dsi_set_display_enable(dsi, true); + samsung_dsim_set_display_mode(dsi); + samsung_dsim_set_display_enable(dsi, true);
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; return; }
-static void exynos_dsi_bridge_disable(struct drm_bridge *bridge) +static void samsung_dsim_bridge_disable(struct drm_bridge *bridge) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct samsung_dsim *dsi = bridge_to_dsi(bridge);
if (!(dsi->state & DSIM_STATE_ENABLED)) return;
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
- exynos_dsi_set_display_enable(dsi, false); + samsung_dsim_set_display_enable(dsi, false);
dsi->state &= ~DSIM_STATE_ENABLED; pm_runtime_put_sync(dsi->dev); }
-static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) +static void samsung_dsim_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct samsung_dsim *dsi = bridge_to_dsi(bridge);
drm_mode_copy(&dsi->mode, adjusted_mode); }
-static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, - struct device_node *node) +static int samsung_dsim_panel_or_bridge(struct samsung_dsim *dsi, + struct device_node *node) { struct drm_bridge *panel_bridge; struct drm_panel *panel; @@ -1453,10 +1457,10 @@ static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi, return 0; }
-static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) +static int samsung_dsim_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct samsung_dsim *dsi = bridge_to_dsi(bridge);
dsi->drm = bridge->dev;
@@ -1464,23 +1468,23 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, flags); }
-static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { - .enable = exynos_dsi_bridge_enable, - .disable = exynos_dsi_bridge_disable, - .mode_set = exynos_dsi_bridge_mode_set, - .attach = exynos_dsi_bridge_attach, +static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = { + .enable = samsung_dsim_bridge_enable, + .disable = samsung_dsim_bridge_disable, + .mode_set = samsung_dsim_bridge_mode_set, + .attach = samsung_dsim_bridge_attach, };
-MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); +MODULE_DEVICE_TABLE(of, samsung_dsim_of_match);
-static int exynos_dsi_host_attach(struct mipi_dsi_host *host, - struct mipi_dsi_device *device) +static int samsung_dsim_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) { - struct exynos_dsi *dsi = host_to_dsi(host); + struct samsung_dsim *dsi = host_to_dsi(host); struct drm_device *drm = dsi->drm; int ret;
- ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node); + ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node); if (ret) return ret;
@@ -1492,7 +1496,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, */ if (dsi->driver_data->exynos_specific && !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) { - int ret = exynos_dsi_register_te_irq(dsi, &device->dev); + int ret = samsung_dsim_register_te_irq(dsi, &device->dev); if (ret) return ret; } @@ -1514,33 +1518,33 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, return 0; }
-static int exynos_dsi_host_detach(struct mipi_dsi_host *host, - struct mipi_dsi_device *device) +static int samsung_dsim_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) { - struct exynos_dsi *dsi = host_to_dsi(host); + struct samsung_dsim *dsi = host_to_dsi(host); struct drm_device *drm = dsi->drm;
if (drm->mode_config.poll_enabled) drm_kms_helper_hotplug_event(drm);
if (dsi->driver_data->exynos_specific) - exynos_dsi_unregister_te_irq(dsi); + samsung_dsim_unregister_te_irq(dsi);
return 0; }
-static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host, - const struct mipi_dsi_msg *msg) +static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) { - struct exynos_dsi *dsi = host_to_dsi(host); - struct exynos_dsi_transfer xfer; + struct samsung_dsim *dsi = host_to_dsi(host); + struct samsung_dsim_transfer xfer; int ret;
if (!(dsi->state & DSIM_STATE_ENABLED)) return -EINVAL;
if (!(dsi->state & DSIM_STATE_INITIALIZED)) { - ret = exynos_dsi_init(dsi); + ret = samsung_dsim_init(dsi); if (ret) return ret; dsi->state |= DSIM_STATE_INITIALIZED; @@ -1554,18 +1558,18 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host, xfer.rx_payload = msg->rx_buf; xfer.flags = msg->flags;
- ret = exynos_dsi_transfer(dsi, &xfer); + ret = samsung_dsim_transfer(dsi, &xfer); return (ret < 0) ? ret : xfer.rx_done; }
-static const struct mipi_dsi_host_ops exynos_dsi_ops = { - .attach = exynos_dsi_host_attach, - .detach = exynos_dsi_host_detach, - .transfer = exynos_dsi_host_transfer, +static const struct mipi_dsi_host_ops samsung_dsim_ops = { + .attach = samsung_dsim_host_attach, + .detach = samsung_dsim_host_detach, + .transfer = samsung_dsim_host_transfer, };
-static int exynos_dsi_of_read_u32(const struct device_node *np, - const char *propname, u32 *out_value) +static int samsung_dsim_of_read_u32(const struct device_node *np, + const char *propname, u32 *out_value) { int ret = of_property_read_u32(np, propname, out_value);
@@ -1580,23 +1584,23 @@ enum { DSI_PORT_OUT };
-static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) +static int samsung_dsim_parse_dt(struct samsung_dsim *dsi) { struct device *dev = dsi->dev; struct device_node *node = dev->of_node; int ret;
- ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", + ret = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency", &dsi->pll_clk_rate); if (ret < 0) return ret;
- ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency", + ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency", &dsi->burst_clk_rate); if (ret < 0) return ret;
- ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency", + ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency", &dsi->esc_clk_rate); if (ret < 0) return ret; @@ -1604,10 +1608,10 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) return 0; }
-static int exynos_dsi_bind(struct device *dev, struct device *master, - void *data) +static int samsung_dsim_bind(struct device *dev, struct device *master, + void *data) { - struct exynos_dsi *dsi = dev_get_drvdata(dev); + struct samsung_dsim *dsi = dev_get_drvdata(dev); struct drm_encoder *encoder = &dsi->encoder; struct drm_device *drm_dev = data; struct device_node *in_bridge_node; @@ -1650,26 +1654,26 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, return mipi_dsi_host_register(&dsi->dsi_host); }
-static void exynos_dsi_unbind(struct device *dev, struct device *master, +static void samsung_dsim_unbind(struct device *dev, struct device *master, void *data) { - struct exynos_dsi *dsi = dev_get_drvdata(dev); + struct samsung_dsim *dsi = dev_get_drvdata(dev);
- exynos_dsi_bridge_disable(&dsi->bridge); + samsung_dsim_bridge_disable(&dsi->bridge); drm_encoder_cleanup(&dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host); }
-static const struct component_ops exynos_dsi_component_ops = { - .bind = exynos_dsi_bind, - .unbind = exynos_dsi_unbind, +static const struct component_ops samsung_dsim_component_ops = { + .bind = samsung_dsim_bind, + .unbind = samsung_dsim_unbind, };
-static int exynos_dsi_probe(struct platform_device *pdev) +static int samsung_dsim_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; - struct exynos_dsi *dsi; + struct samsung_dsim *dsi; int ret, i;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); @@ -1683,7 +1687,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) spin_lock_init(&dsi->transfer_lock); INIT_LIST_HEAD(&dsi->transfer_list);
- dsi->dsi_host.ops = &exynos_dsi_ops; + dsi->dsi_host.ops = &samsung_dsim_ops; dsi->dsi_host.dev = dev;
dsi->dev = dev; @@ -1734,7 +1738,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) return dsi->irq;
ret = devm_request_threaded_irq(dev, dsi->irq, NULL, - exynos_dsi_irq, + samsung_dsim_irq, IRQF_ONESHOT | IRQF_NO_AUTOEN, dev_name(dev), dsi); if (ret) { @@ -1742,7 +1746,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) return ret; }
- ret = exynos_dsi_parse_dt(dsi); + ret = samsung_dsim_parse_dt(dsi); if (ret) return ret;
@@ -1759,14 +1763,14 @@ static int exynos_dsi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
- dsi->bridge.funcs = &exynos_dsi_bridge_funcs; + dsi->bridge.funcs = &samsung_dsim_bridge_funcs; dsi->bridge.of_node = dev->of_node; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
drm_bridge_add(&dsi->bridge);
if (dsi->driver_data->exynos_specific) { - ret = component_add(dev, &exynos_dsi_component_ops); + ret = component_add(dev, &samsung_dsim_component_ops); if (ret) goto err_disable_runtime; } @@ -1779,24 +1783,24 @@ static int exynos_dsi_probe(struct platform_device *pdev) return ret; }
-static int exynos_dsi_remove(struct platform_device *pdev) +static int samsung_dsim_remove(struct platform_device *pdev) { - struct exynos_dsi *dsi = platform_get_drvdata(pdev); + struct samsung_dsim *dsi = platform_get_drvdata(pdev);
drm_bridge_remove(&dsi->bridge);
pm_runtime_disable(&pdev->dev);
if (dsi->driver_data->exynos_specific) - component_del(&pdev->dev, &exynos_dsi_component_ops); + component_del(&pdev->dev, &samsung_dsim_component_ops);
return 0; }
-static int __maybe_unused exynos_dsi_suspend(struct device *dev) +static int __maybe_unused samsung_dsim_suspend(struct device *dev) { - struct exynos_dsi *dsi = dev_get_drvdata(dev); - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + struct samsung_dsim *dsi = dev_get_drvdata(dev); + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; int ret, i;
usleep_range(10000, 20000); @@ -1804,9 +1808,9 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev) if (dsi->state & DSIM_STATE_INITIALIZED) { dsi->state &= ~DSIM_STATE_INITIALIZED;
- exynos_dsi_disable_clock(dsi); + samsung_dsim_disable_clock(dsi);
- exynos_dsi_disable_irq(dsi); + samsung_dsim_disable_irq(dsi); }
dsi->state &= ~DSIM_STATE_CMD_LPM; @@ -1823,10 +1827,10 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev) return 0; }
-static int __maybe_unused exynos_dsi_resume(struct device *dev) +static int __maybe_unused samsung_dsim_resume(struct device *dev) { - struct exynos_dsi *dsi = dev_get_drvdata(dev); - const struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + struct samsung_dsim *dsi = dev_get_drvdata(dev); + const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; int ret, i;
ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies); @@ -1857,24 +1861,25 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev) return ret; }
-static const struct dev_pm_ops exynos_dsi_pm_ops = { - SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL) +static const struct dev_pm_ops samsung_dsim_pm_ops = { + SET_RUNTIME_PM_OPS(samsung_dsim_suspend, samsung_dsim_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) };
struct platform_driver dsi_driver = { - .probe = exynos_dsi_probe, - .remove = exynos_dsi_remove, + .probe = samsung_dsim_probe, + .remove = samsung_dsim_remove, .driver = { - .name = "exynos-dsi", + .name = "samsung-dsim", .owner = THIS_MODULE, - .pm = &exynos_dsi_pm_ops, - .of_match_table = exynos_dsi_of_match, + .pm = &samsung_dsim_pm_ops, + .of_match_table = samsung_dsim_of_match, }, };
MODULE_AUTHOR("Tomasz Figa t.figa@samsung.com"); MODULE_AUTHOR("Andrzej Hajda a.hajda@samsung.com"); -MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master"); +MODULE_AUTHOR("Jagan Teki jagan@amarulasolutions.com"); +MODULE_DESCRIPTION("Samsung MIPI DSIM bridge"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 6a251e3aa779..6bcd0fe03c70 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -53,15 +53,6 @@ config DRM_EXYNOS_DPI help This enables support for Exynos parallel output.
-config DRM_EXYNOS_DSI - bool "MIPI-DSI host" - depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON - select DRM_MIPI_DSI - select DRM_PANEL - default n - help - This enables support for Exynos MIPI-DSI device. - config DRM_EXYNOS_DP bool "Exynos specific extensions for Analogix DP driver" depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 2fd2f3ee4fcf..04832f92051d 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -11,7 +11,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp.o exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER) += exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o
Samsing MIPI DSIM bridge can be found on Exynos and NXP's i.MX8M Mini and Nano SoC's.
This dt-bindings replaces legacy exynos_dsim.txt.
Used the example node from latest Exynos SoC instead of the one used in legacy exynos_dsim.txt.
Add dt-bingings for it.
Cc: Rob Herring robh+dt@kernel.org Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- .../display/bridge/samsung,mipi-dsim.yaml | 278 ++++++++++++++++++ .../bindings/display/exynos/exynos_dsim.txt | 90 ------ MAINTAINERS | 1 + 3 files changed, 279 insertions(+), 90 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml new file mode 100644 index 000000000000..b2970734ffd7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml @@ -0,0 +1,278 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung MIPI DSIM bridge controller + +maintainers: + - Inki Dae inki.dae@samsung.com + - Joonyoung Shim jy0922.shim@samsung.com + - Seung-Woo Kim sw0312.kim@samsung.com + - Kyungmin Park kyungmin.park@samsung.com + - Andrzej Hajda a.hajda@samsung.com + - Jagan Teki jagan@amarulasolutions.com + +description: | + Samsung MIPI DSIM bridge controller can be found it on Exynos + and i.MX8M Mini and Nano SoC's. + +properties: + compatible: + enum: + - samsung,exynos3250-mipi-dsi + - samsung,exynos4210-mipi-dsi + - samsung,exynos5410-mipi-dsi + - samsung,exynos5422-mipi-dsi + - samsung,exynos5433-mipi-dsi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + clocks: + minItems: 2 + maxItems: 5 + + clock-names: + minItems: 2 + maxItems: 5 + + phys: + maxItems: 1 + description: phandle to the phy module representing the DPHY + + phy-names: + items: + - const: dsim + + samsung,phy-type: + $ref: /schemas/types.yaml#/definitions/uint32 + description: phandle to the samsung phy-type + + power-domains: + description: phandle to the associated power domain + maxItems: 1 + + samsung,power-domain: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the associated samsung power domain + maxItems: 1 + + vddcore-supply: + description: MIPI DSIM Core voltage supply (e.g. 1.1V) + + vddio-supply: + description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V) + + samsung,burst-clock-frequency: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + DSIM high speed burst mode frequency. + + samsung,esc-clock-frequency: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + DSIM escape mode frequency. + + samsung,pll-clock-frequency: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + DSIM oscillator clock frequency. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/$defs/port-base + description: + Input port node to receive pixel data from the + display controller. Exactly one endpoint must be + specified. + properties: + endpoint@0: + $ref: /schemas/graph.yaml#/properties/endpoint + description: sub-node describing the input from MIC + + unevaluatedProperties: false + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + DSI output port node to the panel or the next bridge + in the chain + +required: + - '#address-cells' + - '#size-cells' + - clock-names + - clocks + - compatible + - interrupts + - phy-names + - phys + - reg + - samsung,burst-clock-frequency + - samsung,esc-clock-frequency + - samsung,pll-clock-frequency + +allOf: + - $ref: ../dsi-controller.yaml# + - if: + properties: + compatible: + contains: + const: samsung,exynos5433-mipi-dsi + + then: + properties: + clocks: + minItems: 5 + + clock-names: + items: + - const: bus_clk + - const: phyclk_mipidphy0_bitclkdiv8 + - const: phyclk_mipidphy0_rxclkesc0 + - const: sclk_rgb_vclk_to_dsim0 + - const: sclk_mipi + + ports: + required: + - port@0 + + required: + - ports + - vddcore-supply + - vddio-supply + + - if: + properties: + compatible: + contains: + const: samsung,exynos5410-mipi-dsi + + then: + properties: + clocks: + minItems: 2 + + clock-names: + items: + - const: bus_clk + - const: pll_clk + + required: + - vddcore-supply + - vddio-supply + + - if: + properties: + compatible: + contains: + const: samsung,exynos4210-mipi-dsi + + then: + properties: + clocks: + minItems: 2 + + clock-names: + items: + - const: bus_clk + - const: sclk_mipi + + required: + - vddcore-supply + - vddio-supply + + - if: + properties: + compatible: + contains: + const: samsung,exynos3250-mipi-dsi + + then: + properties: + clocks: + minItems: 2 + + clock-names: + items: + - const: bus_clk + - const: pll_clk + + required: + - vddcore-supply + - vddio-supply + - samsung,phy-type + +additionalProperties: + type: object + +examples: + - | + #include <dt-bindings/clock/exynos5433.h> + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + dsi@13900000 { + compatible = "samsung,exynos5433-mipi-dsi"; + reg = <0x13900000 0xC0>; + interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>; + phys = <&mipi_phy 1>; + phy-names = "dsim"; + clocks = <&cmu_disp CLK_PCLK_DSIM0>, + <&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>, + <&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>, + <&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>, + <&cmu_disp CLK_SCLK_DSIM0>; + clock-names = "bus_clk", + "phyclk_mipidphy0_bitclkdiv8", + "phyclk_mipidphy0_rxclkesc0", + "sclk_rgb_vclk_to_dsim0", + "sclk_mipi"; + power-domains = <&pd_disp>; + vddcore-supply = <&ldo6_reg>; + vddio-supply = <&ldo7_reg>; + samsung,burst-clock-frequency = <512000000>; + samsung,esc-clock-frequency = <16000000>; + samsung,pll-clock-frequency = <24000000>; + pinctrl-names = "default"; + pinctrl-0 = <&te_irq>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "samsung,s6e3ha2"; + reg = <0>; + vdd3-supply = <&ldo27_reg>; + vci-supply = <&ldo28_reg>; + reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dsi_to_mic: endpoint { + remote-endpoint = <&mic_to_dsi>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt deleted file mode 100644 index be377786e8cd..000000000000 --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt +++ /dev/null @@ -1,90 +0,0 @@ -Exynos MIPI DSI Master - -Required properties: - - compatible: value should be one of the following - "samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */ - "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */ - "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */ - "samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */ - "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */ - - reg: physical base address and length of the registers set for the device - - interrupts: should contain DSI interrupt - - clocks: list of clock specifiers, must contain an entry for each required - entry in clock-names - - clock-names: should include "bus_clk"and "sclk_mipi" entries - the use of "pll_clk" is deprecated - - phys: list of phy specifiers, must contain an entry for each required - entry in phy-names - - phy-names: should include "dsim" entry - - vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V) - - vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V) - - samsung,pll-clock-frequency: specifies frequency of the oscillator clock - - #address-cells, #size-cells: should be set respectively to <1> and <0> - according to DSI host bindings (see MIPI DSI bindings [1]) - - samsung,burst-clock-frequency: specifies DSI frequency in high-speed burst - mode - - samsung,esc-clock-frequency: specifies DSI frequency in escape mode - -Optional properties: - - power-domains: a phandle to DSIM power domain node - -Child nodes: - Should contain DSI peripheral nodes (see MIPI DSI bindings [1]). - -Video interfaces: - Device node can contain following video interface port nodes according to [2]: - 0: RGB input, - 1: DSI output - -[1]: Documentation/devicetree/bindings/display/mipi-dsi-bus.txt -[2]: Documentation/devicetree/bindings/media/video-interfaces.txt - -Example: - - dsi@11c80000 { - compatible = "samsung,exynos4210-mipi-dsi"; - reg = <0x11C80000 0x10000>; - interrupts = <0 79 0>; - clocks = <&clock 286>, <&clock 143>; - clock-names = "bus_clk", "sclk_mipi"; - phys = <&mipi_phy 1>; - phy-names = "dsim"; - vddcore-supply = <&vusb_reg>; - vddio-supply = <&vmipi_reg>; - power-domains = <&pd_lcd0>; - #address-cells = <1>; - #size-cells = <0>; - samsung,pll-clock-frequency = <24000000>; - - panel@1 { - reg = <0>; - ... - port { - panel_ep: endpoint { - remote-endpoint = <&dsi_ep>; - }; - }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - decon_to_mic: endpoint { - remote-endpoint = <&mic_to_decon>; - }; - }; - - port@1 { - reg = <1>; - dsi_ep: endpoint { - reg = <0>; - samsung,burst-clock-frequency = <500000000>; - samsung,esc-clock-frequency = <20000000>; - remote-endpoint = <&panel_ep>; - }; - }; - }; - }; diff --git a/MAINTAINERS b/MAINTAINERS index 733c2ebc0393..e571fc7792aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5873,6 +5873,7 @@ M: Andrzej Hajda a.hajda@samsung.com M: Jagan Teki jagan@amarulasolutions.com S: Maintained T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml F: drivers/gpu/drm/bridge/samsung-dsim.c
DRM DRIVER FOR SITRONIX ST7703 PANELS
On Sun, Jul 04, 2021 at 02:32:21PM +0530, Jagan Teki wrote:
Samsing MIPI DSIM bridge can be found on Exynos and NXP's i.MX8M Mini and Nano SoC's.
This dt-bindings replaces legacy exynos_dsim.txt.
Used the example node from latest Exynos SoC instead of the one used in legacy exynos_dsim.txt.
Add dt-bingings for it.
typo
Cc: Rob Herring robh+dt@kernel.org Signed-off-by: Jagan Teki jagan@amarulasolutions.com
.../display/bridge/samsung,mipi-dsim.yaml | 278 ++++++++++++++++++ .../bindings/display/exynos/exynos_dsim.txt | 90 ------ MAINTAINERS | 1 + 3 files changed, 279 insertions(+), 90 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml new file mode 100644 index 000000000000..b2970734ffd7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml @@ -0,0 +1,278 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml#
+title: Samsung MIPI DSIM bridge controller
+maintainers:
- Inki Dae inki.dae@samsung.com
- Joonyoung Shim jy0922.shim@samsung.com
- Seung-Woo Kim sw0312.kim@samsung.com
- Kyungmin Park kyungmin.park@samsung.com
- Andrzej Hajda a.hajda@samsung.com
- Jagan Teki jagan@amarulasolutions.com
+description: |
- Samsung MIPI DSIM bridge controller can be found it on Exynos
- and i.MX8M Mini and Nano SoC's.
+properties:
- compatible:
- enum:
- samsung,exynos3250-mipi-dsi
- samsung,exynos4210-mipi-dsi
- samsung,exynos5410-mipi-dsi
- samsung,exynos5422-mipi-dsi
- samsung,exynos5433-mipi-dsi
What about i.MX compatibles?
- reg:
- maxItems: 1
- interrupts:
- maxItems: 1
- '#address-cells':
- const: 1
- '#size-cells':
- const: 0
- clocks:
- minItems: 2
- maxItems: 5
- clock-names:
- minItems: 2
- maxItems: 5
- phys:
- maxItems: 1
- description: phandle to the phy module representing the DPHY
Drop
- phy-names:
- items:
- const: dsim
- samsung,phy-type:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: phandle to the samsung phy-type
- power-domains:
- description: phandle to the associated power domain
Drop
- maxItems: 1
- samsung,power-domain:
- $ref: /schemas/types.yaml#/definitions/phandle
- description: phandle to the associated samsung power domain
- maxItems: 1
- vddcore-supply:
- description: MIPI DSIM Core voltage supply (e.g. 1.1V)
- vddio-supply:
- description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
- samsung,burst-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM high speed burst mode frequency.
- samsung,esc-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM escape mode frequency.
- samsung,pll-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM oscillator clock frequency.
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
If there are no extra endpoint properties, then use '/schemas/graph.yaml#/properties/port'.
description:
Input port node to receive pixel data from the
display controller. Exactly one endpoint must be
specified.
properties:
endpoint@0:
$ref: /schemas/graph.yaml#/properties/endpoint
description: sub-node describing the input from MIC
I'd assume i.MX has a different input than MIC?
unevaluatedProperties: false
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
DSI output port node to the panel or the next bridge
in the chain
+required:
- '#address-cells'
- '#size-cells'
- clock-names
- clocks
- compatible
- interrupts
- phy-names
- phys
- reg
- samsung,burst-clock-frequency
- samsung,esc-clock-frequency
- samsung,pll-clock-frequency
+allOf:
- $ref: ../dsi-controller.yaml#
- if:
properties:
compatible:
contains:
const: samsung,exynos5433-mipi-dsi
- then:
properties:
clocks:
minItems: 5
clock-names:
items:
- const: bus_clk
- const: phyclk_mipidphy0_bitclkdiv8
- const: phyclk_mipidphy0_rxclkesc0
- const: sclk_rgb_vclk_to_dsim0
- const: sclk_mipi
ports:
required:
- port@0
required:
- ports
- vddcore-supply
- vddio-supply
- if:
properties:
compatible:
contains:
const: samsung,exynos5410-mipi-dsi
- then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: bus_clk
- const: pll_clk
required:
- vddcore-supply
- vddio-supply
- if:
properties:
compatible:
contains:
const: samsung,exynos4210-mipi-dsi
- then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: bus_clk
- const: sclk_mipi
required:
- vddcore-supply
- vddio-supply
- if:
properties:
compatible:
contains:
const: samsung,exynos3250-mipi-dsi
- then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: bus_clk
- const: pll_clk
required:
- vddcore-supply
- vddio-supply
- samsung,phy-type
+additionalProperties:
- type: object
+examples:
- |
- #include <dt-bindings/clock/exynos5433.h>
- #include <dt-bindings/gpio/gpio.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- dsi@13900000 {
compatible = "samsung,exynos5433-mipi-dsi";
reg = <0x13900000 0xC0>;
interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
phys = <&mipi_phy 1>;
phy-names = "dsim";
clocks = <&cmu_disp CLK_PCLK_DSIM0>,
<&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>,
<&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>,
<&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>,
<&cmu_disp CLK_SCLK_DSIM0>;
clock-names = "bus_clk",
"phyclk_mipidphy0_bitclkdiv8",
"phyclk_mipidphy0_rxclkesc0",
"sclk_rgb_vclk_to_dsim0",
"sclk_mipi";
power-domains = <&pd_disp>;
vddcore-supply = <&ldo6_reg>;
vddio-supply = <&ldo7_reg>;
samsung,burst-clock-frequency = <512000000>;
samsung,esc-clock-frequency = <16000000>;
samsung,pll-clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&te_irq>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "samsung,s6e3ha2";
reg = <0>;
vdd3-supply = <&ldo27_reg>;
vci-supply = <&ldo28_reg>;
reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi_to_mic: endpoint {
remote-endpoint = <&mic_to_dsi>;
};
};
};
- };
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt deleted file mode 100644 index be377786e8cd..000000000000 --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt +++ /dev/null @@ -1,90 +0,0 @@ -Exynos MIPI DSI Master
-Required properties:
- compatible: value should be one of the following
"samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
"samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
- reg: physical base address and length of the registers set for the device
- interrupts: should contain DSI interrupt
- clocks: list of clock specifiers, must contain an entry for each required
- entry in clock-names
- clock-names: should include "bus_clk"and "sclk_mipi" entries
the use of "pll_clk" is deprecated
- phys: list of phy specifiers, must contain an entry for each required
- entry in phy-names
- phy-names: should include "dsim" entry
- vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V)
- vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
- samsung,pll-clock-frequency: specifies frequency of the oscillator clock
- #address-cells, #size-cells: should be set respectively to <1> and <0>
- according to DSI host bindings (see MIPI DSI bindings [1])
- samsung,burst-clock-frequency: specifies DSI frequency in high-speed burst
- mode
- samsung,esc-clock-frequency: specifies DSI frequency in escape mode
-Optional properties:
- power-domains: a phandle to DSIM power domain node
-Child nodes:
- Should contain DSI peripheral nodes (see MIPI DSI bindings [1]).
-Video interfaces:
- Device node can contain following video interface port nodes according to [2]:
- 0: RGB input,
- 1: DSI output
-[1]: Documentation/devicetree/bindings/display/mipi-dsi-bus.txt -[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
-Example:
- dsi@11c80000 {
compatible = "samsung,exynos4210-mipi-dsi";
reg = <0x11C80000 0x10000>;
interrupts = <0 79 0>;
clocks = <&clock 286>, <&clock 143>;
clock-names = "bus_clk", "sclk_mipi";
phys = <&mipi_phy 1>;
phy-names = "dsim";
vddcore-supply = <&vusb_reg>;
vddio-supply = <&vmipi_reg>;
power-domains = <&pd_lcd0>;
#address-cells = <1>;
#size-cells = <0>;
samsung,pll-clock-frequency = <24000000>;
panel@1 {
reg = <0>;
...
port {
panel_ep: endpoint {
remote-endpoint = <&dsi_ep>;
};
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
decon_to_mic: endpoint {
remote-endpoint = <&mic_to_decon>;
};
};
port@1 {
reg = <1>;
dsi_ep: endpoint {
reg = <0>;
samsung,burst-clock-frequency = <500000000>;
samsung,esc-clock-frequency = <20000000>;
remote-endpoint = <&panel_ep>;
};
};
};
- };
diff --git a/MAINTAINERS b/MAINTAINERS index 733c2ebc0393..e571fc7792aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5873,6 +5873,7 @@ M: Andrzej Hajda a.hajda@samsung.com M: Jagan Teki jagan@amarulasolutions.com S: Maintained T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml F: drivers/gpu/drm/bridge/samsung-dsim.c
DRM DRIVER FOR SITRONIX ST7703 PANELS
2.25.1
On Mon, Jul 12, 2021 at 8:43 PM Rob Herring robh@kernel.org wrote:
On Sun, Jul 04, 2021 at 02:32:21PM +0530, Jagan Teki wrote:
Samsing MIPI DSIM bridge can be found on Exynos and NXP's i.MX8M Mini and Nano SoC's.
This dt-bindings replaces legacy exynos_dsim.txt.
Used the example node from latest Exynos SoC instead of the one used in legacy exynos_dsim.txt.
Add dt-bingings for it.
typo
Cc: Rob Herring robh+dt@kernel.org Signed-off-by: Jagan Teki jagan@amarulasolutions.com
.../display/bridge/samsung,mipi-dsim.yaml | 278 ++++++++++++++++++ .../bindings/display/exynos/exynos_dsim.txt | 90 ------ MAINTAINERS | 1 + 3 files changed, 279 insertions(+), 90 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml new file mode 100644 index 000000000000..b2970734ffd7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml @@ -0,0 +1,278 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml#
+title: Samsung MIPI DSIM bridge controller
+maintainers:
- Inki Dae inki.dae@samsung.com
- Joonyoung Shim jy0922.shim@samsung.com
- Seung-Woo Kim sw0312.kim@samsung.com
- Kyungmin Park kyungmin.park@samsung.com
- Andrzej Hajda a.hajda@samsung.com
- Jagan Teki jagan@amarulasolutions.com
+description: |
- Samsung MIPI DSIM bridge controller can be found it on Exynos
- and i.MX8M Mini and Nano SoC's.
+properties:
- compatible:
- enum:
- samsung,exynos3250-mipi-dsi
- samsung,exynos4210-mipi-dsi
- samsung,exynos5410-mipi-dsi
- samsung,exynos5422-mipi-dsi
- samsung,exynos5433-mipi-dsi
What about i.MX compatibles?
I have added in the next patch since this is yml conversation for existing .txt bindings.
- reg:
- maxItems: 1
- interrupts:
- maxItems: 1
- '#address-cells':
- const: 1
- '#size-cells':
- const: 0
- clocks:
- minItems: 2
- maxItems: 5
- clock-names:
- minItems: 2
- maxItems: 5
- phys:
- maxItems: 1
- description: phandle to the phy module representing the DPHY
Drop
- phy-names:
- items:
- const: dsim
- samsung,phy-type:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: phandle to the samsung phy-type
- power-domains:
- description: phandle to the associated power domain
Drop
- maxItems: 1
- samsung,power-domain:
- $ref: /schemas/types.yaml#/definitions/phandle
- description: phandle to the associated samsung power domain
- maxItems: 1
- vddcore-supply:
- description: MIPI DSIM Core voltage supply (e.g. 1.1V)
- vddio-supply:
- description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
- samsung,burst-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM high speed burst mode frequency.
- samsung,esc-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM escape mode frequency.
- samsung,pll-clock-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
DSIM oscillator clock frequency.
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
If there are no extra endpoint properties, then use '/schemas/graph.yaml#/properties/port'.
Okay.
description:
Input port node to receive pixel data from the
display controller. Exactly one endpoint must be
specified.
properties:
endpoint@0:
$ref: /schemas/graph.yaml#/properties/endpoint
description: sub-node describing the input from MIC
I'd assume i.MX has a different input than MIC?
Yes, updated in next patch.
Thanks, Jagan.
Add module init and exit functions for the bridge to register and unregister dsi_driver.
Exynos drm driver stack will register the platform_driver separately in the common of it's exynos_drm_drv.c including dsi_driver. Register again would return -EBUSY, so return 0 for such cases as dsi_driver is already registered.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index eed6b3ffdea7..627580abd6df 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1878,6 +1878,28 @@ struct platform_driver dsi_driver = { }, };
+static int __init samsung_mipi_dsim_init(void) +{ + int ret; + + ret = platform_driver_register(&dsi_driver); + + /** + * Exynos drm driver stack will register the platform_driver + * separately in the common of it's exynos_drm_drv.c including + * dsi_driver. Register again would return -EBUSY, so return 0 + * for such cases as dsi_driver is already registered. + */ + return ret == -EBUSY ? 0 : ret; +} +module_init(samsung_mipi_dsim_init); + +static void __exit samsung_mipi_dsim_exit(void) +{ + platform_driver_unregister(&dsi_driver); +} +module_exit(samsung_mipi_dsim_exit); + MODULE_AUTHOR("Tomasz Figa t.figa@samsung.com"); MODULE_AUTHOR("Andrzej Hajda a.hajda@samsung.com"); MODULE_AUTHOR("Jagan Teki jagan@amarulasolutions.com");
Existing bridge driver is able to find the panel or bridge if of_node isn't a port(s). This is how the exynos dsi node handling has been done so far.
However in order to make use of this bridge in other or new supported platforms like i.MX8MM it is required to have a port based of_node.
So, this patch will check if node is a port based and then update of_node.
This way we can support the platforms which are using legacy or new DSI bindings.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 627580abd6df..2222c27feffd 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -226,6 +226,11 @@ enum samsung_dsim_transfer_type { EXYNOS_DSI_RX, };
+enum { + DSI_PORT_IN, + DSI_PORT_OUT +}; + struct samsung_dsim_transfer { struct list_head list; struct completion completed; @@ -1436,6 +1441,15 @@ static int samsung_dsim_panel_or_bridge(struct samsung_dsim *dsi, { struct drm_bridge *panel_bridge; struct drm_panel *panel; + struct device_node *remote; + + if (of_graph_is_present(node)) { + remote = of_graph_get_remote_node(node, DSI_PORT_OUT, 0); + if (!remote) + return -ENODEV; + + node = remote; + }
panel_bridge = of_drm_find_bridge(node); if (!panel_bridge) { @@ -1579,11 +1593,6 @@ static int samsung_dsim_of_read_u32(const struct device_node *np, return ret; }
-enum { - DSI_PORT_IN, - DSI_PORT_OUT -}; - static int samsung_dsim_parse_dt(struct samsung_dsim *dsi) { struct device *dev = dsi->dev;
Finding panel_or_bridge might vary based on associated DSI device drivers like DSI panel, bridge, and I2C based DSI bridge.
All of these DSI drivers will invoke the DSI host in order to find the panel_or_bridge from probe to host attach and bridge_attach to host bridge attach.
So, in order to handle all these cases of finding the panel_or_bridge invoke the finding API in host attach and bridge attach with the DSIM_STATE_DEVICE_FOUND flag.
This way we can handle all possible cases of finding the DSI devices.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 2222c27feffd..9a2df1212d0f 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -248,6 +248,7 @@ struct samsung_dsim_transfer { #define DSIM_STATE_INITIALIZED BIT(1) #define DSIM_STATE_CMD_LPM BIT(2) #define DSIM_STATE_VIDOUT_AVAILABLE BIT(3) +#define DSIM_STATE_DEVICE_FOUND BIT(4)
struct samsung_dsim_driver_data { const unsigned int *reg_ofs; @@ -1475,6 +1476,15 @@ static int samsung_dsim_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); + int ret; + + if (!(dsi->state & DSIM_STATE_DEVICE_FOUND)) { + ret = samsung_dsim_panel_or_bridge(dsi, dsi->dev->of_node); + if (ret) + return ret; + + dsi->state |= DSIM_STATE_DEVICE_FOUND; + }
dsi->drm = bridge->dev;
@@ -1498,9 +1508,13 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host, struct drm_device *drm = dsi->drm; int ret;
- ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node); - if (ret) - return ret; + if (!(dsi->state & DSIM_STATE_DEVICE_FOUND)) { + ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node); + if (ret) + return ret; + + dsi->state |= DSIM_STATE_DEVICE_FOUND; + }
/* * This is a temporary solution and should be made by more generic way.
Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.
Add dt-bingings for it.
Cc: Rob Herring robh+dt@kernel.org Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- .../display/bridge/samsung,mipi-dsim.yaml | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml index b2970734ffd7..bd12d5706291 100644 --- a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml @@ -26,6 +26,7 @@ properties: - samsung,exynos5410-mipi-dsi - samsung,exynos5422-mipi-dsi - samsung,exynos5433-mipi-dsi + - fsl,imx8mm-mipi-dsim
reg: maxItems: 1 @@ -39,6 +40,10 @@ properties: '#size-cells': const: 0
+ assigned-clock-parents: true + assigned-clock-rates: true + assigned-clocks: true + clocks: minItems: 2 maxItems: 5 @@ -102,7 +107,7 @@ properties: properties: endpoint@0: $ref: /schemas/graph.yaml#/properties/endpoint - description: sub-node describing the input from MIC + description: sub-node describing the input from MIC or LCDIF
unevaluatedProperties: false
@@ -128,6 +133,30 @@ required:
allOf: - $ref: ../dsi-controller.yaml# + - if: + properties: + compatible: + contains: + const: fsl,imx8mm-mipi-dsim + + then: + properties: + clocks: + minItems: 2 + + clock-names: + items: + - const: bus_clk + - const: sclk_mipi + + ports: + required: + - port@0 + - port@1 + + required: + - ports + - if: properties: compatible: @@ -221,6 +250,59 @@ additionalProperties: type: object
examples: + - | + #include <dt-bindings/clock/imx8mm-clock.h> + #include <dt-bindings/power/imx8mm-power.h> + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + dsi@32e10000 { + compatible = "fsl,imx8mm-mipi-dsim"; + reg = <0x32e10000 0x400>; + clocks = <&clk IMX8MM_CLK_DSI_CORE>, + <&clk IMX8MM_CLK_DSI_PHY_REF>; + clock-names = "bus_clk", "sclk_mipi"; + assigned-clocks = <&clk IMX8MM_CLK_DSI_CORE>, + <&clk IMX8MM_VIDEO_PLL1_OUT>, + <&clk IMX8MM_CLK_DSI_PHY_REF>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>, + <&clk IMX8MM_VIDEO_PLL1_BYPASS>, + <&clk IMX8MM_VIDEO_PLL1_OUT>; + assigned-clock-rates = <266000000>, <594000000>, <27000000>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + phys = <&mipi_phy 0>; + phy-names = "dsim"; + power-domains = <&dispmix_blk_ctl IMX8MM_BLK_CTL_PD_DISPMIX_MIPI_DSI>; + samsung,burst-clock-frequency = <891000000>; + samsung,esc-clock-frequency = <54000000>; + samsung,pll-clock-frequency = <27000000>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + dsi_in_lcdif: endpoint@0 { + reg = <0>; + remote-endpoint = <&lcdif_out_dsi>; + }; + }; + + port@1 { + reg = <1>; + + dsi_out_panel: endpoint { + remote-endpoint = <&panel_in_dsi>; + }; + }; + }; + }; + - | #include <dt-bindings/clock/exynos5433.h> #include <dt-bindings/gpio/gpio.h>
On Sun, Jul 04, 2021 at 02:32:25PM +0530, Jagan Teki wrote:
Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.
Add dt-bingings for it.
Cc: Rob Herring robh+dt@kernel.org Signed-off-by: Jagan Teki jagan@amarulasolutions.com
.../display/bridge/samsung,mipi-dsim.yaml | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml index b2970734ffd7..bd12d5706291 100644 --- a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml @@ -26,6 +26,7 @@ properties: - samsung,exynos5410-mipi-dsi - samsung,exynos5422-mipi-dsi - samsung,exynos5433-mipi-dsi
- fsl,imx8mm-mipi-dsim
reg: maxItems: 1
@@ -39,6 +40,10 @@ properties: '#size-cells': const: 0
- assigned-clock-parents: true
- assigned-clock-rates: true
- assigned-clocks: true
You don't need these. They are always allowed if 'clocks' is present.
- clocks: minItems: 2 maxItems: 5
@@ -102,7 +107,7 @@ properties: properties: endpoint@0: $ref: /schemas/graph.yaml#/properties/endpoint
description: sub-node describing the input from MIC
description: sub-node describing the input from MIC or LCDIF unevaluatedProperties: false
@@ -128,6 +133,30 @@ required:
allOf:
- $ref: ../dsi-controller.yaml#
- if:
properties:
compatible:
contains:
const: fsl,imx8mm-mipi-dsim
- then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: bus_clk
- const: sclk_mipi
ports:
required:
- port@0
- port@1
required:
- ports
- if: properties: compatible:
@@ -221,6 +250,59 @@ additionalProperties: type: object
examples:
- |
- #include <dt-bindings/clock/imx8mm-clock.h>
- #include <dt-bindings/power/imx8mm-power.h>
- #include <dt-bindings/gpio/gpio.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- dsi@32e10000 {
compatible = "fsl,imx8mm-mipi-dsim";
reg = <0x32e10000 0x400>;
clocks = <&clk IMX8MM_CLK_DSI_CORE>,
<&clk IMX8MM_CLK_DSI_PHY_REF>;
clock-names = "bus_clk", "sclk_mipi";
assigned-clocks = <&clk IMX8MM_CLK_DSI_CORE>,
<&clk IMX8MM_VIDEO_PLL1_OUT>,
<&clk IMX8MM_CLK_DSI_PHY_REF>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>,
<&clk IMX8MM_VIDEO_PLL1_BYPASS>,
<&clk IMX8MM_VIDEO_PLL1_OUT>;
assigned-clock-rates = <266000000>, <594000000>, <27000000>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
phys = <&mipi_phy 0>;
phy-names = "dsim";
power-domains = <&dispmix_blk_ctl IMX8MM_BLK_CTL_PD_DISPMIX_MIPI_DSI>;
samsung,burst-clock-frequency = <891000000>;
samsung,esc-clock-frequency = <54000000>;
samsung,pll-clock-frequency = <27000000>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dsi_in_lcdif: endpoint@0 {
reg = <0>;
remote-endpoint = <&lcdif_out_dsi>;
};
};
port@1 {
reg = <1>;
dsi_out_panel: endpoint {
remote-endpoint = <&panel_in_dsi>;
};
};
};
- };
- | #include <dt-bindings/clock/exynos5433.h> #include <dt-bindings/gpio/gpio.h>
-- 2.25.1
Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.
Add compatible and associated driver_data it.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 9a2df1212d0f..ea379cb0cc32 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -460,6 +460,24 @@ static const unsigned int exynos5433_reg_values[] = { [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c), };
+static const unsigned int imx8mm_dsim_reg_values[] = { + [RESET_TYPE] = DSIM_SWRST, + [PLL_TIMER] = 500, + [STOP_STATE_CNT] = 0xf, + [PHYCTRL_ULPS_EXIT] = 0, + [PHYCTRL_VREG_LP] = 0, + [PHYCTRL_SLEW_UP] = 0, + [PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x06), + [PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0b), + [PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x07), + [PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x26), + [PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d), + [PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08), + [PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x08), + [PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d), + [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b), +}; + static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x50, @@ -521,6 +539,17 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = { .exynos_specific = true, };
+static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = { + .reg_ofs = exynos5433_reg_ofs, + .plltmr_reg = 0xa0, + .has_clklane_stop = 1, + .num_clks = 2, + .max_freq = 2100, + .wait_for_reset = 0, + .num_bits_resol = 12, + .reg_values = imx8mm_dsim_reg_values, +}; + static const struct of_device_id samsung_dsim_of_match[] = { { .compatible = "samsung,exynos3250-mipi-dsi", .data = &exynos3_dsi_driver_data }, @@ -532,6 +561,8 @@ static const struct of_device_id samsung_dsim_of_match[] = { .data = &exynos5422_dsi_driver_data }, { .compatible = "samsung,exynos5433-mipi-dsi", .data = &exynos5433_dsi_driver_data }, + { .compatible = "fsl,imx8mm-mipi-dsim", + .data = &imx8mm_dsi_driver_data }, { } };
eLCDIF is expecting to have input_bus_flags as DE_LOW in order to set active low during valid data transfer on each horizontal line.
Add DE_LOW flag via drm bridge timings.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index ea379cb0cc32..bc845ae100d4 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1723,6 +1723,10 @@ static const struct component_ops samsung_dsim_component_ops = { .unbind = samsung_dsim_unbind, };
+static const struct drm_bridge_timings samsung_dsim_bridge_timings = { + .input_bus_flags = DRM_BUS_FLAG_DE_LOW, +}; + static int samsung_dsim_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1819,6 +1823,7 @@ static int samsung_dsim_probe(struct platform_device *pdev)
dsi->bridge.funcs = &samsung_dsim_bridge_funcs; dsi->bridge.of_node = dev->of_node; + dsi->bridge.timings = &samsung_dsim_bridge_timings; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
drm_bridge_add(&dsi->bridge);
Host transfer in DSI master will invoke only when the DSI commands sent from DSI devices like DSI Panel or DSI bridges and this host transfer wouldn't invoke I2C based DSI bridge drivers.
Handling DSI host initialization in transfer calls might miss the controller setup for I2C based DSI bridges.
So, move the DSI initialization from transfer to bridge enable as the bridge enable API as it is common across all classes of DSI device drivers.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index bc845ae100d4..54767cbf231c 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1437,6 +1437,13 @@ static void samsung_dsim_bridge_enable(struct drm_bridge *bridge)
dsi->state |= DSIM_STATE_ENABLED;
+ if (!(dsi->state & DSIM_STATE_INITIALIZED)) { + ret = samsung_dsim_init(dsi); + if (ret) + return; + dsi->state |= DSIM_STATE_INITIALIZED; + } + samsung_dsim_set_display_mode(dsi); samsung_dsim_set_display_enable(dsi, true);
@@ -1602,13 +1609,6 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host, if (!(dsi->state & DSIM_STATE_ENABLED)) return -EINVAL;
- if (!(dsi->state & DSIM_STATE_INITIALIZED)) { - ret = samsung_dsim_init(dsi); - if (ret) - return ret; - dsi->state |= DSIM_STATE_INITIALIZED; - } - ret = mipi_dsi_create_packet(&xfer.packet, msg); if (ret < 0) return ret;
PMS_P offset value in existing driver is not compatible with i.MX8MM.
However the i.MX8M Mini Application Reference manual shows the PMS_P offset is the same in the driver, but the i.MX8MM downstream driver uses a different one.
So, handle the PMS_P offset via driver_data and use the offset value for i.MX8MM from the downstream driver.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 54767cbf231c..0ed218f5eefc 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -184,7 +184,7 @@ /* DSIM_PLLCTRL */ #define DSIM_FREQ_BAND(x) ((x) << 24) #define DSIM_PLL_EN (1 << 23) -#define DSIM_PLL_P(x) ((x) << 13) +#define DSIM_PLL_P(x, offset) ((x) << (offset)) #define DSIM_PLL_M(x) ((x) << 4) #define DSIM_PLL_S(x) ((x) << 1)
@@ -259,6 +259,7 @@ struct samsung_dsim_driver_data { unsigned int max_freq; unsigned int wait_for_reset; unsigned int num_bits_resol; + unsigned int pll_p_offset; const unsigned int *reg_values; bool exynos_specific; }; @@ -487,6 +488,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11, + .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true, }; @@ -500,6 +502,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11, + .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true, }; @@ -511,6 +514,7 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11, + .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true, }; @@ -523,6 +527,7 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = { .max_freq = 1500, .wait_for_reset = 0, .num_bits_resol = 12, + .pll_p_offset = 13, .reg_values = exynos5433_reg_values, .exynos_specific = true, }; @@ -535,6 +540,7 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = { .max_freq = 1500, .wait_for_reset = 1, .num_bits_resol = 12, + .pll_p_offset = 13, .reg_values = exynos5422_reg_values, .exynos_specific = true, }; @@ -547,6 +553,7 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = { .max_freq = 2100, .wait_for_reset = 0, .num_bits_resol = 12, + .pll_p_offset = 14, .reg_values = imx8mm_dsim_reg_values, };
@@ -662,7 +669,8 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi, writel(driver_data->reg_values[PLL_TIMER], dsi->reg_base + driver_data->plltmr_reg);
- reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s); + reg = DSIM_PLL_EN | DSIM_PLL_P(p, driver_data->pll_p_offset) | + DSIM_PLL_M(m) | DSIM_PLL_S(s);
if (driver_data->has_freqband) { static const unsigned long freq_bands[] = {
Hi Jagan, On Sun, Jul 04, 2021 at 02:32:29PM +0530, Jagan Teki wrote:
PMS_P offset value in existing driver is not compatible with i.MX8MM.
However the i.MX8M Mini Application Reference manual shows the PMS_P offset is the same in the driver, but the i.MX8MM downstream driver uses a different one.
So, handle the PMS_P offset via driver_data and use the offset value for i.MX8MM from the downstream driver.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
$subject and code speaks of PLL but the changelog says PMS. I think the changelog needs a small update here.
Sam
drivers/gpu/drm/bridge/samsung-dsim.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 54767cbf231c..0ed218f5eefc 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -184,7 +184,7 @@ /* DSIM_PLLCTRL */ #define DSIM_FREQ_BAND(x) ((x) << 24) #define DSIM_PLL_EN (1 << 23) -#define DSIM_PLL_P(x) ((x) << 13) +#define DSIM_PLL_P(x, offset) ((x) << (offset)) #define DSIM_PLL_M(x) ((x) << 4) #define DSIM_PLL_S(x) ((x) << 1)
@@ -259,6 +259,7 @@ struct samsung_dsim_driver_data { unsigned int max_freq; unsigned int wait_for_reset; unsigned int num_bits_resol;
- unsigned int pll_p_offset; const unsigned int *reg_values; bool exynos_specific;
}; @@ -487,6 +488,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11,
- .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true,
}; @@ -500,6 +502,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11,
- .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true,
}; @@ -511,6 +514,7 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = { .max_freq = 1000, .wait_for_reset = 1, .num_bits_resol = 11,
- .pll_p_offset = 13, .reg_values = reg_values, .exynos_specific = true,
}; @@ -523,6 +527,7 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = { .max_freq = 1500, .wait_for_reset = 0, .num_bits_resol = 12,
- .pll_p_offset = 13, .reg_values = exynos5433_reg_values, .exynos_specific = true,
}; @@ -535,6 +540,7 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = { .max_freq = 1500, .wait_for_reset = 1, .num_bits_resol = 12,
- .pll_p_offset = 13, .reg_values = exynos5422_reg_values, .exynos_specific = true,
}; @@ -547,6 +553,7 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = { .max_freq = 2100, .wait_for_reset = 0, .num_bits_resol = 12,
- .pll_p_offset = 14, .reg_values = imx8mm_dsim_reg_values,
};
@@ -662,7 +669,8 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi, writel(driver_data->reg_values[PLL_TIMER], dsi->reg_base + driver_data->plltmr_reg);
- reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
reg = DSIM_PLL_EN | DSIM_PLL_P(p, driver_data->pll_p_offset) |
DSIM_PLL_M(m) | DSIM_PLL_S(s);
if (driver_data->has_freqband) { static const unsigned long freq_bands[] = {
-- 2.25.1
Fixing up the mode flags are required in order to correlate the correct sync flags in i.MX8MM eLCDIF.
So, handle the mode flags via bridge, mode_fixup.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/samsung-dsim.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 0ed218f5eefc..c2a76ee5ac4e 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1474,6 +1474,16 @@ static void samsung_dsim_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static bool samsung_dsim_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + adjusted_mode->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); + adjusted_mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); + + return true; +} + static void samsung_dsim_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode) @@ -1542,6 +1552,7 @@ static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = { .enable = samsung_dsim_bridge_enable, .disable = samsung_dsim_bridge_disable, .mode_set = samsung_dsim_bridge_mode_set, + .mode_fixup = samsung_dsim_bridge_mode_fixup, .attach = samsung_dsim_bridge_attach, };
Hi Jagan, On Sun, Jul 04, 2021 at 02:32:30PM +0530, Jagan Teki wrote:
Fixing up the mode flags are required in order to correlate the correct sync flags in i.MX8MM eLCDIF.
So, handle the mode flags via bridge, mode_fixup.
Please do this in atomic_check. Check rcar-du for a way to get access to adjusted_mode.
I have a helper in the works, but I may not return to it until a week or more.
Sam
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
drivers/gpu/drm/bridge/samsung-dsim.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 0ed218f5eefc..c2a76ee5ac4e 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1474,6 +1474,16 @@ static void samsung_dsim_bridge_disable(struct drm_bridge *bridge) pm_runtime_put_sync(dsi->dev); }
+static bool samsung_dsim_bridge_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
+{
- adjusted_mode->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
- adjusted_mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
- return true;
+}
static void samsung_dsim_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode) @@ -1542,6 +1552,7 @@ static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = { .enable = samsung_dsim_bridge_enable, .disable = samsung_dsim_bridge_disable, .mode_set = samsung_dsim_bridge_mode_set,
- .mode_fixup = samsung_dsim_bridge_mode_fixup, .attach = samsung_dsim_bridge_attach,
};
-- 2.25.1
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Sam
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Thanks, Jagan.
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
Best regards,
Tim
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation - change few difference with samsung bridge - fix crashes of my dsi panels - compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael
Best regards,
Tim
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
Best regards,
Tim
Hi Tim
On Thu, Dec 9, 2021 at 5:40 PM Tim Harvey tharvey@gateworks.com wrote:
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
This series supports common bridge support for Samsung MIPI DSIM which is used in Exynos and i.MX8MM SoC's.
The final bridge supports both the Exynos and i.MX8MM DSI devices.
Right now bridge offers two sets of implementations.
A. With component_ops and exynos specific code exclusively for exynos dsi drivers and it's legacy bindings.
B. Without componenet_ops for newly implemented bridges and its users like i.MX8MM.
The future plan is to fix the implementation A) by dropping component_ops and fixing exynos specific code in order to make the bridge more mature to use and the same is mentioned in drivers TODO.
Patch 0001 - 0006: Bridge conversion Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
Tested in Engicam i.Core MX8M Mini SoM.
Anyone interest, please have a look on this repo https://github.com/openedev/linux/tree/070421-imx8mm-dsim
Would appreciate anyone from the exynos team to test it on the exynos platform?
Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
I will push on some tree and share
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi
patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
I plan to push on github
[17:07:42.315] Sending ready to systemd [ 214.052085] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 214.595998] etnaviv-gpu 38000000.gpu: recover hung GPU!
** (maynard:386): WARNING **: 17:07:43.874: failed to setup mixer: Success [17:07:44.175] Added surface 0xaaab02630440, app_id (null) to pending list [17:07:44.176] Added surface 0xaaab026172b0, app_id (null) to pending list ** Message: 17:07:44.289: New advertisement app id maynard ** Message: 17:07:44.290: New advertisement app id maynard [17:07:45.171] (background) position view 0xaaab0261f860, x 0, y 0, on output DSI-1 [17:07:45.171] (panel) geom.width 100, geom.height 480, geom.x 0, geom.y 0 [17:07:45.171] (panel) edge 2 position view 0xaaab02634510, x 0, y 0 [17:07:45.172] panel type 2 inited on output DSI-1 [17:07:45.172] Usable area: 380x480+100,0 [ 216.932080] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 217.476015] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 218.020157] etnaviv-gpu 38000000.gpu: recover hung GPU!
This is my problem on imx8mn
Michael
Michael
Best regards,
Tim
-- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________
Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com
On Thu, Dec 9, 2021 at 9:09 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Thu, Dec 9, 2021 at 5:40 PM Tim Harvey tharvey@gateworks.com wrote:
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote: > This series supports common bridge support for Samsung MIPI DSIM > which is used in Exynos and i.MX8MM SoC's. > > The final bridge supports both the Exynos and i.MX8MM DSI devices. > > Right now bridge offers two sets of implementations. > > A. With component_ops and exynos specific code exclusively for > exynos dsi drivers and it's legacy bindings. > > B. Without componenet_ops for newly implemented bridges and its > users like i.MX8MM. > > The future plan is to fix the implementation A) by dropping > component_ops and fixing exynos specific code in order to make > the bridge more mature to use and the same is mentioned in > drivers TODO. > > Patch 0001 - 0006: Bridge conversion > Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions > > Tested in Engicam i.Core MX8M Mini SoM. > > Anyone interest, please have a look on this repo > https://github.com/openedev/linux/tree/070421-imx8mm-dsim > > Would appreciate anyone from the exynos team to test it on > the exynos platform? > > Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
I will push on some tree and share
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi
patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
I plan to push on github
[17:07:42.315] Sending ready to systemd [ 214.052085] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 214.595998] etnaviv-gpu 38000000.gpu: recover hung GPU!
** (maynard:386): WARNING **: 17:07:43.874: failed to setup mixer: Success [17:07:44.175] Added surface 0xaaab02630440, app_id (null) to pending list [17:07:44.176] Added surface 0xaaab026172b0, app_id (null) to pending list ** Message: 17:07:44.289: New advertisement app id maynard ** Message: 17:07:44.290: New advertisement app id maynard [17:07:45.171] (background) position view 0xaaab0261f860, x 0, y 0, on output DSI-1 [17:07:45.171] (panel) geom.width 100, geom.height 480, geom.x 0, geom.y 0 [17:07:45.171] (panel) edge 2 position view 0xaaab02634510, x 0, y 0 [17:07:45.172] panel type 2 inited on output DSI-1 [17:07:45.172] Usable area: 380x480+100,0 [ 216.932080] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 217.476015] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 218.020157] etnaviv-gpu 38000000.gpu: recover hung GPU!
This is my problem on imx8mn
Do you have an imx8mm to compare with? Unfortunately I do not have an imx8mn with a MIPI DSI connector and can only test with imx8mm.
What software (other than kernel which you will share) do you have installed above and how is it configured or run to show the issue?
Best regards,
Tim
Am Donnerstag, dem 09.12.2021 um 18:09 +0100 schrieb Michael Nazzareno Trimarchi:
Hi Tim
On Thu, Dec 9, 2021 at 5:40 PM Tim Harvey tharvey@gateworks.com wrote:
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote:
Hi Jagan,
On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote: > This series supports common bridge support for Samsung MIPI DSIM > which is used in Exynos and i.MX8MM SoC's. > > The final bridge supports both the Exynos and i.MX8MM DSI devices. > > Right now bridge offers two sets of implementations. > > A. With component_ops and exynos specific code exclusively for > exynos dsi drivers and it's legacy bindings. > > B. Without componenet_ops for newly implemented bridges and its > users like i.MX8MM. > > The future plan is to fix the implementation A) by dropping > component_ops and fixing exynos specific code in order to make > the bridge more mature to use and the same is mentioned in > drivers TODO. > > Patch 0001 - 0006: Bridge conversion > Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions > > Tested in Engicam i.Core MX8M Mini SoM. > > Anyone interest, please have a look on this repo > https://github.com/openedev/linux/tree/070421-imx8mm-dsim > > Would appreciate anyone from the exynos team to test it on > the exynos platform? > > Any inputs?
I really like where you are headign with this! No testing - sorry. But I will try to provide a bit of feedback on the individual patches.
I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
I will push on some tree and share
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi
patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
I plan to push on github
[17:07:42.315] Sending ready to systemd [ 214.052085] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 214.595998] etnaviv-gpu 38000000.gpu: recover hung GPU!
** (maynard:386): WARNING **: 17:07:43.874: failed to setup mixer: Success [17:07:44.175] Added surface 0xaaab02630440, app_id (null) to pending list [17:07:44.176] Added surface 0xaaab026172b0, app_id (null) to pending list ** Message: 17:07:44.289: New advertisement app id maynard ** Message: 17:07:44.290: New advertisement app id maynard [17:07:45.171] (background) position view 0xaaab0261f860, x 0, y 0, on output DSI-1 [17:07:45.171] (panel) geom.width 100, geom.height 480, geom.x 0, geom.y 0 [17:07:45.171] (panel) edge 2 position view 0xaaab02634510, x 0, y 0 [17:07:45.172] panel type 2 inited on output DSI-1 [17:07:45.172] Usable area: 380x480+100,0 [ 216.932080] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 217.476015] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 218.020157] etnaviv-gpu 38000000.gpu: recover hung GPU!
This is my problem on imx8mn
Note that the GPU on the 8MN is from the GC7000 generation, which genreally has bogus feature registers, as VeriSilicon stopped using them in favor of a hardware database. To get the GPu working you need to transcribe the entry for this specific GPU from the downstream GPU driver into the etanviv HWDB format, to make the kernel and userspace driver aware of how to drive this GPU.
Regards, Lucas
Hi
On Thu, Dec 9, 2021 at 9:24 PM Lucas Stach dev@lynxeye.de wrote:
Am Donnerstag, dem 09.12.2021 um 18:09 +0100 schrieb Michael Nazzareno Trimarchi:
Hi Tim
On Thu, Dec 9, 2021 at 5:40 PM Tim Harvey tharvey@gateworks.com wrote:
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Sam,
On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote: > > Hi Jagan, > > On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote: > > This series supports common bridge support for Samsung MIPI DSIM > > which is used in Exynos and i.MX8MM SoC's. > > > > The final bridge supports both the Exynos and i.MX8MM DSI devices. > > > > Right now bridge offers two sets of implementations. > > > > A. With component_ops and exynos specific code exclusively for > > exynos dsi drivers and it's legacy bindings. > > > > B. Without componenet_ops for newly implemented bridges and its > > users like i.MX8MM. > > > > The future plan is to fix the implementation A) by dropping > > component_ops and fixing exynos specific code in order to make > > the bridge more mature to use and the same is mentioned in > > drivers TODO. > > > > Patch 0001 - 0006: Bridge conversion > > Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions > > > > Tested in Engicam i.Core MX8M Mini SoM. > > > > Anyone interest, please have a look on this repo > > https://github.com/openedev/linux/tree/070421-imx8mm-dsim > > > > Would appreciate anyone from the exynos team to test it on > > the exynos platform? > > > > Any inputs? > > I really like where you are headign with this! > No testing - sorry. But I will try to provide a bit of feedback on the > individual patches. > > I hope you find a way to move forward with this.
Thanks for the response.
We have found some issues with Bridge conversion on existing exynos drivers. The component based DSI drivers(like exynos) are difficult to attach if it involves kms hotplug. kms hotplug would require drm pointer and that pointer would only available after the bind call finishes. But the bridge attach in bind call will defer till it find the attached bridge.
Right now I'm trying to find the proper way to attach the bridges for component based DSI drivers which involves kms hot-plug.
If you have any ideas on this, please let me know.
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
I will push on some tree and share
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi
patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
I plan to push on github
[17:07:42.315] Sending ready to systemd [ 214.052085] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 214.595998] etnaviv-gpu 38000000.gpu: recover hung GPU!
** (maynard:386): WARNING **: 17:07:43.874: failed to setup mixer: Success [17:07:44.175] Added surface 0xaaab02630440, app_id (null) to pending list [17:07:44.176] Added surface 0xaaab026172b0, app_id (null) to pending list ** Message: 17:07:44.289: New advertisement app id maynard ** Message: 17:07:44.290: New advertisement app id maynard [17:07:45.171] (background) position view 0xaaab0261f860, x 0, y 0, on output DSI-1 [17:07:45.171] (panel) geom.width 100, geom.height 480, geom.x 0, geom.y 0 [17:07:45.171] (panel) edge 2 position view 0xaaab02634510, x 0, y 0 [17:07:45.172] panel type 2 inited on output DSI-1 [17:07:45.172] Usable area: 380x480+100,0 [ 216.932080] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 217.476015] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 218.020157] etnaviv-gpu 38000000.gpu: recover hung GPU!
This is my problem on imx8mn
Note that the GPU on the 8MN is from the GC7000 generation, which genreally has bogus feature registers, as VeriSilicon stopped using them in favor of a hardware database. To get the GPu working you need to transcribe the entry for this specific GPU from the downstream GPU driver into the etanviv HWDB format, to make the kernel and userspace driver aware of how to drive this GPU.
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index f2fc645c7956..724f78fd37e5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -68,6 +68,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .minor_features10 = 0x00004040, .minor_features11 = 0x00000024, }, + { + .model = 0x7000, + .revision = 0x6203, + .product_id = ~0U, + .customer_id = ~0U, + .eco_id = 0, + .stream_count = 16, + .register_max = 64, + .thread_count = 512, + .shader_core_count = 2, + .vertex_cache_size = 16, + .vertex_output_buffer_size = 1024, + .pixel_pipes = 1, + .instruction_count = 512, + .num_constants = 320, + .buffer_size = 0, + .varyings_count = 16, + .features = 0xe0287c8c, + .minor_features0 = 0xc1589eff, + .minor_features1 = 0xfefbfad9, + .minor_features2 = 0xeb9d4fbf, + .minor_features3 = 0xedfffced, + .minor_features4 = 0xdb0dafc7, + .minor_features5 = 0x3b5ac333, + .minor_features6 = 0xfcce6000, + .minor_features7 = 0xfffbfa6f, + .minor_features8 = 0x00e10ef3, + .minor_features9 = 0x00c8003c, + .minor_features10 = 0x00004040, + .minor_features11 = 0x00000024, + }, { .model = 0x7000, .revision = 0x6204,
Ok, should something like this. Only does not know about this gcFEATURE_BIT_DE_2D_FAST_CLEAR. I put in features but can even a minor. Do you know the right mapping?
Michael
Michael
Regards, Lucas
On Thu, Dec 9, 2021 at 3:24 PM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi
On Thu, Dec 9, 2021 at 9:24 PM Lucas Stach dev@lynxeye.de wrote:
Am Donnerstag, dem 09.12.2021 um 18:09 +0100 schrieb Michael Nazzareno Trimarchi:
Hi Tim
On Thu, Dec 9, 2021 at 5:40 PM Tim Harvey tharvey@gateworks.com wrote:
On Thu, Dec 9, 2021 at 12:36 AM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi Tim
On Tue, Oct 5, 2021 at 11:43 PM Tim Harvey tharvey@gateworks.com wrote:
On Sun, Jul 25, 2021 at 10:14 AM Jagan Teki jagan@amarulasolutions.com wrote: > > Hi Sam, > > On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg sam@ravnborg.org wrote: > > > > Hi Jagan, > > > > On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote: > > > This series supports common bridge support for Samsung MIPI DSIM > > > which is used in Exynos and i.MX8MM SoC's. > > > > > > The final bridge supports both the Exynos and i.MX8MM DSI devices. > > > > > > Right now bridge offers two sets of implementations. > > > > > > A. With component_ops and exynos specific code exclusively for > > > exynos dsi drivers and it's legacy bindings. > > > > > > B. Without componenet_ops for newly implemented bridges and its > > > users like i.MX8MM. > > > > > > The future plan is to fix the implementation A) by dropping > > > component_ops and fixing exynos specific code in order to make > > > the bridge more mature to use and the same is mentioned in > > > drivers TODO. > > > > > > Patch 0001 - 0006: Bridge conversion > > > Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions > > > > > > Tested in Engicam i.Core MX8M Mini SoM. > > > > > > Anyone interest, please have a look on this repo > > > https://github.com/openedev/linux/tree/070421-imx8mm-dsim > > > > > > Would appreciate anyone from the exynos team to test it on > > > the exynos platform? > > > > > > Any inputs? > > > > I really like where you are headign with this! > > No testing - sorry. But I will try to provide a bit of feedback on the > > individual patches. > > > > I hope you find a way to move forward with this. > > Thanks for the response. > > We have found some issues with Bridge conversion on existing exynos > drivers. The component based DSI drivers(like exynos) are difficult to > attach if it involves kms hotplug. kms hotplug would require drm > pointer and that pointer would only available after the bind call > finishes. But the bridge attach in bind call will defer till it find > the attached bridge. > > Right now I'm trying to find the proper way to attach the bridges for > component based DSI drivers which involves kms hot-plug. > > If you have any ideas on this, please let me know. >
Jagan,
How is your progress on this series? Looking at your repo it looks like you've rebased on top of 5.13-rc3 in your 070121-imx8mm-dsim branch but you've got a lot of things there that are likely not related to this series?
I have a bit of work on those patches and tested on imx8mn. Basically:
- add the dsi timing calculation
- change few difference with samsung bridge
- fix crashes of my dsi panels
- compare with NXP driver the final results
I found that I have one problem that gives me some instability. In the NXP original driver the panel needs to be enabled in bridge_enable before out the standby. If I understand correctly, our standby should be done after. I would like to have some feedback and help and testing on other boards/devices and some suggestions on how to handle some of the differences. Another big problem is etnavi that is not stable
Michael,
Where can I find your patches?
I will push on some tree and share
What do you mean by etnaviv not being stable?
I did some limited testing with etnaviv on imx8mm with 5.15 + dsi
patches on an Ubuntu focal root filesystem by: apt update apt install gnome-session gnome-terminal ^^^ 2D hardware acceleration appears to be working (dragging opaque windows around) apt install mesa-utils glmark2 glxgears ^^^ ~160fps on IMX8MM glmark2 ^^^ score of 39 on IMX8MM
I haven't seen any updates from Jagan since Nov 24 (https://www.spinics.net/lists/dri-devel/msg324059.html) and am not sure if he's been able to work through drm/exynos issues that have been blocking his progress.
I plan to push on github
[17:07:42.315] Sending ready to systemd [ 214.052085] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 214.595998] etnaviv-gpu 38000000.gpu: recover hung GPU!
Which Nano variant do you have? Not all Nano's have a GPU. I know Tim Harvey was having a similar issue, but it turns out his variant of the Nano did not include a GPU.
** (maynard:386): WARNING **: 17:07:43.874: failed to setup mixer: Success [17:07:44.175] Added surface 0xaaab02630440, app_id (null) to pending list [17:07:44.176] Added surface 0xaaab026172b0, app_id (null) to pending list ** Message: 17:07:44.289: New advertisement app id maynard ** Message: 17:07:44.290: New advertisement app id maynard [17:07:45.171] (background) position view 0xaaab0261f860, x 0, y 0, on output DSI-1 [17:07:45.171] (panel) geom.width 100, geom.height 480, geom.x 0, geom.y 0 [17:07:45.171] (panel) edge 2 position view 0xaaab02634510, x 0, y 0 [17:07:45.172] panel type 2 inited on output DSI-1 [17:07:45.172] Usable area: 380x480+100,0 [ 216.932080] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 217.476015] etnaviv-gpu 38000000.gpu: recover hung GPU! [ 218.020157] etnaviv-gpu 38000000.gpu: recover hung GPU!
This is my problem on imx8mn
Note that the GPU on the 8MN is from the GC7000 generation, which genreally has bogus feature registers, as VeriSilicon stopped using them in favor of a hardware database. To get the GPu working you need to transcribe the entry for this specific GPU from the downstream GPU driver into the etanviv HWDB format, to make the kernel and userspace driver aware of how to drive this GPU.
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index f2fc645c7956..724f78fd37e5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -68,6 +68,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .minor_features10 = 0x00004040, .minor_features11 = 0x00000024, },
{
.model = 0x7000,
.revision = 0x6203,
.product_id = ~0U,
.customer_id = ~0U,
.eco_id = 0,
.stream_count = 16,
.register_max = 64,
.thread_count = 512,
.shader_core_count = 2,
.vertex_cache_size = 16,
.vertex_output_buffer_size = 1024,
.pixel_pipes = 1,
.instruction_count = 512,
.num_constants = 320,
.buffer_size = 0,
.varyings_count = 16,
.features = 0xe0287c8c,
.minor_features0 = 0xc1589eff,
.minor_features1 = 0xfefbfad9,
.minor_features2 = 0xeb9d4fbf,
.minor_features3 = 0xedfffced,
.minor_features4 = 0xdb0dafc7,
.minor_features5 = 0x3b5ac333,
.minor_features6 = 0xfcce6000,
.minor_features7 = 0xfffbfa6f,
.minor_features8 = 0x00e10ef3,
.minor_features9 = 0x00c8003c,
.minor_features10 = 0x00004040,
.minor_features11 = 0x00000024,
}, { .model = 0x7000, .revision = 0x6204,
Ok, should something like this. Only does not know about this gcFEATURE_BIT_DE_2D_FAST_CLEAR. I put in features but can even a minor. Do you know the right mapping?
Michael
Michael
Regards, Lucas
-- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________
Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com
dri-devel@lists.freedesktop.org