brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · bf16dea Raw
196 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Samsung MIPI DSIM glue for Exynos SoCs.4 *5 * Copyright (c) 2014 Samsung Electronics Co., Ltd6 *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 21struct exynos_dsi {22	struct drm_encoder encoder;23};24 25static 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 36static 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 64static 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 74static 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 91static 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 100static const struct component_ops exynos_dsi_component_ops = {101	.bind	= exynos_dsi_bind,102	.unbind	= exynos_dsi_unbind,103};104 105static 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 119static void exynos_dsi_unregister_host(struct samsung_dsim *dsim)120{121	component_del(dsim->dev, &exynos_dsi_component_ops);122}123 124static 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 132static 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 137static 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 142static 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 147static 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 152static 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 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 182struct platform_driver dsi_driver = {183	.probe = samsung_dsim_probe,184	.remove_new = samsung_dsim_remove,185	.driver = {186		   .name = "exynos-dsi",187		   .pm = &samsung_dsim_pm_ops,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");196