Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HDMI Connector driver
0004  *
0005  * Copyright (C) 2013 Texas Instruments
0006  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
0007  */
0008 
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/of.h>
0013 #include <linux/of_gpio.h>
0014 
0015 #include <drm/drm_edid.h>
0016 
0017 #include <video/omapfb_dss.h>
0018 
0019 static const struct omap_video_timings hdmic_default_timings = {
0020     .x_res      = 640,
0021     .y_res      = 480,
0022     .pixelclock = 25175000,
0023     .hsw        = 96,
0024     .hfp        = 16,
0025     .hbp        = 48,
0026     .vsw        = 2,
0027     .vfp        = 11,
0028     .vbp        = 31,
0029 
0030     .vsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
0031     .hsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
0032 
0033     .interlace  = false,
0034 };
0035 
0036 struct panel_drv_data {
0037     struct omap_dss_device dssdev;
0038     struct omap_dss_device *in;
0039 
0040     struct device *dev;
0041 
0042     struct omap_video_timings timings;
0043 
0044     int hpd_gpio;
0045 };
0046 
0047 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
0048 
0049 static int hdmic_connect(struct omap_dss_device *dssdev)
0050 {
0051     struct panel_drv_data *ddata = to_panel_data(dssdev);
0052     struct omap_dss_device *in = ddata->in;
0053 
0054     dev_dbg(ddata->dev, "connect\n");
0055 
0056     if (omapdss_device_is_connected(dssdev))
0057         return 0;
0058 
0059     return in->ops.hdmi->connect(in, dssdev);
0060 }
0061 
0062 static void hdmic_disconnect(struct omap_dss_device *dssdev)
0063 {
0064     struct panel_drv_data *ddata = to_panel_data(dssdev);
0065     struct omap_dss_device *in = ddata->in;
0066 
0067     dev_dbg(ddata->dev, "disconnect\n");
0068 
0069     if (!omapdss_device_is_connected(dssdev))
0070         return;
0071 
0072     in->ops.hdmi->disconnect(in, dssdev);
0073 }
0074 
0075 static int hdmic_enable(struct omap_dss_device *dssdev)
0076 {
0077     struct panel_drv_data *ddata = to_panel_data(dssdev);
0078     struct omap_dss_device *in = ddata->in;
0079     int r;
0080 
0081     dev_dbg(ddata->dev, "enable\n");
0082 
0083     if (!omapdss_device_is_connected(dssdev))
0084         return -ENODEV;
0085 
0086     if (omapdss_device_is_enabled(dssdev))
0087         return 0;
0088 
0089     in->ops.hdmi->set_timings(in, &ddata->timings);
0090 
0091     r = in->ops.hdmi->enable(in);
0092     if (r)
0093         return r;
0094 
0095     dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
0096 
0097     return r;
0098 }
0099 
0100 static void hdmic_disable(struct omap_dss_device *dssdev)
0101 {
0102     struct panel_drv_data *ddata = to_panel_data(dssdev);
0103     struct omap_dss_device *in = ddata->in;
0104 
0105     dev_dbg(ddata->dev, "disable\n");
0106 
0107     if (!omapdss_device_is_enabled(dssdev))
0108         return;
0109 
0110     in->ops.hdmi->disable(in);
0111 
0112     dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
0113 }
0114 
0115 static void hdmic_set_timings(struct omap_dss_device *dssdev,
0116         struct omap_video_timings *timings)
0117 {
0118     struct panel_drv_data *ddata = to_panel_data(dssdev);
0119     struct omap_dss_device *in = ddata->in;
0120 
0121     ddata->timings = *timings;
0122     dssdev->panel.timings = *timings;
0123 
0124     in->ops.hdmi->set_timings(in, timings);
0125 }
0126 
0127 static void hdmic_get_timings(struct omap_dss_device *dssdev,
0128         struct omap_video_timings *timings)
0129 {
0130     struct panel_drv_data *ddata = to_panel_data(dssdev);
0131 
0132     *timings = ddata->timings;
0133 }
0134 
0135 static int hdmic_check_timings(struct omap_dss_device *dssdev,
0136         struct omap_video_timings *timings)
0137 {
0138     struct panel_drv_data *ddata = to_panel_data(dssdev);
0139     struct omap_dss_device *in = ddata->in;
0140 
0141     return in->ops.hdmi->check_timings(in, timings);
0142 }
0143 
0144 static int hdmic_read_edid(struct omap_dss_device *dssdev,
0145         u8 *edid, int len)
0146 {
0147     struct panel_drv_data *ddata = to_panel_data(dssdev);
0148     struct omap_dss_device *in = ddata->in;
0149 
0150     return in->ops.hdmi->read_edid(in, edid, len);
0151 }
0152 
0153 static bool hdmic_detect(struct omap_dss_device *dssdev)
0154 {
0155     struct panel_drv_data *ddata = to_panel_data(dssdev);
0156     struct omap_dss_device *in = ddata->in;
0157 
0158     if (gpio_is_valid(ddata->hpd_gpio))
0159         return gpio_get_value_cansleep(ddata->hpd_gpio);
0160     else
0161         return in->ops.hdmi->detect(in);
0162 }
0163 
0164 static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
0165 {
0166     struct panel_drv_data *ddata = to_panel_data(dssdev);
0167     struct omap_dss_device *in = ddata->in;
0168 
0169     return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode);
0170 }
0171 
0172 static int hdmic_set_infoframe(struct omap_dss_device *dssdev,
0173         const struct hdmi_avi_infoframe *avi)
0174 {
0175     struct panel_drv_data *ddata = to_panel_data(dssdev);
0176     struct omap_dss_device *in = ddata->in;
0177 
0178     return in->ops.hdmi->set_infoframe(in, avi);
0179 }
0180 
0181 static struct omap_dss_driver hdmic_driver = {
0182     .connect        = hdmic_connect,
0183     .disconnect     = hdmic_disconnect,
0184 
0185     .enable         = hdmic_enable,
0186     .disable        = hdmic_disable,
0187 
0188     .set_timings        = hdmic_set_timings,
0189     .get_timings        = hdmic_get_timings,
0190     .check_timings      = hdmic_check_timings,
0191 
0192     .get_resolution     = omapdss_default_get_resolution,
0193 
0194     .read_edid      = hdmic_read_edid,
0195     .detect         = hdmic_detect,
0196     .set_hdmi_mode      = hdmic_set_hdmi_mode,
0197     .set_hdmi_infoframe = hdmic_set_infoframe,
0198 };
0199 
0200 static int hdmic_probe_of(struct platform_device *pdev)
0201 {
0202     struct panel_drv_data *ddata = platform_get_drvdata(pdev);
0203     struct device_node *node = pdev->dev.of_node;
0204     struct omap_dss_device *in;
0205     int gpio;
0206 
0207     /* HPD GPIO */
0208     gpio = of_get_named_gpio(node, "hpd-gpios", 0);
0209     if (gpio_is_valid(gpio))
0210         ddata->hpd_gpio = gpio;
0211     else
0212         ddata->hpd_gpio = -ENODEV;
0213 
0214     in = omapdss_of_find_source_for_first_ep(node);
0215     if (IS_ERR(in)) {
0216         dev_err(&pdev->dev, "failed to find video source\n");
0217         return PTR_ERR(in);
0218     }
0219 
0220     ddata->in = in;
0221 
0222     return 0;
0223 }
0224 
0225 static int hdmic_probe(struct platform_device *pdev)
0226 {
0227     struct panel_drv_data *ddata;
0228     struct omap_dss_device *dssdev;
0229     int r;
0230 
0231     if (!pdev->dev.of_node)
0232         return -ENODEV;
0233 
0234     ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
0235     if (!ddata)
0236         return -ENOMEM;
0237 
0238     platform_set_drvdata(pdev, ddata);
0239     ddata->dev = &pdev->dev;
0240 
0241     r = hdmic_probe_of(pdev);
0242     if (r)
0243         return r;
0244 
0245     if (gpio_is_valid(ddata->hpd_gpio)) {
0246         r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
0247                 GPIOF_DIR_IN, "hdmi_hpd");
0248         if (r)
0249             goto err_reg;
0250     }
0251 
0252     ddata->timings = hdmic_default_timings;
0253 
0254     dssdev = &ddata->dssdev;
0255     dssdev->driver = &hdmic_driver;
0256     dssdev->dev = &pdev->dev;
0257     dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
0258     dssdev->owner = THIS_MODULE;
0259     dssdev->panel.timings = hdmic_default_timings;
0260 
0261     r = omapdss_register_display(dssdev);
0262     if (r) {
0263         dev_err(&pdev->dev, "Failed to register panel\n");
0264         goto err_reg;
0265     }
0266 
0267     return 0;
0268 err_reg:
0269     omap_dss_put_device(ddata->in);
0270     return r;
0271 }
0272 
0273 static int __exit hdmic_remove(struct platform_device *pdev)
0274 {
0275     struct panel_drv_data *ddata = platform_get_drvdata(pdev);
0276     struct omap_dss_device *dssdev = &ddata->dssdev;
0277     struct omap_dss_device *in = ddata->in;
0278 
0279     omapdss_unregister_display(&ddata->dssdev);
0280 
0281     hdmic_disable(dssdev);
0282     hdmic_disconnect(dssdev);
0283 
0284     omap_dss_put_device(in);
0285 
0286     return 0;
0287 }
0288 
0289 static const struct of_device_id hdmic_of_match[] = {
0290     { .compatible = "omapdss,hdmi-connector", },
0291     {},
0292 };
0293 
0294 MODULE_DEVICE_TABLE(of, hdmic_of_match);
0295 
0296 static struct platform_driver hdmi_connector_driver = {
0297     .probe  = hdmic_probe,
0298     .remove = __exit_p(hdmic_remove),
0299     .driver = {
0300         .name   = "connector-hdmi",
0301         .of_match_table = hdmic_of_match,
0302         .suppress_bind_attrs = true,
0303     },
0304 };
0305 
0306 module_platform_driver(hdmi_connector_driver);
0307 
0308 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
0309 MODULE_DESCRIPTION("HDMI Connector driver");
0310 MODULE_LICENSE("GPL");