Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/video/omap2/dss/sdi.c
0004  *
0005  * Copyright (C) 2009 Nokia Corporation
0006  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
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      * DSS fclk gives us very few possibilities, so finding a good pixel
0078      * clock may not be possible. We try multiple times to find the clock,
0079      * each time widening the pixel clock range we look for, up to
0080      * +/- 1MHz.
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     /* 15.5.9.1.2 */
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      * LCLK and PCLK divisors are located in shadow registers, and we
0171      * normally write them to DISPC registers when enabling the output.
0172      * However, SDI uses pck-free as source clock for its PLL, and pck-free
0173      * is affected by the divisors. And as we need the PLL before enabling
0174      * the output, we need to write the divisors early.
0175      *
0176      * It seems just writing to the DISPC register is enough, and we don't
0177      * need to care about the shadow register mechanism for pck-free. The
0178      * exact reason for this is unknown.
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     /* We have SDI only on OMAP3, where it's on port 1 */
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 }