brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · dbea84f Raw
209 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com4 *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>5 */6 7#include <linux/module.h>8#include <linux/of.h>9#include <linux/regulator/consumer.h>10 11#include <drm/drm_crtc.h>12#include <drm/drm_device.h>13#include <drm/drm_mipi_dsi.h>14#include <drm/drm_panel.h>15 16#include <video/mipi_display.h>17 18struct osd101t2587_panel {19	struct drm_panel base;20	struct mipi_dsi_device *dsi;21 22	struct regulator *supply;23 24	const struct drm_display_mode *default_mode;25};26 27static inline struct osd101t2587_panel *ti_osd_panel(struct drm_panel *panel)28{29	return container_of(panel, struct osd101t2587_panel, base);30}31 32static int osd101t2587_panel_disable(struct drm_panel *panel)33{34	struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);35	int ret;36 37	ret = mipi_dsi_shutdown_peripheral(osd101t2587->dsi);38 39	return ret;40}41 42static int osd101t2587_panel_unprepare(struct drm_panel *panel)43{44	struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);45 46	regulator_disable(osd101t2587->supply);47 48	return 0;49}50 51static int osd101t2587_panel_prepare(struct drm_panel *panel)52{53	struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);54 55	return regulator_enable(osd101t2587->supply);56}57 58static int osd101t2587_panel_enable(struct drm_panel *panel)59{60	struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);61	int ret;62 63	ret = mipi_dsi_turn_on_peripheral(osd101t2587->dsi);64	if (ret)65		return ret;66 67	return ret;68}69 70static const struct drm_display_mode default_mode_osd101t2587 = {71	.clock = 164400,72	.hdisplay = 1920,73	.hsync_start = 1920 + 152,74	.hsync_end = 1920 + 152 + 52,75	.htotal = 1920 + 152 + 52 + 20,76	.vdisplay = 1200,77	.vsync_start = 1200 + 24,78	.vsync_end = 1200 + 24 + 6,79	.vtotal = 1200 + 24 + 6 + 48,80	.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,81};82 83static int osd101t2587_panel_get_modes(struct drm_panel *panel,84				       struct drm_connector *connector)85{86	struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);87	struct drm_display_mode *mode;88 89	mode = drm_mode_duplicate(connector->dev, osd101t2587->default_mode);90	if (!mode) {91		dev_err(panel->dev, "failed to add mode %ux%ux@%u\n",92			osd101t2587->default_mode->hdisplay,93			osd101t2587->default_mode->vdisplay,94			drm_mode_vrefresh(osd101t2587->default_mode));95		return -ENOMEM;96	}97 98	drm_mode_set_name(mode);99 100	drm_mode_probed_add(connector, mode);101 102	connector->display_info.width_mm = 217;103	connector->display_info.height_mm = 136;104 105	return 1;106}107 108static const struct drm_panel_funcs osd101t2587_panel_funcs = {109	.disable = osd101t2587_panel_disable,110	.unprepare = osd101t2587_panel_unprepare,111	.prepare = osd101t2587_panel_prepare,112	.enable = osd101t2587_panel_enable,113	.get_modes = osd101t2587_panel_get_modes,114};115 116static const struct of_device_id osd101t2587_of_match[] = {117	{118		.compatible = "osddisplays,osd101t2587-53ts",119		.data = &default_mode_osd101t2587,120	}, {121		/* sentinel */122	}123};124MODULE_DEVICE_TABLE(of, osd101t2587_of_match);125 126static int osd101t2587_panel_add(struct osd101t2587_panel *osd101t2587)127{128	struct device *dev = &osd101t2587->dsi->dev;129	int ret;130 131	osd101t2587->supply = devm_regulator_get(dev, "power");132	if (IS_ERR(osd101t2587->supply))133		return PTR_ERR(osd101t2587->supply);134 135	drm_panel_init(&osd101t2587->base, &osd101t2587->dsi->dev,136		       &osd101t2587_panel_funcs, DRM_MODE_CONNECTOR_DSI);137 138	ret = drm_panel_of_backlight(&osd101t2587->base);139	if (ret)140		return ret;141 142	drm_panel_add(&osd101t2587->base);143 144	return 0;145}146 147static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi)148{149	struct osd101t2587_panel *osd101t2587;150	const struct of_device_id *id;151	int ret;152 153	id = of_match_node(osd101t2587_of_match, dsi->dev.of_node);154	if (!id)155		return -ENODEV;156 157	dsi->lanes = 4;158	dsi->format = MIPI_DSI_FMT_RGB888;159	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |160			  MIPI_DSI_MODE_VIDEO_BURST |161			  MIPI_DSI_MODE_VIDEO_SYNC_PULSE |162			  MIPI_DSI_MODE_NO_EOT_PACKET;163 164	osd101t2587 = devm_kzalloc(&dsi->dev, sizeof(*osd101t2587), GFP_KERNEL);165	if (!osd101t2587)166		return -ENOMEM;167 168	mipi_dsi_set_drvdata(dsi, osd101t2587);169 170	osd101t2587->dsi = dsi;171	osd101t2587->default_mode = id->data;172 173	ret = osd101t2587_panel_add(osd101t2587);174	if (ret < 0)175		return ret;176 177	ret = mipi_dsi_attach(dsi);178	if (ret)179		drm_panel_remove(&osd101t2587->base);180 181	return ret;182}183 184static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi)185{186	struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);187	int ret;188 189	drm_panel_remove(&osd101t2587->base);190 191	ret = mipi_dsi_detach(dsi);192	if (ret < 0)193		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);194}195 196static struct mipi_dsi_driver osd101t2587_panel_driver = {197	.driver = {198		.name = "panel-osd-osd101t2587-53ts",199		.of_match_table = osd101t2587_of_match,200	},201	.probe = osd101t2587_panel_probe,202	.remove = osd101t2587_panel_remove,203};204module_mipi_dsi_driver(osd101t2587_panel_driver);205 206MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");207MODULE_DESCRIPTION("OSD101T2587-53TS DSI panel");208MODULE_LICENSE("GPL v2");209