Merge tag 'soc-ep93xx-dt-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-block.git] / drivers / gpu / drm / exynos / exynos_drm_dsi.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
7eb8f069 2/*
e7447128 3 * Samsung MIPI DSIM glue for Exynos SoCs.
7eb8f069
AH
4 *
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd
6 *
7 * Contacts: Tomasz Figa <t.figa@samsung.com>
44d214a7 8 */
295e7954 9
e7447128 10#include <linux/component.h>
722d4f06
RH
11#include <linux/of.h>
12#include <linux/platform_device.h>
295e7954 13
e7447128
JT
14#include <drm/bridge/samsung-dsim.h>
15#include <drm/drm_probe_helper.h>
16#include <drm/drm_simple_kms_helper.h>
295e7954 17
e7447128
JT
18#include "exynos_drm_crtc.h"
19#include "exynos_drm_drv.h"
295e7954 20
e7447128
JT
21struct exynos_dsi {
22 struct drm_encoder encoder;
295e7954
AH
23};
24
e7447128 25static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
48b64ba8 26{
e7447128
JT
27 struct exynos_dsi *dsi = dsim->priv;
28 struct drm_encoder *encoder = &dsi->encoder;
48b64ba8
JT
29
30 if (dsim->state & DSIM_STATE_VIDOUT_AVAILABLE)
31 exynos_drm_crtc_te_handler(encoder->crtc);
32
33 return IRQ_HANDLED;
34}
35
e7447128
JT
36static int exynos_dsi_host_attach(struct samsung_dsim *dsim,
37 struct mipi_dsi_device *device)
70e360f9 38{
e7447128
JT
39 struct exynos_dsi *dsi = dsim->priv;
40 struct drm_encoder *encoder = &dsi->encoder;
70e360f9
JT
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
e7447128
JT
64static void exynos_dsi_host_detach(struct samsung_dsim *dsim,
65 struct mipi_dsi_device *device)
70e360f9 66{
e7447128
JT
67 struct exynos_dsi *dsi = dsim->priv;
68 struct drm_device *drm = dsi->encoder.dev;
70e360f9
JT
69
70 if (drm->mode_config.poll_enabled)
71 drm_kms_helper_hotplug_event(drm);
72}
73
e7447128 74static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
f37cd5e8 75{
e7447128
JT
76 struct samsung_dsim *dsim = dev_get_drvdata(dev);
77 struct exynos_dsi *dsi = dsim->priv;
78 struct drm_encoder *encoder = &dsi->encoder;
f37cd5e8 79 struct drm_device *drm_dev = data;
f37cd5e8
ID
80 int ret;
81
3e1fe32d 82 drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
2b8376c8 83
1ca582f1
AH
84 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
85 if (ret < 0)
86 return ret;
87
e7447128 88 return mipi_dsi_host_register(&dsim->dsi_host);
f37cd5e8
ID
89}
90
e7447128 91static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
f37cd5e8 92{
e7447128 93 struct samsung_dsim *dsim = dev_get_drvdata(dev);
f37cd5e8 94
e7447128 95 dsim->bridge.funcs->atomic_disable(&dsim->bridge, NULL);
f37cd5e8 96
e7447128 97 mipi_dsi_host_unregister(&dsim->dsi_host);
f37cd5e8
ID
98}
99
f37cd5e8
ID
100static const struct component_ops exynos_dsi_component_ops = {
101 .bind = exynos_dsi_bind,
102 .unbind = exynos_dsi_unbind,
103};
104
e7447128 105static int exynos_dsi_register_host(struct samsung_dsim *dsim)
70e360f9 106{
e7447128 107 struct exynos_dsi *dsi;
70e360f9 108
e7447128
JT
109 dsi = devm_kzalloc(dsim->dev, sizeof(*dsi), GFP_KERNEL);
110 if (!dsi)
70e360f9
JT
111 return -ENOMEM;
112
e7447128 113 dsim->priv = dsi;
70e360f9
JT
114 dsim->bridge.pre_enable_prev_first = true;
115
116 return component_add(dsim->dev, &exynos_dsi_component_ops);
117}
118
e7447128 119static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)
70e360f9
JT
120{
121 component_del(dsim->dev, &exynos_dsi_component_ops);
122}
123
e7447128 124static const struct samsung_dsim_host_ops exynos_dsi_exynos_host_ops = {
70e360f9
JT
125 .register_host = exynos_dsi_register_host,
126 .unregister_host = exynos_dsi_unregister_host,
e7447128
JT
127 .attach = exynos_dsi_host_attach,
128 .detach = exynos_dsi_host_detach,
129 .te_irq_handler = exynos_dsi_te_irq_handler,
70e360f9
JT
130};
131
e7447128 132static const struct samsung_dsim_plat_data exynos3250_dsi_pdata = {
7e9f0d32 133 .hw_type = DSIM_TYPE_EXYNOS3250,
e7447128 134 .host_ops = &exynos_dsi_exynos_host_ops,
7e9f0d32
JT
135};
136
e7447128 137static const struct samsung_dsim_plat_data exynos4210_dsi_pdata = {
7e9f0d32 138 .hw_type = DSIM_TYPE_EXYNOS4210,
e7447128 139 .host_ops = &exynos_dsi_exynos_host_ops,
7e9f0d32
JT
140};
141
e7447128 142static const struct samsung_dsim_plat_data exynos5410_dsi_pdata = {
7e9f0d32 143 .hw_type = DSIM_TYPE_EXYNOS5410,
e7447128 144 .host_ops = &exynos_dsi_exynos_host_ops,
7e9f0d32
JT
145};
146
e7447128 147static const struct samsung_dsim_plat_data exynos5422_dsi_pdata = {
7e9f0d32 148 .hw_type = DSIM_TYPE_EXYNOS5422,
e7447128 149 .host_ops = &exynos_dsi_exynos_host_ops,
7e9f0d32
JT
150};
151
e7447128 152static const struct samsung_dsim_plat_data exynos5433_dsi_pdata = {
7e9f0d32 153 .hw_type = DSIM_TYPE_EXYNOS5433,
e7447128 154 .host_ops = &exynos_dsi_exynos_host_ops,
7e9f0d32
JT
155};
156
157static 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};
180MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
181
7eb8f069 182struct platform_driver dsi_driver = {
e7447128 183 .probe = samsung_dsim_probe,
c1698c73 184 .remove_new = samsung_dsim_remove,
7eb8f069
AH
185 .driver = {
186 .name = "exynos-dsi",
e7447128 187 .pm = &samsung_dsim_pm_ops,
7eb8f069
AH
188 .of_match_table = exynos_dsi_of_match,
189 },
190};
191
192MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
193MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
194MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
195MODULE_LICENSE("GPL v2");