root/drivers/gpu/drm/omapdrm/dss/sdi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dpi_calc_dispc_cb
  2. dpi_calc_dss_cb
  3. sdi_calc_clock_div
  4. sdi_config_lcd_manager
  5. sdi_display_enable
  6. sdi_display_disable
  7. sdi_set_timings
  8. sdi_check_timings
  9. sdi_connect
  10. sdi_disconnect
  11. sdi_init_output
  12. sdi_uninit_output
  13. sdi_init_port
  14. sdi_uninit_port

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2009 Nokia Corporation
   4  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
   5  */
   6 
   7 #define DSS_SUBSYS_NAME "SDI"
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/delay.h>
  11 #include <linux/err.h>
  12 #include <linux/regulator/consumer.h>
  13 #include <linux/export.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/string.h>
  16 #include <linux/of.h>
  17 
  18 #include "omapdss.h"
  19 #include "dss.h"
  20 
  21 struct sdi_device {
  22         struct platform_device *pdev;
  23         struct dss_device *dss;
  24 
  25         bool update_enabled;
  26         struct regulator *vdds_sdi_reg;
  27 
  28         struct dss_lcd_mgr_config mgr_config;
  29         unsigned long pixelclock;
  30         int datapairs;
  31 
  32         struct omap_dss_device output;
  33 };
  34 
  35 #define dssdev_to_sdi(dssdev) container_of(dssdev, struct sdi_device, output)
  36 
  37 struct sdi_clk_calc_ctx {
  38         struct sdi_device *sdi;
  39         unsigned long pck_min, pck_max;
  40 
  41         unsigned long fck;
  42         struct dispc_clock_info dispc_cinfo;
  43 };
  44 
  45 static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
  46                 unsigned long pck, void *data)
  47 {
  48         struct sdi_clk_calc_ctx *ctx = data;
  49 
  50         ctx->dispc_cinfo.lck_div = lckd;
  51         ctx->dispc_cinfo.pck_div = pckd;
  52         ctx->dispc_cinfo.lck = lck;
  53         ctx->dispc_cinfo.pck = pck;
  54 
  55         return true;
  56 }
  57 
  58 static bool dpi_calc_dss_cb(unsigned long fck, void *data)
  59 {
  60         struct sdi_clk_calc_ctx *ctx = data;
  61 
  62         ctx->fck = fck;
  63 
  64         return dispc_div_calc(ctx->sdi->dss->dispc, fck,
  65                               ctx->pck_min, ctx->pck_max,
  66                               dpi_calc_dispc_cb, ctx);
  67 }
  68 
  69 static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
  70                               unsigned long *fck,
  71                               struct dispc_clock_info *dispc_cinfo)
  72 {
  73         int i;
  74         struct sdi_clk_calc_ctx ctx;
  75 
  76         /*
  77          * DSS fclk gives us very few possibilities, so finding a good pixel
  78          * clock may not be possible. We try multiple times to find the clock,
  79          * each time widening the pixel clock range we look for, up to
  80          * +/- 1MHz.
  81          */
  82 
  83         for (i = 0; i < 10; ++i) {
  84                 bool ok;
  85 
  86                 memset(&ctx, 0, sizeof(ctx));
  87 
  88                 ctx.sdi = sdi;
  89 
  90                 if (pclk > 1000 * i * i * i)
  91                         ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
  92                 else
  93                         ctx.pck_min = 0;
  94                 ctx.pck_max = pclk + 1000 * i * i * i;
  95 
  96                 ok = dss_div_calc(sdi->dss, pclk, ctx.pck_min,
  97                                   dpi_calc_dss_cb, &ctx);
  98                 if (ok) {
  99                         *fck = ctx.fck;
 100                         *dispc_cinfo = ctx.dispc_cinfo;
 101                         return 0;
 102                 }
 103         }
 104 
 105         return -EINVAL;
 106 }
 107 
 108 static void sdi_config_lcd_manager(struct sdi_device *sdi)
 109 {
 110         sdi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 111 
 112         sdi->mgr_config.stallmode = false;
 113         sdi->mgr_config.fifohandcheck = false;
 114 
 115         sdi->mgr_config.video_port_width = 24;
 116         sdi->mgr_config.lcden_sig_polarity = 1;
 117 
 118         dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config);
 119 }
 120 
 121 static void sdi_display_enable(struct omap_dss_device *dssdev)
 122 {
 123         struct sdi_device *sdi = dssdev_to_sdi(dssdev);
 124         struct dispc_clock_info dispc_cinfo;
 125         unsigned long fck;
 126         int r;
 127 
 128         r = regulator_enable(sdi->vdds_sdi_reg);
 129         if (r)
 130                 return;
 131 
 132         r = dispc_runtime_get(sdi->dss->dispc);
 133         if (r)
 134                 goto err_get_dispc;
 135 
 136         r = sdi_calc_clock_div(sdi, sdi->pixelclock, &fck, &dispc_cinfo);
 137         if (r)
 138                 goto err_calc_clock_div;
 139 
 140         sdi->mgr_config.clock_info = dispc_cinfo;
 141 
 142         r = dss_set_fck_rate(sdi->dss, fck);
 143         if (r)
 144                 goto err_set_dss_clock_div;
 145 
 146         sdi_config_lcd_manager(sdi);
 147 
 148         /*
 149          * LCLK and PCLK divisors are located in shadow registers, and we
 150          * normally write them to DISPC registers when enabling the output.
 151          * However, SDI uses pck-free as source clock for its PLL, and pck-free
 152          * is affected by the divisors. And as we need the PLL before enabling
 153          * the output, we need to write the divisors early.
 154          *
 155          * It seems just writing to the DISPC register is enough, and we don't
 156          * need to care about the shadow register mechanism for pck-free. The
 157          * exact reason for this is unknown.
 158          */
 159         dispc_mgr_set_clock_div(sdi->dss->dispc, sdi->output.dispc_channel,
 160                                 &sdi->mgr_config.clock_info);
 161 
 162         dss_sdi_init(sdi->dss, sdi->datapairs);
 163         r = dss_sdi_enable(sdi->dss);
 164         if (r)
 165                 goto err_sdi_enable;
 166         mdelay(2);
 167 
 168         r = dss_mgr_enable(&sdi->output);
 169         if (r)
 170                 goto err_mgr_enable;
 171 
 172         return;
 173 
 174 err_mgr_enable:
 175         dss_sdi_disable(sdi->dss);
 176 err_sdi_enable:
 177 err_set_dss_clock_div:
 178 err_calc_clock_div:
 179         dispc_runtime_put(sdi->dss->dispc);
 180 err_get_dispc:
 181         regulator_disable(sdi->vdds_sdi_reg);
 182 }
 183 
 184 static void sdi_display_disable(struct omap_dss_device *dssdev)
 185 {
 186         struct sdi_device *sdi = dssdev_to_sdi(dssdev);
 187 
 188         dss_mgr_disable(&sdi->output);
 189 
 190         dss_sdi_disable(sdi->dss);
 191 
 192         dispc_runtime_put(sdi->dss->dispc);
 193 
 194         regulator_disable(sdi->vdds_sdi_reg);
 195 }
 196 
 197 static void sdi_set_timings(struct omap_dss_device *dssdev,
 198                             const struct drm_display_mode *mode)
 199 {
 200         struct sdi_device *sdi = dssdev_to_sdi(dssdev);
 201 
 202         sdi->pixelclock = mode->clock * 1000;
 203 }
 204 
 205 static int sdi_check_timings(struct omap_dss_device *dssdev,
 206                              struct drm_display_mode *mode)
 207 {
 208         struct sdi_device *sdi = dssdev_to_sdi(dssdev);
 209         struct dispc_clock_info dispc_cinfo;
 210         unsigned long pixelclock = mode->clock * 1000;
 211         unsigned long fck;
 212         unsigned long pck;
 213         int r;
 214 
 215         if (pixelclock == 0)
 216                 return -EINVAL;
 217 
 218         r = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
 219         if (r)
 220                 return r;
 221 
 222         pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
 223 
 224         if (pck != pixelclock) {
 225                 DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n",
 226                         pixelclock, pck);
 227 
 228                 mode->clock = pck / 1000;
 229         }
 230 
 231         return 0;
 232 }
 233 
 234 static int sdi_connect(struct omap_dss_device *src,
 235                        struct omap_dss_device *dst)
 236 {
 237         return omapdss_device_connect(dst->dss, dst, dst->next);
 238 }
 239 
 240 static void sdi_disconnect(struct omap_dss_device *src,
 241                            struct omap_dss_device *dst)
 242 {
 243         omapdss_device_disconnect(dst, dst->next);
 244 }
 245 
 246 static const struct omap_dss_device_ops sdi_ops = {
 247         .connect = sdi_connect,
 248         .disconnect = sdi_disconnect,
 249 
 250         .enable = sdi_display_enable,
 251         .disable = sdi_display_disable,
 252 
 253         .check_timings = sdi_check_timings,
 254         .set_timings = sdi_set_timings,
 255 };
 256 
 257 static int sdi_init_output(struct sdi_device *sdi)
 258 {
 259         struct omap_dss_device *out = &sdi->output;
 260         int r;
 261 
 262         out->dev = &sdi->pdev->dev;
 263         out->id = OMAP_DSS_OUTPUT_SDI;
 264         out->type = OMAP_DISPLAY_TYPE_SDI;
 265         out->name = "sdi.0";
 266         out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 267         /* We have SDI only on OMAP3, where it's on port 1 */
 268         out->of_ports = BIT(1);
 269         out->ops = &sdi_ops;
 270         out->owner = THIS_MODULE;
 271         out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE     /* 15.5.9.1.2 */
 272                        | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
 273 
 274         r = omapdss_device_init_output(out);
 275         if (r < 0)
 276                 return r;
 277 
 278         omapdss_device_register(out);
 279 
 280         return 0;
 281 }
 282 
 283 static void sdi_uninit_output(struct sdi_device *sdi)
 284 {
 285         omapdss_device_unregister(&sdi->output);
 286         omapdss_device_cleanup_output(&sdi->output);
 287 }
 288 
 289 int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
 290                   struct device_node *port)
 291 {
 292         struct sdi_device *sdi;
 293         struct device_node *ep;
 294         u32 datapairs;
 295         int r;
 296 
 297         sdi = kzalloc(sizeof(*sdi), GFP_KERNEL);
 298         if (!sdi)
 299                 return -ENOMEM;
 300 
 301         ep = of_get_next_child(port, NULL);
 302         if (!ep) {
 303                 r = 0;
 304                 goto err_free;
 305         }
 306 
 307         r = of_property_read_u32(ep, "datapairs", &datapairs);
 308         of_node_put(ep);
 309         if (r) {
 310                 DSSERR("failed to parse datapairs\n");
 311                 goto err_free;
 312         }
 313 
 314         sdi->datapairs = datapairs;
 315         sdi->dss = dss;
 316 
 317         sdi->pdev = pdev;
 318         port->data = sdi;
 319 
 320         sdi->vdds_sdi_reg = devm_regulator_get(&pdev->dev, "vdds_sdi");
 321         if (IS_ERR(sdi->vdds_sdi_reg)) {
 322                 r = PTR_ERR(sdi->vdds_sdi_reg);
 323                 if (r != -EPROBE_DEFER)
 324                         DSSERR("can't get VDDS_SDI regulator\n");
 325                 goto err_free;
 326         }
 327 
 328         r = sdi_init_output(sdi);
 329         if (r)
 330                 goto err_free;
 331 
 332         return 0;
 333 
 334 err_free:
 335         kfree(sdi);
 336 
 337         return r;
 338 }
 339 
 340 void sdi_uninit_port(struct device_node *port)
 341 {
 342         struct sdi_device *sdi = port->data;
 343 
 344         if (!sdi)
 345                 return;
 346 
 347         sdi_uninit_output(sdi);
 348         kfree(sdi);
 349 }

/* [<][>][^][v][top][bottom][index][help] */