0001
0002
0003
0004
0005
0006
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
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");