brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 22f4262 Raw
249 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Generic MIPI DPI Panel Driver4 *5 * Copyright (C) 2013 Texas Instruments6 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>7 */8 9#include <linux/gpio/consumer.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/slab.h>13#include <linux/of.h>14 15#include <video/omapfb_dss.h>16#include <video/of_display_timing.h>17 18struct panel_drv_data {19	struct omap_dss_device dssdev;20	struct omap_dss_device *in;21 22	int data_lines;23 24	struct omap_video_timings videomode;25 26	struct gpio_desc *enable_gpio;27};28 29#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)30 31static int panel_dpi_connect(struct omap_dss_device *dssdev)32{33	struct panel_drv_data *ddata = to_panel_data(dssdev);34	struct omap_dss_device *in = ddata->in;35 36	if (omapdss_device_is_connected(dssdev))37		return 0;38 39	return in->ops.dpi->connect(in, dssdev);40}41 42static void panel_dpi_disconnect(struct omap_dss_device *dssdev)43{44	struct panel_drv_data *ddata = to_panel_data(dssdev);45	struct omap_dss_device *in = ddata->in;46 47	if (!omapdss_device_is_connected(dssdev))48		return;49 50	in->ops.dpi->disconnect(in, dssdev);51}52 53static int panel_dpi_enable(struct omap_dss_device *dssdev)54{55	struct panel_drv_data *ddata = to_panel_data(dssdev);56	struct omap_dss_device *in = ddata->in;57	int r;58 59	if (!omapdss_device_is_connected(dssdev))60		return -ENODEV;61 62	if (omapdss_device_is_enabled(dssdev))63		return 0;64 65	if (ddata->data_lines)66		in->ops.dpi->set_data_lines(in, ddata->data_lines);67	in->ops.dpi->set_timings(in, &ddata->videomode);68 69	r = in->ops.dpi->enable(in);70	if (r)71		return r;72 73	gpiod_set_value_cansleep(ddata->enable_gpio, 1);74 75	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;76 77	return 0;78}79 80static void panel_dpi_disable(struct omap_dss_device *dssdev)81{82	struct panel_drv_data *ddata = to_panel_data(dssdev);83	struct omap_dss_device *in = ddata->in;84 85	if (!omapdss_device_is_enabled(dssdev))86		return;87 88	gpiod_set_value_cansleep(ddata->enable_gpio, 0);89 90	in->ops.dpi->disable(in);91 92	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;93}94 95static void panel_dpi_set_timings(struct omap_dss_device *dssdev,96		struct omap_video_timings *timings)97{98	struct panel_drv_data *ddata = to_panel_data(dssdev);99	struct omap_dss_device *in = ddata->in;100 101	ddata->videomode = *timings;102	dssdev->panel.timings = *timings;103 104	in->ops.dpi->set_timings(in, timings);105}106 107static void panel_dpi_get_timings(struct omap_dss_device *dssdev,108		struct omap_video_timings *timings)109{110	struct panel_drv_data *ddata = to_panel_data(dssdev);111 112	*timings = ddata->videomode;113}114 115static int panel_dpi_check_timings(struct omap_dss_device *dssdev,116		struct omap_video_timings *timings)117{118	struct panel_drv_data *ddata = to_panel_data(dssdev);119	struct omap_dss_device *in = ddata->in;120 121	return in->ops.dpi->check_timings(in, timings);122}123 124static struct omap_dss_driver panel_dpi_ops = {125	.connect	= panel_dpi_connect,126	.disconnect	= panel_dpi_disconnect,127 128	.enable		= panel_dpi_enable,129	.disable	= panel_dpi_disable,130 131	.set_timings	= panel_dpi_set_timings,132	.get_timings	= panel_dpi_get_timings,133	.check_timings	= panel_dpi_check_timings,134 135	.get_resolution	= omapdss_default_get_resolution,136};137 138static int panel_dpi_probe_of(struct platform_device *pdev)139{140	struct panel_drv_data *ddata = platform_get_drvdata(pdev);141	struct device_node *node = pdev->dev.of_node;142	struct omap_dss_device *in;143	int r;144	struct display_timing timing;145	struct videomode vm;146	struct gpio_desc *gpio;147 148	gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);149	if (IS_ERR(gpio))150		return PTR_ERR(gpio);151 152	ddata->enable_gpio = gpio;153 154	r = of_get_display_timing(node, "panel-timing", &timing);155	if (r) {156		dev_err(&pdev->dev, "failed to get video timing\n");157		return r;158	}159 160	videomode_from_timing(&timing, &vm);161	videomode_to_omap_video_timings(&vm, &ddata->videomode);162 163	in = omapdss_of_find_source_for_first_ep(node);164	if (IS_ERR(in)) {165		dev_err(&pdev->dev, "failed to find video source\n");166		return PTR_ERR(in);167	}168 169	ddata->in = in;170 171	return 0;172}173 174static int panel_dpi_probe(struct platform_device *pdev)175{176	struct panel_drv_data *ddata;177	struct omap_dss_device *dssdev;178	int r;179 180	if (!pdev->dev.of_node)181		return -ENODEV;182 183	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);184	if (ddata == NULL)185		return -ENOMEM;186 187	platform_set_drvdata(pdev, ddata);188 189	r = panel_dpi_probe_of(pdev);190	if (r)191		return r;192 193	dssdev = &ddata->dssdev;194	dssdev->dev = &pdev->dev;195	dssdev->driver = &panel_dpi_ops;196	dssdev->type = OMAP_DISPLAY_TYPE_DPI;197	dssdev->owner = THIS_MODULE;198	dssdev->panel.timings = ddata->videomode;199	dssdev->phy.dpi.data_lines = ddata->data_lines;200 201	r = omapdss_register_display(dssdev);202	if (r) {203		dev_err(&pdev->dev, "Failed to register panel\n");204		goto err_reg;205	}206 207	return 0;208 209err_reg:210	omap_dss_put_device(ddata->in);211	return r;212}213 214static void panel_dpi_remove(struct platform_device *pdev)215{216	struct panel_drv_data *ddata = platform_get_drvdata(pdev);217	struct omap_dss_device *dssdev = &ddata->dssdev;218	struct omap_dss_device *in = ddata->in;219 220	omapdss_unregister_display(dssdev);221 222	panel_dpi_disable(dssdev);223	panel_dpi_disconnect(dssdev);224 225	omap_dss_put_device(in);226}227 228static const struct of_device_id panel_dpi_of_match[] = {229	{ .compatible = "omapdss,panel-dpi", },230	{},231};232 233MODULE_DEVICE_TABLE(of, panel_dpi_of_match);234 235static struct platform_driver panel_dpi_driver = {236	.probe = panel_dpi_probe,237	.remove = panel_dpi_remove,238	.driver = {239		.name = "panel-dpi",240		.of_match_table = panel_dpi_of_match,241	},242};243 244module_platform_driver(panel_dpi_driver);245 246MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");247MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");248MODULE_LICENSE("GPL");249