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

connector-analog-tv.c (6667B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Analog TV Connector driver
      4 *
      5 * Copyright (C) 2013 Texas Instruments
      6 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
      7 */
      8
      9#include <linux/slab.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/of.h>
     13
     14#include <video/omapfb_dss.h>
     15#include <video/omap-panel-data.h>
     16
     17struct panel_drv_data {
     18	struct omap_dss_device dssdev;
     19	struct omap_dss_device *in;
     20
     21	struct device *dev;
     22
     23	struct omap_video_timings timings;
     24
     25	bool invert_polarity;
     26};
     27
     28static const struct omap_video_timings tvc_pal_timings = {
     29	.x_res		= 720,
     30	.y_res		= 574,
     31	.pixelclock	= 13500000,
     32	.hsw		= 64,
     33	.hfp		= 12,
     34	.hbp		= 68,
     35	.vsw		= 5,
     36	.vfp		= 5,
     37	.vbp		= 41,
     38
     39	.interlace	= true,
     40};
     41
     42static const struct of_device_id tvc_of_match[];
     43
     44#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
     45
     46static int tvc_connect(struct omap_dss_device *dssdev)
     47{
     48	struct panel_drv_data *ddata = to_panel_data(dssdev);
     49	struct omap_dss_device *in = ddata->in;
     50
     51	dev_dbg(ddata->dev, "connect\n");
     52
     53	if (omapdss_device_is_connected(dssdev))
     54		return 0;
     55
     56	return in->ops.atv->connect(in, dssdev);
     57}
     58
     59static void tvc_disconnect(struct omap_dss_device *dssdev)
     60{
     61	struct panel_drv_data *ddata = to_panel_data(dssdev);
     62	struct omap_dss_device *in = ddata->in;
     63
     64	dev_dbg(ddata->dev, "disconnect\n");
     65
     66	if (!omapdss_device_is_connected(dssdev))
     67		return;
     68
     69	in->ops.atv->disconnect(in, dssdev);
     70}
     71
     72static int tvc_enable(struct omap_dss_device *dssdev)
     73{
     74	struct panel_drv_data *ddata = to_panel_data(dssdev);
     75	struct omap_dss_device *in = ddata->in;
     76	int r;
     77
     78	dev_dbg(ddata->dev, "enable\n");
     79
     80	if (!omapdss_device_is_connected(dssdev))
     81		return -ENODEV;
     82
     83	if (omapdss_device_is_enabled(dssdev))
     84		return 0;
     85
     86	in->ops.atv->set_timings(in, &ddata->timings);
     87
     88	if (!ddata->dev->of_node) {
     89		in->ops.atv->set_type(in, OMAP_DSS_VENC_TYPE_COMPOSITE);
     90
     91		in->ops.atv->invert_vid_out_polarity(in,
     92			ddata->invert_polarity);
     93	}
     94
     95	r = in->ops.atv->enable(in);
     96	if (r)
     97		return r;
     98
     99	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
    100
    101	return r;
    102}
    103
    104static void tvc_disable(struct omap_dss_device *dssdev)
    105{
    106	struct panel_drv_data *ddata = to_panel_data(dssdev);
    107	struct omap_dss_device *in = ddata->in;
    108
    109	dev_dbg(ddata->dev, "disable\n");
    110
    111	if (!omapdss_device_is_enabled(dssdev))
    112		return;
    113
    114	in->ops.atv->disable(in);
    115
    116	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    117}
    118
    119static void tvc_set_timings(struct omap_dss_device *dssdev,
    120		struct omap_video_timings *timings)
    121{
    122	struct panel_drv_data *ddata = to_panel_data(dssdev);
    123	struct omap_dss_device *in = ddata->in;
    124
    125	ddata->timings = *timings;
    126	dssdev->panel.timings = *timings;
    127
    128	in->ops.atv->set_timings(in, timings);
    129}
    130
    131static void tvc_get_timings(struct omap_dss_device *dssdev,
    132		struct omap_video_timings *timings)
    133{
    134	struct panel_drv_data *ddata = to_panel_data(dssdev);
    135
    136	*timings = ddata->timings;
    137}
    138
    139static int tvc_check_timings(struct omap_dss_device *dssdev,
    140		struct omap_video_timings *timings)
    141{
    142	struct panel_drv_data *ddata = to_panel_data(dssdev);
    143	struct omap_dss_device *in = ddata->in;
    144
    145	return in->ops.atv->check_timings(in, timings);
    146}
    147
    148static u32 tvc_get_wss(struct omap_dss_device *dssdev)
    149{
    150	struct panel_drv_data *ddata = to_panel_data(dssdev);
    151	struct omap_dss_device *in = ddata->in;
    152
    153	return in->ops.atv->get_wss(in);
    154}
    155
    156static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
    157{
    158	struct panel_drv_data *ddata = to_panel_data(dssdev);
    159	struct omap_dss_device *in = ddata->in;
    160
    161	return in->ops.atv->set_wss(in, wss);
    162}
    163
    164static struct omap_dss_driver tvc_driver = {
    165	.connect		= tvc_connect,
    166	.disconnect		= tvc_disconnect,
    167
    168	.enable			= tvc_enable,
    169	.disable		= tvc_disable,
    170
    171	.set_timings		= tvc_set_timings,
    172	.get_timings		= tvc_get_timings,
    173	.check_timings		= tvc_check_timings,
    174
    175	.get_resolution		= omapdss_default_get_resolution,
    176
    177	.get_wss		= tvc_get_wss,
    178	.set_wss		= tvc_set_wss,
    179};
    180
    181static int tvc_probe_pdata(struct platform_device *pdev)
    182{
    183	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    184	struct connector_atv_platform_data *pdata;
    185	struct omap_dss_device *in, *dssdev;
    186
    187	pdata = dev_get_platdata(&pdev->dev);
    188
    189	in = omap_dss_find_output(pdata->source);
    190	if (in == NULL) {
    191		dev_err(&pdev->dev, "Failed to find video source\n");
    192		return -EPROBE_DEFER;
    193	}
    194
    195	ddata->in = in;
    196
    197	ddata->invert_polarity = pdata->invert_polarity;
    198
    199	dssdev = &ddata->dssdev;
    200	dssdev->name = pdata->name;
    201
    202	return 0;
    203}
    204
    205static int tvc_probe_of(struct platform_device *pdev)
    206{
    207	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    208	struct device_node *node = pdev->dev.of_node;
    209	struct omap_dss_device *in;
    210
    211	in = omapdss_of_find_source_for_first_ep(node);
    212	if (IS_ERR(in)) {
    213		dev_err(&pdev->dev, "failed to find video source\n");
    214		return PTR_ERR(in);
    215	}
    216
    217	ddata->in = in;
    218
    219	return 0;
    220}
    221
    222static int tvc_probe(struct platform_device *pdev)
    223{
    224	struct panel_drv_data *ddata;
    225	struct omap_dss_device *dssdev;
    226	int r;
    227
    228	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
    229	if (!ddata)
    230		return -ENOMEM;
    231
    232	platform_set_drvdata(pdev, ddata);
    233	ddata->dev = &pdev->dev;
    234
    235	if (dev_get_platdata(&pdev->dev)) {
    236		r = tvc_probe_pdata(pdev);
    237		if (r)
    238			return r;
    239	} else if (pdev->dev.of_node) {
    240		r = tvc_probe_of(pdev);
    241		if (r)
    242			return r;
    243	} else {
    244		return -ENODEV;
    245	}
    246
    247	ddata->timings = tvc_pal_timings;
    248
    249	dssdev = &ddata->dssdev;
    250	dssdev->driver = &tvc_driver;
    251	dssdev->dev = &pdev->dev;
    252	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
    253	dssdev->owner = THIS_MODULE;
    254	dssdev->panel.timings = tvc_pal_timings;
    255
    256	r = omapdss_register_display(dssdev);
    257	if (r) {
    258		dev_err(&pdev->dev, "Failed to register panel\n");
    259		goto err_reg;
    260	}
    261
    262	return 0;
    263err_reg:
    264	omap_dss_put_device(ddata->in);
    265	return r;
    266}
    267
    268static int __exit tvc_remove(struct platform_device *pdev)
    269{
    270	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    271	struct omap_dss_device *dssdev = &ddata->dssdev;
    272	struct omap_dss_device *in = ddata->in;
    273
    274	omapdss_unregister_display(&ddata->dssdev);
    275
    276	tvc_disable(dssdev);
    277	tvc_disconnect(dssdev);
    278
    279	omap_dss_put_device(in);
    280
    281	return 0;
    282}
    283
    284static const struct of_device_id tvc_of_match[] = {
    285	{ .compatible = "omapdss,svideo-connector", },
    286	{ .compatible = "omapdss,composite-video-connector", },
    287	{},
    288};
    289
    290MODULE_DEVICE_TABLE(of, tvc_of_match);
    291
    292static struct platform_driver tvc_connector_driver = {
    293	.probe	= tvc_probe,
    294	.remove	= __exit_p(tvc_remove),
    295	.driver	= {
    296		.name	= "connector-analog-tv",
    297		.of_match_table = tvc_of_match,
    298		.suppress_bind_attrs = true,
    299	},
    300};
    301
    302module_platform_driver(tvc_connector_driver);
    303
    304MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
    305MODULE_DESCRIPTION("Analog TV Connector driver");
    306MODULE_LICENSE("GPL");