drm/connector: Change DRM card alias from underscore to hyphen
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / exynos / exynos_drm_dsi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Samsung MIPI DSIM glue for Exynos SoCs.
4  *
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd
6  *
7  * Contacts: Tomasz Figa <t.figa@samsung.com>
8  */
9
10 #include <linux/component.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13
14 #include <drm/bridge/samsung-dsim.h>
15 #include <drm/drm_probe_helper.h>
16 #include <drm/drm_simple_kms_helper.h>
17
18 #include "exynos_drm_crtc.h"
19 #include "exynos_drm_drv.h"
20
21 struct exynos_dsi {
22         struct drm_encoder encoder;
23 };
24
25 static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
26 {
27         struct exynos_dsi *dsi = dsim->priv;
28         struct drm_encoder *encoder = &dsi->encoder;
29
30         if (dsim->state & DSIM_STATE_VIDOUT_AVAILABLE)
31                 exynos_drm_crtc_te_handler(encoder->crtc);
32
33         return IRQ_HANDLED;
34 }
35
36 static int exynos_dsi_host_attach(struct samsung_dsim *dsim,
37                                   struct mipi_dsi_device *device)
38 {
39         struct exynos_dsi *dsi = dsim->priv;
40         struct drm_encoder *encoder = &dsi->encoder;
41         struct drm_device *drm = encoder->dev;
42
43         drm_bridge_attach(encoder, &dsim->bridge,
44                           list_first_entry_or_null(&encoder->bridge_chain,
45                                                    struct drm_bridge,
46                                                    chain_node), 0);
47
48         mutex_lock(&drm->mode_config.mutex);
49
50         dsim->lanes = device->lanes;
51         dsim->format = device->format;
52         dsim->mode_flags = device->mode_flags;
53         exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
54                         !(dsim->mode_flags & MIPI_DSI_MODE_VIDEO);
55
56         mutex_unlock(&drm->mode_config.mutex);
57
58         if (drm->mode_config.poll_enabled)
59                 drm_kms_helper_hotplug_event(drm);
60
61         return 0;
62 }
63
64 static void exynos_dsi_host_detach(struct samsung_dsim *dsim,
65                                    struct mipi_dsi_device *device)
66 {
67         struct exynos_dsi *dsi = dsim->priv;
68         struct drm_device *drm = dsi->encoder.dev;
69
70         if (drm->mode_config.poll_enabled)
71                 drm_kms_helper_hotplug_event(drm);
72 }
73
74 static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
75 {
76         struct samsung_dsim *dsim = dev_get_drvdata(dev);
77         struct exynos_dsi *dsi = dsim->priv;
78         struct drm_encoder *encoder = &dsi->encoder;
79         struct drm_device *drm_dev = data;
80         int ret;
81
82         drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
83
84         ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
85         if (ret < 0)
86                 return ret;
87
88         return mipi_dsi_host_register(&dsim->dsi_host);
89 }
90
91 static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
92 {
93         struct samsung_dsim *dsim = dev_get_drvdata(dev);
94
95         dsim->bridge.funcs->atomic_disable(&dsim->bridge, NULL);
96
97         mipi_dsi_host_unregister(&dsim->dsi_host);
98 }
99
100 static const struct component_ops exynos_dsi_component_ops = {
101         .bind   = exynos_dsi_bind,
102         .unbind = exynos_dsi_unbind,
103 };
104
105 static int exynos_dsi_register_host(struct samsung_dsim *dsim)
106 {
107         struct exynos_dsi *dsi;
108
109         dsi = devm_kzalloc(dsim->dev, sizeof(*dsi), GFP_KERNEL);
110         if (!dsi)
111                 return -ENOMEM;
112
113         dsim->priv = dsi;
114         dsim->bridge.pre_enable_prev_first = true;
115
116         return component_add(dsim->dev, &exynos_dsi_component_ops);
117 }
118
119 static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)
120 {
121         component_del(dsim->dev, &exynos_dsi_component_ops);
122 }
123
124 static const struct samsung_dsim_host_ops exynos_dsi_exynos_host_ops = {
125         .register_host = exynos_dsi_register_host,
126         .unregister_host = exynos_dsi_unregister_host,
127         .attach = exynos_dsi_host_attach,
128         .detach = exynos_dsi_host_detach,
129         .te_irq_handler = exynos_dsi_te_irq_handler,
130 };
131
132 static const struct samsung_dsim_plat_data exynos3250_dsi_pdata = {
133         .hw_type = DSIM_TYPE_EXYNOS3250,
134         .host_ops = &exynos_dsi_exynos_host_ops,
135 };
136
137 static const struct samsung_dsim_plat_data exynos4210_dsi_pdata = {
138         .hw_type = DSIM_TYPE_EXYNOS4210,
139         .host_ops = &exynos_dsi_exynos_host_ops,
140 };
141
142 static const struct samsung_dsim_plat_data exynos5410_dsi_pdata = {
143         .hw_type = DSIM_TYPE_EXYNOS5410,
144         .host_ops = &exynos_dsi_exynos_host_ops,
145 };
146
147 static const struct samsung_dsim_plat_data exynos5422_dsi_pdata = {
148         .hw_type = DSIM_TYPE_EXYNOS5422,
149         .host_ops = &exynos_dsi_exynos_host_ops,
150 };
151
152 static const struct samsung_dsim_plat_data exynos5433_dsi_pdata = {
153         .hw_type = DSIM_TYPE_EXYNOS5433,
154         .host_ops = &exynos_dsi_exynos_host_ops,
155 };
156
157 static const struct of_device_id exynos_dsi_of_match[] = {
158         {
159                 .compatible = "samsung,exynos3250-mipi-dsi",
160                 .data = &exynos3250_dsi_pdata,
161         },
162         {
163                 .compatible = "samsung,exynos4210-mipi-dsi",
164                 .data = &exynos4210_dsi_pdata,
165         },
166         {
167                 .compatible = "samsung,exynos5410-mipi-dsi",
168                 .data = &exynos5410_dsi_pdata,
169         },
170         {
171                 .compatible = "samsung,exynos5422-mipi-dsi",
172                 .data = &exynos5422_dsi_pdata,
173         },
174         {
175                 .compatible = "samsung,exynos5433-mipi-dsi",
176                 .data = &exynos5433_dsi_pdata,
177         },
178         { /* sentinel. */ }
179 };
180 MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
181
182 struct platform_driver dsi_driver = {
183         .probe = samsung_dsim_probe,
184         .remove = samsung_dsim_remove,
185         .driver = {
186                    .name = "exynos-dsi",
187                    .owner = THIS_MODULE,
188                    .pm = &samsung_dsim_pm_ops,
189                    .of_match_table = exynos_dsi_of_match,
190         },
191 };
192
193 MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
194 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
195 MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
196 MODULE_LICENSE("GPL v2");