1 // SPDX-License-Identifier: GPL-2.0-only
3 * Samsung MIPI DSIM glue for Exynos SoCs.
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd
10 #include <linux/component.h>
11 #include <linux/of_device.h>
13 #include <drm/bridge/samsung-dsim.h>
14 #include <drm/drm_probe_helper.h>
15 #include <drm/drm_simple_kms_helper.h>
17 #include "exynos_drm_crtc.h"
18 #include "exynos_drm_drv.h"
21 struct drm_encoder encoder;
24 static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
26 struct exynos_dsi *dsi = dsim->priv;
27 struct drm_encoder *encoder = &dsi->encoder;
29 if (dsim->state & DSIM_STATE_VIDOUT_AVAILABLE)
30 exynos_drm_crtc_te_handler(encoder->crtc);
35 static int exynos_dsi_host_attach(struct samsung_dsim *dsim,
36 struct mipi_dsi_device *device)
38 struct exynos_dsi *dsi = dsim->priv;
39 struct drm_encoder *encoder = &dsi->encoder;
40 struct drm_device *drm = encoder->dev;
42 drm_bridge_attach(encoder, &dsim->bridge,
43 list_first_entry_or_null(&encoder->bridge_chain,
47 mutex_lock(&drm->mode_config.mutex);
49 dsim->lanes = device->lanes;
50 dsim->format = device->format;
51 dsim->mode_flags = device->mode_flags;
52 exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
53 !(dsim->mode_flags & MIPI_DSI_MODE_VIDEO);
55 mutex_unlock(&drm->mode_config.mutex);
57 if (drm->mode_config.poll_enabled)
58 drm_kms_helper_hotplug_event(drm);
63 static void exynos_dsi_host_detach(struct samsung_dsim *dsim,
64 struct mipi_dsi_device *device)
66 struct exynos_dsi *dsi = dsim->priv;
67 struct drm_device *drm = dsi->encoder.dev;
69 if (drm->mode_config.poll_enabled)
70 drm_kms_helper_hotplug_event(drm);
73 static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
75 struct samsung_dsim *dsim = dev_get_drvdata(dev);
76 struct exynos_dsi *dsi = dsim->priv;
77 struct drm_encoder *encoder = &dsi->encoder;
78 struct drm_device *drm_dev = data;
81 drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
83 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
87 return mipi_dsi_host_register(&dsim->dsi_host);
90 static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
92 struct samsung_dsim *dsim = dev_get_drvdata(dev);
94 dsim->bridge.funcs->atomic_disable(&dsim->bridge, NULL);
96 mipi_dsi_host_unregister(&dsim->dsi_host);
99 static const struct component_ops exynos_dsi_component_ops = {
100 .bind = exynos_dsi_bind,
101 .unbind = exynos_dsi_unbind,
104 static int exynos_dsi_register_host(struct samsung_dsim *dsim)
106 struct exynos_dsi *dsi;
108 dsi = devm_kzalloc(dsim->dev, sizeof(*dsi), GFP_KERNEL);
113 dsim->bridge.pre_enable_prev_first = true;
115 return component_add(dsim->dev, &exynos_dsi_component_ops);
118 static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)
120 component_del(dsim->dev, &exynos_dsi_component_ops);
123 static const struct samsung_dsim_host_ops exynos_dsi_exynos_host_ops = {
124 .register_host = exynos_dsi_register_host,
125 .unregister_host = exynos_dsi_unregister_host,
126 .attach = exynos_dsi_host_attach,
127 .detach = exynos_dsi_host_detach,
128 .te_irq_handler = exynos_dsi_te_irq_handler,
131 static const struct samsung_dsim_plat_data exynos3250_dsi_pdata = {
132 .hw_type = DSIM_TYPE_EXYNOS3250,
133 .host_ops = &exynos_dsi_exynos_host_ops,
136 static const struct samsung_dsim_plat_data exynos4210_dsi_pdata = {
137 .hw_type = DSIM_TYPE_EXYNOS4210,
138 .host_ops = &exynos_dsi_exynos_host_ops,
141 static const struct samsung_dsim_plat_data exynos5410_dsi_pdata = {
142 .hw_type = DSIM_TYPE_EXYNOS5410,
143 .host_ops = &exynos_dsi_exynos_host_ops,
146 static const struct samsung_dsim_plat_data exynos5422_dsi_pdata = {
147 .hw_type = DSIM_TYPE_EXYNOS5422,
148 .host_ops = &exynos_dsi_exynos_host_ops,
151 static const struct samsung_dsim_plat_data exynos5433_dsi_pdata = {
152 .hw_type = DSIM_TYPE_EXYNOS5433,
153 .host_ops = &exynos_dsi_exynos_host_ops,
156 static const struct of_device_id exynos_dsi_of_match[] = {
158 .compatible = "samsung,exynos3250-mipi-dsi",
159 .data = &exynos3250_dsi_pdata,
162 .compatible = "samsung,exynos4210-mipi-dsi",
163 .data = &exynos4210_dsi_pdata,
166 .compatible = "samsung,exynos5410-mipi-dsi",
167 .data = &exynos5410_dsi_pdata,
170 .compatible = "samsung,exynos5422-mipi-dsi",
171 .data = &exynos5422_dsi_pdata,
174 .compatible = "samsung,exynos5433-mipi-dsi",
175 .data = &exynos5433_dsi_pdata,
179 MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
181 struct platform_driver dsi_driver = {
182 .probe = samsung_dsim_probe,
183 .remove = samsung_dsim_remove,
185 .name = "exynos-dsi",
186 .owner = THIS_MODULE,
187 .pm = &samsung_dsim_pm_ops,
188 .of_match_table = exynos_dsi_of_match,
194 MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
195 MODULE_LICENSE("GPL v2");