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-hdmi.c (6934B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HDMI 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#include <linux/of_gpio.h>
     14
     15#include <drm/drm_edid.h>
     16
     17#include <video/omapfb_dss.h>
     18
     19static const struct omap_video_timings hdmic_default_timings = {
     20	.x_res		= 640,
     21	.y_res		= 480,
     22	.pixelclock	= 25175000,
     23	.hsw		= 96,
     24	.hfp		= 16,
     25	.hbp		= 48,
     26	.vsw		= 2,
     27	.vfp		= 11,
     28	.vbp		= 31,
     29
     30	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     31	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     32
     33	.interlace	= false,
     34};
     35
     36struct panel_drv_data {
     37	struct omap_dss_device dssdev;
     38	struct omap_dss_device *in;
     39
     40	struct device *dev;
     41
     42	struct omap_video_timings timings;
     43
     44	int hpd_gpio;
     45};
     46
     47#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
     48
     49static int hdmic_connect(struct omap_dss_device *dssdev)
     50{
     51	struct panel_drv_data *ddata = to_panel_data(dssdev);
     52	struct omap_dss_device *in = ddata->in;
     53
     54	dev_dbg(ddata->dev, "connect\n");
     55
     56	if (omapdss_device_is_connected(dssdev))
     57		return 0;
     58
     59	return in->ops.hdmi->connect(in, dssdev);
     60}
     61
     62static void hdmic_disconnect(struct omap_dss_device *dssdev)
     63{
     64	struct panel_drv_data *ddata = to_panel_data(dssdev);
     65	struct omap_dss_device *in = ddata->in;
     66
     67	dev_dbg(ddata->dev, "disconnect\n");
     68
     69	if (!omapdss_device_is_connected(dssdev))
     70		return;
     71
     72	in->ops.hdmi->disconnect(in, dssdev);
     73}
     74
     75static int hdmic_enable(struct omap_dss_device *dssdev)
     76{
     77	struct panel_drv_data *ddata = to_panel_data(dssdev);
     78	struct omap_dss_device *in = ddata->in;
     79	int r;
     80
     81	dev_dbg(ddata->dev, "enable\n");
     82
     83	if (!omapdss_device_is_connected(dssdev))
     84		return -ENODEV;
     85
     86	if (omapdss_device_is_enabled(dssdev))
     87		return 0;
     88
     89	in->ops.hdmi->set_timings(in, &ddata->timings);
     90
     91	r = in->ops.hdmi->enable(in);
     92	if (r)
     93		return r;
     94
     95	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
     96
     97	return r;
     98}
     99
    100static void hdmic_disable(struct omap_dss_device *dssdev)
    101{
    102	struct panel_drv_data *ddata = to_panel_data(dssdev);
    103	struct omap_dss_device *in = ddata->in;
    104
    105	dev_dbg(ddata->dev, "disable\n");
    106
    107	if (!omapdss_device_is_enabled(dssdev))
    108		return;
    109
    110	in->ops.hdmi->disable(in);
    111
    112	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    113}
    114
    115static void hdmic_set_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	ddata->timings = *timings;
    122	dssdev->panel.timings = *timings;
    123
    124	in->ops.hdmi->set_timings(in, timings);
    125}
    126
    127static void hdmic_get_timings(struct omap_dss_device *dssdev,
    128		struct omap_video_timings *timings)
    129{
    130	struct panel_drv_data *ddata = to_panel_data(dssdev);
    131
    132	*timings = ddata->timings;
    133}
    134
    135static int hdmic_check_timings(struct omap_dss_device *dssdev,
    136		struct omap_video_timings *timings)
    137{
    138	struct panel_drv_data *ddata = to_panel_data(dssdev);
    139	struct omap_dss_device *in = ddata->in;
    140
    141	return in->ops.hdmi->check_timings(in, timings);
    142}
    143
    144static int hdmic_read_edid(struct omap_dss_device *dssdev,
    145		u8 *edid, int len)
    146{
    147	struct panel_drv_data *ddata = to_panel_data(dssdev);
    148	struct omap_dss_device *in = ddata->in;
    149
    150	return in->ops.hdmi->read_edid(in, edid, len);
    151}
    152
    153static bool hdmic_detect(struct omap_dss_device *dssdev)
    154{
    155	struct panel_drv_data *ddata = to_panel_data(dssdev);
    156	struct omap_dss_device *in = ddata->in;
    157
    158	if (gpio_is_valid(ddata->hpd_gpio))
    159		return gpio_get_value_cansleep(ddata->hpd_gpio);
    160	else
    161		return in->ops.hdmi->detect(in);
    162}
    163
    164static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
    165{
    166	struct panel_drv_data *ddata = to_panel_data(dssdev);
    167	struct omap_dss_device *in = ddata->in;
    168
    169	return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode);
    170}
    171
    172static int hdmic_set_infoframe(struct omap_dss_device *dssdev,
    173		const struct hdmi_avi_infoframe *avi)
    174{
    175	struct panel_drv_data *ddata = to_panel_data(dssdev);
    176	struct omap_dss_device *in = ddata->in;
    177
    178	return in->ops.hdmi->set_infoframe(in, avi);
    179}
    180
    181static struct omap_dss_driver hdmic_driver = {
    182	.connect		= hdmic_connect,
    183	.disconnect		= hdmic_disconnect,
    184
    185	.enable			= hdmic_enable,
    186	.disable		= hdmic_disable,
    187
    188	.set_timings		= hdmic_set_timings,
    189	.get_timings		= hdmic_get_timings,
    190	.check_timings		= hdmic_check_timings,
    191
    192	.get_resolution		= omapdss_default_get_resolution,
    193
    194	.read_edid		= hdmic_read_edid,
    195	.detect			= hdmic_detect,
    196	.set_hdmi_mode		= hdmic_set_hdmi_mode,
    197	.set_hdmi_infoframe	= hdmic_set_infoframe,
    198};
    199
    200static int hdmic_probe_of(struct platform_device *pdev)
    201{
    202	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    203	struct device_node *node = pdev->dev.of_node;
    204	struct omap_dss_device *in;
    205	int gpio;
    206
    207	/* HPD GPIO */
    208	gpio = of_get_named_gpio(node, "hpd-gpios", 0);
    209	if (gpio_is_valid(gpio))
    210		ddata->hpd_gpio = gpio;
    211	else
    212		ddata->hpd_gpio = -ENODEV;
    213
    214	in = omapdss_of_find_source_for_first_ep(node);
    215	if (IS_ERR(in)) {
    216		dev_err(&pdev->dev, "failed to find video source\n");
    217		return PTR_ERR(in);
    218	}
    219
    220	ddata->in = in;
    221
    222	return 0;
    223}
    224
    225static int hdmic_probe(struct platform_device *pdev)
    226{
    227	struct panel_drv_data *ddata;
    228	struct omap_dss_device *dssdev;
    229	int r;
    230
    231	if (!pdev->dev.of_node)
    232		return -ENODEV;
    233
    234	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
    235	if (!ddata)
    236		return -ENOMEM;
    237
    238	platform_set_drvdata(pdev, ddata);
    239	ddata->dev = &pdev->dev;
    240
    241	r = hdmic_probe_of(pdev);
    242	if (r)
    243		return r;
    244
    245	if (gpio_is_valid(ddata->hpd_gpio)) {
    246		r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
    247				GPIOF_DIR_IN, "hdmi_hpd");
    248		if (r)
    249			goto err_reg;
    250	}
    251
    252	ddata->timings = hdmic_default_timings;
    253
    254	dssdev = &ddata->dssdev;
    255	dssdev->driver = &hdmic_driver;
    256	dssdev->dev = &pdev->dev;
    257	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
    258	dssdev->owner = THIS_MODULE;
    259	dssdev->panel.timings = hdmic_default_timings;
    260
    261	r = omapdss_register_display(dssdev);
    262	if (r) {
    263		dev_err(&pdev->dev, "Failed to register panel\n");
    264		goto err_reg;
    265	}
    266
    267	return 0;
    268err_reg:
    269	omap_dss_put_device(ddata->in);
    270	return r;
    271}
    272
    273static int __exit hdmic_remove(struct platform_device *pdev)
    274{
    275	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    276	struct omap_dss_device *dssdev = &ddata->dssdev;
    277	struct omap_dss_device *in = ddata->in;
    278
    279	omapdss_unregister_display(&ddata->dssdev);
    280
    281	hdmic_disable(dssdev);
    282	hdmic_disconnect(dssdev);
    283
    284	omap_dss_put_device(in);
    285
    286	return 0;
    287}
    288
    289static const struct of_device_id hdmic_of_match[] = {
    290	{ .compatible = "omapdss,hdmi-connector", },
    291	{},
    292};
    293
    294MODULE_DEVICE_TABLE(of, hdmic_of_match);
    295
    296static struct platform_driver hdmi_connector_driver = {
    297	.probe	= hdmic_probe,
    298	.remove	= __exit_p(hdmic_remove),
    299	.driver	= {
    300		.name	= "connector-hdmi",
    301		.of_match_table = hdmic_of_match,
    302		.suppress_bind_attrs = true,
    303	},
    304};
    305
    306module_platform_driver(hdmi_connector_driver);
    307
    308MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
    309MODULE_DESCRIPTION("HDMI Connector driver");
    310MODULE_LICENSE("GPL");