cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

encoder-tfp410.c (6461B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * TFP410 DPI-to-DVI encoder driver
      4 *
      5 * Copyright (C) 2013 Texas Instruments
      6 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
      7 */
      8
      9#include <linux/gpio.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/slab.h>
     13#include <linux/of_gpio.h>
     14
     15#include <video/omapfb_dss.h>
     16
     17struct panel_drv_data {
     18	struct omap_dss_device dssdev;
     19	struct omap_dss_device *in;
     20
     21	int pd_gpio;
     22	int data_lines;
     23
     24	struct omap_video_timings timings;
     25};
     26
     27#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
     28
     29static int tfp410_connect(struct omap_dss_device *dssdev,
     30		struct omap_dss_device *dst)
     31{
     32	struct panel_drv_data *ddata = to_panel_data(dssdev);
     33	struct omap_dss_device *in = ddata->in;
     34	int r;
     35
     36	if (omapdss_device_is_connected(dssdev))
     37		return -EBUSY;
     38
     39	r = in->ops.dpi->connect(in, dssdev);
     40	if (r)
     41		return r;
     42
     43	dst->src = dssdev;
     44	dssdev->dst = dst;
     45
     46	return 0;
     47}
     48
     49static void tfp410_disconnect(struct omap_dss_device *dssdev,
     50		struct omap_dss_device *dst)
     51{
     52	struct panel_drv_data *ddata = to_panel_data(dssdev);
     53	struct omap_dss_device *in = ddata->in;
     54
     55	WARN_ON(!omapdss_device_is_connected(dssdev));
     56	if (!omapdss_device_is_connected(dssdev))
     57		return;
     58
     59	WARN_ON(dst != dssdev->dst);
     60	if (dst != dssdev->dst)
     61		return;
     62
     63	dst->src = NULL;
     64	dssdev->dst = NULL;
     65
     66	in->ops.dpi->disconnect(in, &ddata->dssdev);
     67}
     68
     69static int tfp410_enable(struct omap_dss_device *dssdev)
     70{
     71	struct panel_drv_data *ddata = to_panel_data(dssdev);
     72	struct omap_dss_device *in = ddata->in;
     73	int r;
     74
     75	if (!omapdss_device_is_connected(dssdev))
     76		return -ENODEV;
     77
     78	if (omapdss_device_is_enabled(dssdev))
     79		return 0;
     80
     81	in->ops.dpi->set_timings(in, &ddata->timings);
     82	if (ddata->data_lines)
     83		in->ops.dpi->set_data_lines(in, ddata->data_lines);
     84
     85	r = in->ops.dpi->enable(in);
     86	if (r)
     87		return r;
     88
     89	if (gpio_is_valid(ddata->pd_gpio))
     90		gpio_set_value_cansleep(ddata->pd_gpio, 1);
     91
     92	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
     93
     94	return 0;
     95}
     96
     97static void tfp410_disable(struct omap_dss_device *dssdev)
     98{
     99	struct panel_drv_data *ddata = to_panel_data(dssdev);
    100	struct omap_dss_device *in = ddata->in;
    101
    102	if (!omapdss_device_is_enabled(dssdev))
    103		return;
    104
    105	if (gpio_is_valid(ddata->pd_gpio))
    106		gpio_set_value_cansleep(ddata->pd_gpio, 0);
    107
    108	in->ops.dpi->disable(in);
    109
    110	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    111}
    112
    113static void tfp410_fix_timings(struct omap_video_timings *timings)
    114{
    115	timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
    116	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
    117	timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
    118}
    119
    120static void tfp410_set_timings(struct omap_dss_device *dssdev,
    121		struct omap_video_timings *timings)
    122{
    123	struct panel_drv_data *ddata = to_panel_data(dssdev);
    124	struct omap_dss_device *in = ddata->in;
    125
    126	tfp410_fix_timings(timings);
    127
    128	ddata->timings = *timings;
    129	dssdev->panel.timings = *timings;
    130
    131	in->ops.dpi->set_timings(in, timings);
    132}
    133
    134static void tfp410_get_timings(struct omap_dss_device *dssdev,
    135		struct omap_video_timings *timings)
    136{
    137	struct panel_drv_data *ddata = to_panel_data(dssdev);
    138
    139	*timings = ddata->timings;
    140}
    141
    142static int tfp410_check_timings(struct omap_dss_device *dssdev,
    143		struct omap_video_timings *timings)
    144{
    145	struct panel_drv_data *ddata = to_panel_data(dssdev);
    146	struct omap_dss_device *in = ddata->in;
    147
    148	tfp410_fix_timings(timings);
    149
    150	return in->ops.dpi->check_timings(in, timings);
    151}
    152
    153static const struct omapdss_dvi_ops tfp410_dvi_ops = {
    154	.connect	= tfp410_connect,
    155	.disconnect	= tfp410_disconnect,
    156
    157	.enable		= tfp410_enable,
    158	.disable	= tfp410_disable,
    159
    160	.check_timings	= tfp410_check_timings,
    161	.set_timings	= tfp410_set_timings,
    162	.get_timings	= tfp410_get_timings,
    163};
    164
    165static int tfp410_probe_of(struct platform_device *pdev)
    166{
    167	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    168	struct device_node *node = pdev->dev.of_node;
    169	struct omap_dss_device *in;
    170	int gpio;
    171
    172	gpio = of_get_named_gpio(node, "powerdown-gpios", 0);
    173
    174	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
    175		ddata->pd_gpio = gpio;
    176	} else {
    177		dev_err(&pdev->dev, "failed to parse PD gpio\n");
    178		return gpio;
    179	}
    180
    181	in = omapdss_of_find_source_for_first_ep(node);
    182	if (IS_ERR(in)) {
    183		dev_err(&pdev->dev, "failed to find video source\n");
    184		return PTR_ERR(in);
    185	}
    186
    187	ddata->in = in;
    188
    189	return 0;
    190}
    191
    192static int tfp410_probe(struct platform_device *pdev)
    193{
    194	struct panel_drv_data *ddata;
    195	struct omap_dss_device *dssdev;
    196	int r;
    197
    198	if (!pdev->dev.of_node)
    199		return -ENODEV;
    200
    201	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
    202	if (!ddata)
    203		return -ENOMEM;
    204
    205	platform_set_drvdata(pdev, ddata);
    206
    207	r = tfp410_probe_of(pdev);
    208	if (r)
    209		return r;
    210
    211	if (gpio_is_valid(ddata->pd_gpio)) {
    212		r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
    213				GPIOF_OUT_INIT_LOW, "tfp410 PD");
    214		if (r) {
    215			dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
    216					ddata->pd_gpio);
    217			goto err_gpio;
    218		}
    219	}
    220
    221	dssdev = &ddata->dssdev;
    222	dssdev->ops.dvi = &tfp410_dvi_ops;
    223	dssdev->dev = &pdev->dev;
    224	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
    225	dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
    226	dssdev->owner = THIS_MODULE;
    227	dssdev->phy.dpi.data_lines = ddata->data_lines;
    228	dssdev->port_num = 1;
    229
    230	r = omapdss_register_output(dssdev);
    231	if (r) {
    232		dev_err(&pdev->dev, "Failed to register output\n");
    233		goto err_reg;
    234	}
    235
    236	return 0;
    237err_reg:
    238err_gpio:
    239	omap_dss_put_device(ddata->in);
    240	return r;
    241}
    242
    243static int __exit tfp410_remove(struct platform_device *pdev)
    244{
    245	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    246	struct omap_dss_device *dssdev = &ddata->dssdev;
    247	struct omap_dss_device *in = ddata->in;
    248
    249	omapdss_unregister_output(&ddata->dssdev);
    250
    251	WARN_ON(omapdss_device_is_enabled(dssdev));
    252	if (omapdss_device_is_enabled(dssdev))
    253		tfp410_disable(dssdev);
    254
    255	WARN_ON(omapdss_device_is_connected(dssdev));
    256	if (omapdss_device_is_connected(dssdev))
    257		tfp410_disconnect(dssdev, dssdev->dst);
    258
    259	omap_dss_put_device(in);
    260
    261	return 0;
    262}
    263
    264static const struct of_device_id tfp410_of_match[] = {
    265	{ .compatible = "omapdss,ti,tfp410", },
    266	{},
    267};
    268
    269MODULE_DEVICE_TABLE(of, tfp410_of_match);
    270
    271static struct platform_driver tfp410_driver = {
    272	.probe	= tfp410_probe,
    273	.remove	= __exit_p(tfp410_remove),
    274	.driver	= {
    275		.name	= "tfp410",
    276		.of_match_table = tfp410_of_match,
    277		.suppress_bind_attrs = true,
    278	},
    279};
    280
    281module_platform_driver(tfp410_driver);
    282
    283MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
    284MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
    285MODULE_LICENSE("GPL");