Contributors: 17
Author |
Tokens |
Token Proportion |
Commits |
Commit Proportion |
Jagan Teki |
508 |
63.18% |
7 |
20.00% |
Inki Dae |
131 |
16.29% |
4 |
11.43% |
Andrzej Hajda |
115 |
14.30% |
8 |
22.86% |
Christophe Jaillet |
11 |
1.37% |
1 |
2.86% |
Gustavo Padovan |
8 |
1.00% |
3 |
8.57% |
Michael Tretter |
7 |
0.87% |
1 |
2.86% |
YoungJun Cho |
6 |
0.75% |
1 |
2.86% |
Sascha Hauer |
3 |
0.37% |
1 |
2.86% |
Thomas Zimmermann |
3 |
0.37% |
1 |
2.86% |
Marek Szyprowski |
3 |
0.37% |
1 |
2.86% |
Hyungwon Hwang |
3 |
0.37% |
1 |
2.86% |
Sam Ravnborg |
1 |
0.12% |
1 |
2.86% |
Boris Brezillon |
1 |
0.12% |
1 |
2.86% |
Rob Herring |
1 |
0.12% |
1 |
2.86% |
Uwe Kleine-König |
1 |
0.12% |
1 |
2.86% |
Thomas Gleixner |
1 |
0.12% |
1 |
2.86% |
Daniel Vetter |
1 |
0.12% |
1 |
2.86% |
Total |
804 |
|
35 |
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* Samsung MIPI DSIM glue for Exynos SoCs.
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd
*
* Contacts: Tomasz Figa <t.figa@samsung.com>
*/
#include <linux/component.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <drm/bridge/samsung-dsim.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
struct exynos_dsi {
struct drm_encoder encoder;
};
static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
{
struct exynos_dsi *dsi = dsim->priv;
struct drm_encoder *encoder = &dsi->encoder;
if (dsim->state & DSIM_STATE_VIDOUT_AVAILABLE)
exynos_drm_crtc_te_handler(encoder->crtc);
return IRQ_HANDLED;
}
static int exynos_dsi_host_attach(struct samsung_dsim *dsim,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = dsim->priv;
struct drm_encoder *encoder = &dsi->encoder;
struct drm_device *drm = encoder->dev;
drm_bridge_attach(encoder, &dsim->bridge,
list_first_entry_or_null(&encoder->bridge_chain,
struct drm_bridge,
chain_node), 0);
mutex_lock(&drm->mode_config.mutex);
dsim->lanes = device->lanes;
dsim->format = device->format;
dsim->mode_flags = device->mode_flags;
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsim->mode_flags & MIPI_DSI_MODE_VIDEO);
mutex_unlock(&drm->mode_config.mutex);
if (drm->mode_config.poll_enabled)
drm_kms_helper_hotplug_event(drm);
return 0;
}
static void exynos_dsi_host_detach(struct samsung_dsim *dsim,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = dsim->priv;
struct drm_device *drm = dsi->encoder.dev;
if (drm->mode_config.poll_enabled)
drm_kms_helper_hotplug_event(drm);
}
static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
{
struct samsung_dsim *dsim = dev_get_drvdata(dev);
struct exynos_dsi *dsi = dsim->priv;
struct drm_encoder *encoder = &dsi->encoder;
struct drm_device *drm_dev = data;
int ret;
drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
if (ret < 0)
return ret;
return mipi_dsi_host_register(&dsim->dsi_host);
}
static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
{
struct samsung_dsim *dsim = dev_get_drvdata(dev);
dsim->bridge.funcs->atomic_disable(&dsim->bridge, NULL);
mipi_dsi_host_unregister(&dsim->dsi_host);
}
static const struct component_ops exynos_dsi_component_ops = {
.bind = exynos_dsi_bind,
.unbind = exynos_dsi_unbind,
};
static int exynos_dsi_register_host(struct samsung_dsim *dsim)
{
struct exynos_dsi *dsi;
dsi = devm_kzalloc(dsim->dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
dsim->priv = dsi;
dsim->bridge.pre_enable_prev_first = true;
return component_add(dsim->dev, &exynos_dsi_component_ops);
}
static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)
{
component_del(dsim->dev, &exynos_dsi_component_ops);
}
static const struct samsung_dsim_host_ops exynos_dsi_exynos_host_ops = {
.register_host = exynos_dsi_register_host,
.unregister_host = exynos_dsi_unregister_host,
.attach = exynos_dsi_host_attach,
.detach = exynos_dsi_host_detach,
.te_irq_handler = exynos_dsi_te_irq_handler,
};
static const struct samsung_dsim_plat_data exynos3250_dsi_pdata = {
.hw_type = DSIM_TYPE_EXYNOS3250,
.host_ops = &exynos_dsi_exynos_host_ops,
};
static const struct samsung_dsim_plat_data exynos4210_dsi_pdata = {
.hw_type = DSIM_TYPE_EXYNOS4210,
.host_ops = &exynos_dsi_exynos_host_ops,
};
static const struct samsung_dsim_plat_data exynos5410_dsi_pdata = {
.hw_type = DSIM_TYPE_EXYNOS5410,
.host_ops = &exynos_dsi_exynos_host_ops,
};
static const struct samsung_dsim_plat_data exynos5422_dsi_pdata = {
.hw_type = DSIM_TYPE_EXYNOS5422,
.host_ops = &exynos_dsi_exynos_host_ops,
};
static const struct samsung_dsim_plat_data exynos5433_dsi_pdata = {
.hw_type = DSIM_TYPE_EXYNOS5433,
.host_ops = &exynos_dsi_exynos_host_ops,
};
static const struct of_device_id exynos_dsi_of_match[] = {
{
.compatible = "samsung,exynos3250-mipi-dsi",
.data = &exynos3250_dsi_pdata,
},
{
.compatible = "samsung,exynos4210-mipi-dsi",
.data = &exynos4210_dsi_pdata,
},
{
.compatible = "samsung,exynos5410-mipi-dsi",
.data = &exynos5410_dsi_pdata,
},
{
.compatible = "samsung,exynos5422-mipi-dsi",
.data = &exynos5422_dsi_pdata,
},
{
.compatible = "samsung,exynos5433-mipi-dsi",
.data = &exynos5433_dsi_pdata,
},
{ /* sentinel. */ }
};
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
struct platform_driver dsi_driver = {
.probe = samsung_dsim_probe,
.remove_new = samsung_dsim_remove,
.driver = {
.name = "exynos-dsi",
.pm = &samsung_dsim_pm_ops,
.of_match_table = exynos_dsi_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_LICENSE("GPL v2");