0001
0002
0003
0004
0005
0006
0007
0008
0009 #define DSS_SUBSYS_NAME "SDI"
0010
0011 #include <linux/kernel.h>
0012 #include <linux/delay.h>
0013 #include <linux/err.h>
0014 #include <linux/regulator/consumer.h>
0015 #include <linux/export.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/string.h>
0018 #include <linux/of.h>
0019 #include <linux/component.h>
0020
0021 #include <video/omapfb_dss.h>
0022 #include "dss.h"
0023
0024 static struct {
0025 struct platform_device *pdev;
0026
0027 bool update_enabled;
0028 struct regulator *vdds_sdi_reg;
0029
0030 struct dss_lcd_mgr_config mgr_config;
0031 struct omap_video_timings timings;
0032 int datapairs;
0033
0034 struct omap_dss_device output;
0035
0036 bool port_initialized;
0037 } sdi;
0038
0039 struct sdi_clk_calc_ctx {
0040 unsigned long pck_min, pck_max;
0041
0042 unsigned long fck;
0043 struct dispc_clock_info dispc_cinfo;
0044 };
0045
0046 static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
0047 unsigned long pck, void *data)
0048 {
0049 struct sdi_clk_calc_ctx *ctx = data;
0050
0051 ctx->dispc_cinfo.lck_div = lckd;
0052 ctx->dispc_cinfo.pck_div = pckd;
0053 ctx->dispc_cinfo.lck = lck;
0054 ctx->dispc_cinfo.pck = pck;
0055
0056 return true;
0057 }
0058
0059 static bool dpi_calc_dss_cb(unsigned long fck, void *data)
0060 {
0061 struct sdi_clk_calc_ctx *ctx = data;
0062
0063 ctx->fck = fck;
0064
0065 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
0066 dpi_calc_dispc_cb, ctx);
0067 }
0068
0069 static int sdi_calc_clock_div(unsigned long pclk,
0070 unsigned long *fck,
0071 struct dispc_clock_info *dispc_cinfo)
0072 {
0073 int i;
0074 struct sdi_clk_calc_ctx ctx;
0075
0076
0077
0078
0079
0080
0081
0082
0083 for (i = 0; i < 10; ++i) {
0084 bool ok;
0085
0086 memset(&ctx, 0, sizeof(ctx));
0087 if (pclk > 1000 * i * i * i)
0088 ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
0089 else
0090 ctx.pck_min = 0;
0091 ctx.pck_max = pclk + 1000 * i * i * i;
0092
0093 ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx);
0094 if (ok) {
0095 *fck = ctx.fck;
0096 *dispc_cinfo = ctx.dispc_cinfo;
0097 return 0;
0098 }
0099 }
0100
0101 return -EINVAL;
0102 }
0103
0104 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
0105 {
0106 struct omap_overlay_manager *mgr = sdi.output.manager;
0107
0108 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
0109
0110 sdi.mgr_config.stallmode = false;
0111 sdi.mgr_config.fifohandcheck = false;
0112
0113 sdi.mgr_config.video_port_width = 24;
0114 sdi.mgr_config.lcden_sig_polarity = 1;
0115
0116 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
0117 }
0118
0119 static int sdi_display_enable(struct omap_dss_device *dssdev)
0120 {
0121 struct omap_dss_device *out = &sdi.output;
0122 struct omap_video_timings *t = &sdi.timings;
0123 unsigned long fck;
0124 struct dispc_clock_info dispc_cinfo;
0125 unsigned long pck;
0126 int r;
0127
0128 if (out->manager == NULL) {
0129 DSSERR("failed to enable display: no output/manager\n");
0130 return -ENODEV;
0131 }
0132
0133 r = regulator_enable(sdi.vdds_sdi_reg);
0134 if (r)
0135 goto err_reg_enable;
0136
0137 r = dispc_runtime_get();
0138 if (r)
0139 goto err_get_dispc;
0140
0141
0142 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
0143 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
0144
0145 r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
0146 if (r)
0147 goto err_calc_clock_div;
0148
0149 sdi.mgr_config.clock_info = dispc_cinfo;
0150
0151 pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
0152
0153 if (pck != t->pixelclock) {
0154 DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
0155 t->pixelclock, pck);
0156
0157 t->pixelclock = pck;
0158 }
0159
0160
0161 dss_mgr_set_timings(out->manager, t);
0162
0163 r = dss_set_fck_rate(fck);
0164 if (r)
0165 goto err_set_dss_clock_div;
0166
0167 sdi_config_lcd_manager(dssdev);
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
0181
0182 dss_sdi_init(sdi.datapairs);
0183 r = dss_sdi_enable();
0184 if (r)
0185 goto err_sdi_enable;
0186 mdelay(2);
0187
0188 r = dss_mgr_enable(out->manager);
0189 if (r)
0190 goto err_mgr_enable;
0191
0192 return 0;
0193
0194 err_mgr_enable:
0195 dss_sdi_disable();
0196 err_sdi_enable:
0197 err_set_dss_clock_div:
0198 err_calc_clock_div:
0199 dispc_runtime_put();
0200 err_get_dispc:
0201 regulator_disable(sdi.vdds_sdi_reg);
0202 err_reg_enable:
0203 return r;
0204 }
0205
0206 static void sdi_display_disable(struct omap_dss_device *dssdev)
0207 {
0208 struct omap_overlay_manager *mgr = sdi.output.manager;
0209
0210 dss_mgr_disable(mgr);
0211
0212 dss_sdi_disable();
0213
0214 dispc_runtime_put();
0215
0216 regulator_disable(sdi.vdds_sdi_reg);
0217 }
0218
0219 static void sdi_set_timings(struct omap_dss_device *dssdev,
0220 struct omap_video_timings *timings)
0221 {
0222 sdi.timings = *timings;
0223 }
0224
0225 static void sdi_get_timings(struct omap_dss_device *dssdev,
0226 struct omap_video_timings *timings)
0227 {
0228 *timings = sdi.timings;
0229 }
0230
0231 static int sdi_check_timings(struct omap_dss_device *dssdev,
0232 struct omap_video_timings *timings)
0233 {
0234 struct omap_overlay_manager *mgr = sdi.output.manager;
0235
0236 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
0237 return -EINVAL;
0238
0239 if (timings->pixelclock == 0)
0240 return -EINVAL;
0241
0242 return 0;
0243 }
0244
0245 static void sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
0246 {
0247 sdi.datapairs = datapairs;
0248 }
0249
0250 static int sdi_init_regulator(void)
0251 {
0252 struct regulator *vdds_sdi;
0253
0254 if (sdi.vdds_sdi_reg)
0255 return 0;
0256
0257 vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
0258 if (IS_ERR(vdds_sdi)) {
0259 if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
0260 DSSERR("can't get VDDS_SDI regulator\n");
0261 return PTR_ERR(vdds_sdi);
0262 }
0263
0264 sdi.vdds_sdi_reg = vdds_sdi;
0265
0266 return 0;
0267 }
0268
0269 static int sdi_connect(struct omap_dss_device *dssdev,
0270 struct omap_dss_device *dst)
0271 {
0272 struct omap_overlay_manager *mgr;
0273 int r;
0274
0275 r = sdi_init_regulator();
0276 if (r)
0277 return r;
0278
0279 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
0280 if (!mgr)
0281 return -ENODEV;
0282
0283 r = dss_mgr_connect(mgr, dssdev);
0284 if (r)
0285 return r;
0286
0287 r = omapdss_output_set_device(dssdev, dst);
0288 if (r) {
0289 DSSERR("failed to connect output to new device: %s\n",
0290 dst->name);
0291 dss_mgr_disconnect(mgr, dssdev);
0292 return r;
0293 }
0294
0295 return 0;
0296 }
0297
0298 static void sdi_disconnect(struct omap_dss_device *dssdev,
0299 struct omap_dss_device *dst)
0300 {
0301 WARN_ON(dst != dssdev->dst);
0302
0303 if (dst != dssdev->dst)
0304 return;
0305
0306 omapdss_output_unset_device(dssdev);
0307
0308 if (dssdev->manager)
0309 dss_mgr_disconnect(dssdev->manager, dssdev);
0310 }
0311
0312 static const struct omapdss_sdi_ops sdi_ops = {
0313 .connect = sdi_connect,
0314 .disconnect = sdi_disconnect,
0315
0316 .enable = sdi_display_enable,
0317 .disable = sdi_display_disable,
0318
0319 .check_timings = sdi_check_timings,
0320 .set_timings = sdi_set_timings,
0321 .get_timings = sdi_get_timings,
0322
0323 .set_datapairs = sdi_set_datapairs,
0324 };
0325
0326 static void sdi_init_output(struct platform_device *pdev)
0327 {
0328 struct omap_dss_device *out = &sdi.output;
0329
0330 out->dev = &pdev->dev;
0331 out->id = OMAP_DSS_OUTPUT_SDI;
0332 out->output_type = OMAP_DISPLAY_TYPE_SDI;
0333 out->name = "sdi.0";
0334 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
0335
0336 out->port_num = 1;
0337 out->ops.sdi = &sdi_ops;
0338 out->owner = THIS_MODULE;
0339
0340 omapdss_register_output(out);
0341 }
0342
0343 static void sdi_uninit_output(struct platform_device *pdev)
0344 {
0345 struct omap_dss_device *out = &sdi.output;
0346
0347 omapdss_unregister_output(out);
0348 }
0349
0350 static int sdi_bind(struct device *dev, struct device *master, void *data)
0351 {
0352 struct platform_device *pdev = to_platform_device(dev);
0353
0354 sdi.pdev = pdev;
0355
0356 sdi_init_output(pdev);
0357
0358 return 0;
0359 }
0360
0361 static void sdi_unbind(struct device *dev, struct device *master, void *data)
0362 {
0363 struct platform_device *pdev = to_platform_device(dev);
0364
0365 sdi_uninit_output(pdev);
0366 }
0367
0368 static const struct component_ops sdi_component_ops = {
0369 .bind = sdi_bind,
0370 .unbind = sdi_unbind,
0371 };
0372
0373 static int sdi_probe(struct platform_device *pdev)
0374 {
0375 return component_add(&pdev->dev, &sdi_component_ops);
0376 }
0377
0378 static int sdi_remove(struct platform_device *pdev)
0379 {
0380 component_del(&pdev->dev, &sdi_component_ops);
0381 return 0;
0382 }
0383
0384 static struct platform_driver omap_sdi_driver = {
0385 .probe = sdi_probe,
0386 .remove = sdi_remove,
0387 .driver = {
0388 .name = "omapdss_sdi",
0389 .suppress_bind_attrs = true,
0390 },
0391 };
0392
0393 int __init sdi_init_platform_driver(void)
0394 {
0395 return platform_driver_register(&omap_sdi_driver);
0396 }
0397
0398 void sdi_uninit_platform_driver(void)
0399 {
0400 platform_driver_unregister(&omap_sdi_driver);
0401 }
0402
0403 int sdi_init_port(struct platform_device *pdev, struct device_node *port)
0404 {
0405 struct device_node *ep;
0406 u32 datapairs;
0407 int r;
0408
0409 ep = omapdss_of_get_next_endpoint(port, NULL);
0410 if (!ep)
0411 return 0;
0412
0413 r = of_property_read_u32(ep, "datapairs", &datapairs);
0414 if (r) {
0415 DSSERR("failed to parse datapairs\n");
0416 goto err_datapairs;
0417 }
0418
0419 sdi.datapairs = datapairs;
0420
0421 of_node_put(ep);
0422
0423 sdi.pdev = pdev;
0424
0425 sdi_init_output(pdev);
0426
0427 sdi.port_initialized = true;
0428
0429 return 0;
0430
0431 err_datapairs:
0432 of_node_put(ep);
0433
0434 return r;
0435 }
0436
0437 void sdi_uninit_port(struct device_node *port)
0438 {
0439 if (!sdi.port_initialized)
0440 return;
0441
0442 sdi_uninit_output(sdi.pdev);
0443 }