linux/drivers/gpu/drm/omapdrm/dss/sdi.c
<<
>>
Prefs
   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/delay.h>
  10#include <linux/err.h>
  11#include <linux/export.h>
  12#include <linux/kernel.h>
  13#include <linux/of.h>
  14#include <linux/platform_device.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/string.h>
  17
  18#include <drm/drm_bridge.h>
  19
  20#include "dss.h"
  21#include "omapdss.h"
  22
  23struct sdi_device {
  24        struct platform_device *pdev;
  25        struct dss_device *dss;
  26
  27        bool update_enabled;
  28        struct regulator *vdds_sdi_reg;
  29
  30        struct dss_lcd_mgr_config mgr_config;
  31        unsigned long pixelclock;
  32        int datapairs;
  33
  34        struct omap_dss_device output;
  35        struct drm_bridge bridge;
  36};
  37
  38#define drm_bridge_to_sdi(bridge) \
  39        container_of(bridge, struct sdi_device, bridge)
  40
  41struct sdi_clk_calc_ctx {
  42        struct sdi_device *sdi;
  43        unsigned long pck_min, pck_max;
  44
  45        unsigned long fck;
  46        struct dispc_clock_info dispc_cinfo;
  47};
  48
  49static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
  50                unsigned long pck, void *data)
  51{
  52        struct sdi_clk_calc_ctx *ctx = data;
  53
  54        ctx->dispc_cinfo.lck_div = lckd;
  55        ctx->dispc_cinfo.pck_div = pckd;
  56        ctx->dispc_cinfo.lck = lck;
  57        ctx->dispc_cinfo.pck = pck;
  58
  59        return true;
  60}
  61
  62static bool dpi_calc_dss_cb(unsigned long fck, void *data)
  63{
  64        struct sdi_clk_calc_ctx *ctx = data;
  65
  66        ctx->fck = fck;
  67
  68        return dispc_div_calc(ctx->sdi->dss->dispc, fck,
  69                              ctx->pck_min, ctx->pck_max,
  70                              dpi_calc_dispc_cb, ctx);
  71}
  72
  73static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
  74                              unsigned long *fck,
  75                              struct dispc_clock_info *dispc_cinfo)
  76{
  77        int i;
  78        struct sdi_clk_calc_ctx ctx;
  79
  80        /*
  81         * DSS fclk gives us very few possibilities, so finding a good pixel
  82         * clock may not be possible. We try multiple times to find the clock,
  83         * each time widening the pixel clock range we look for, up to
  84         * +/- 1MHz.
  85         */
  86
  87        for (i = 0; i < 10; ++i) {
  88                bool ok;
  89
  90                memset(&ctx, 0, sizeof(ctx));
  91
  92                ctx.sdi = sdi;
  93
  94                if (pclk > 1000 * i * i * i)
  95                        ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
  96                else
  97                        ctx.pck_min = 0;
  98                ctx.pck_max = pclk + 1000 * i * i * i;
  99
 100                ok = dss_div_calc(sdi->dss, pclk, ctx.pck_min,
 101                                  dpi_calc_dss_cb, &ctx);
 102                if (ok) {
 103                        *fck = ctx.fck;
 104                        *dispc_cinfo = ctx.dispc_cinfo;
 105                        return 0;
 106                }
 107        }
 108
 109        return -EINVAL;
 110}
 111
 112static void sdi_config_lcd_manager(struct sdi_device *sdi)
 113{
 114        sdi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 115
 116        sdi->mgr_config.stallmode = false;
 117        sdi->mgr_config.fifohandcheck = false;
 118
 119        sdi->mgr_config.video_port_width = 24;
 120        sdi->mgr_config.lcden_sig_polarity = 1;
 121
 122        dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config);
 123}
 124
 125/* -----------------------------------------------------------------------------
 126 * DRM Bridge Operations
 127 */
 128
 129static int sdi_bridge_attach(struct drm_bridge *bridge,
 130                             enum drm_bridge_attach_flags flags)
 131{
 132        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 133
 134        if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
 135                return -EINVAL;
 136
 137        return drm_bridge_attach(bridge->encoder, sdi->output.next_bridge,
 138                                 bridge, flags);
 139}
 140
 141static enum drm_mode_status
 142sdi_bridge_mode_valid(struct drm_bridge *bridge,
 143                      const struct drm_display_info *info,
 144                      const struct drm_display_mode *mode)
 145{
 146        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 147        unsigned long pixelclock = mode->clock * 1000;
 148        struct dispc_clock_info dispc_cinfo;
 149        unsigned long fck;
 150        int ret;
 151
 152        if (pixelclock == 0)
 153                return MODE_NOCLOCK;
 154
 155        ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
 156        if (ret < 0)
 157                return MODE_CLOCK_RANGE;
 158
 159        return MODE_OK;
 160}
 161
 162static bool sdi_bridge_mode_fixup(struct drm_bridge *bridge,
 163                                  const struct drm_display_mode *mode,
 164                                  struct drm_display_mode *adjusted_mode)
 165{
 166        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 167        unsigned long pixelclock = mode->clock * 1000;
 168        struct dispc_clock_info dispc_cinfo;
 169        unsigned long fck;
 170        unsigned long pck;
 171        int ret;
 172
 173        ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
 174        if (ret < 0)
 175                return false;
 176
 177        pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
 178
 179        if (pck != pixelclock)
 180                dev_dbg(&sdi->pdev->dev,
 181                        "pixel clock adjusted from %lu Hz to %lu Hz\n",
 182                        pixelclock, pck);
 183
 184        adjusted_mode->clock = pck / 1000;
 185
 186        return true;
 187}
 188
 189static void sdi_bridge_mode_set(struct drm_bridge *bridge,
 190                                const struct drm_display_mode *mode,
 191                                const struct drm_display_mode *adjusted_mode)
 192{
 193        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 194
 195        sdi->pixelclock = adjusted_mode->clock * 1000;
 196}
 197
 198static void sdi_bridge_enable(struct drm_bridge *bridge)
 199{
 200        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 201        struct dispc_clock_info dispc_cinfo;
 202        unsigned long fck;
 203        int r;
 204
 205        r = regulator_enable(sdi->vdds_sdi_reg);
 206        if (r)
 207                return;
 208
 209        r = dispc_runtime_get(sdi->dss->dispc);
 210        if (r)
 211                goto err_get_dispc;
 212
 213        r = sdi_calc_clock_div(sdi, sdi->pixelclock, &fck, &dispc_cinfo);
 214        if (r)
 215                goto err_calc_clock_div;
 216
 217        sdi->mgr_config.clock_info = dispc_cinfo;
 218
 219        r = dss_set_fck_rate(sdi->dss, fck);
 220        if (r)
 221                goto err_set_dss_clock_div;
 222
 223        sdi_config_lcd_manager(sdi);
 224
 225        /*
 226         * LCLK and PCLK divisors are located in shadow registers, and we
 227         * normally write them to DISPC registers when enabling the output.
 228         * However, SDI uses pck-free as source clock for its PLL, and pck-free
 229         * is affected by the divisors. And as we need the PLL before enabling
 230         * the output, we need to write the divisors early.
 231         *
 232         * It seems just writing to the DISPC register is enough, and we don't
 233         * need to care about the shadow register mechanism for pck-free. The
 234         * exact reason for this is unknown.
 235         */
 236        dispc_mgr_set_clock_div(sdi->dss->dispc, sdi->output.dispc_channel,
 237                                &sdi->mgr_config.clock_info);
 238
 239        dss_sdi_init(sdi->dss, sdi->datapairs);
 240        r = dss_sdi_enable(sdi->dss);
 241        if (r)
 242                goto err_sdi_enable;
 243        mdelay(2);
 244
 245        r = dss_mgr_enable(&sdi->output);
 246        if (r)
 247                goto err_mgr_enable;
 248
 249        return;
 250
 251err_mgr_enable:
 252        dss_sdi_disable(sdi->dss);
 253err_sdi_enable:
 254err_set_dss_clock_div:
 255err_calc_clock_div:
 256        dispc_runtime_put(sdi->dss->dispc);
 257err_get_dispc:
 258        regulator_disable(sdi->vdds_sdi_reg);
 259}
 260
 261static void sdi_bridge_disable(struct drm_bridge *bridge)
 262{
 263        struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 264
 265        dss_mgr_disable(&sdi->output);
 266
 267        dss_sdi_disable(sdi->dss);
 268
 269        dispc_runtime_put(sdi->dss->dispc);
 270
 271        regulator_disable(sdi->vdds_sdi_reg);
 272}
 273
 274static const struct drm_bridge_funcs sdi_bridge_funcs = {
 275        .attach = sdi_bridge_attach,
 276        .mode_valid = sdi_bridge_mode_valid,
 277        .mode_fixup = sdi_bridge_mode_fixup,
 278        .mode_set = sdi_bridge_mode_set,
 279        .enable = sdi_bridge_enable,
 280        .disable = sdi_bridge_disable,
 281};
 282
 283static void sdi_bridge_init(struct sdi_device *sdi)
 284{
 285        sdi->bridge.funcs = &sdi_bridge_funcs;
 286        sdi->bridge.of_node = sdi->pdev->dev.of_node;
 287        sdi->bridge.type = DRM_MODE_CONNECTOR_LVDS;
 288
 289        drm_bridge_add(&sdi->bridge);
 290}
 291
 292static void sdi_bridge_cleanup(struct sdi_device *sdi)
 293{
 294        drm_bridge_remove(&sdi->bridge);
 295}
 296
 297/* -----------------------------------------------------------------------------
 298 * Initialisation and Cleanup
 299 */
 300
 301static int sdi_init_output(struct sdi_device *sdi)
 302{
 303        struct omap_dss_device *out = &sdi->output;
 304        int r;
 305
 306        sdi_bridge_init(sdi);
 307
 308        out->dev = &sdi->pdev->dev;
 309        out->id = OMAP_DSS_OUTPUT_SDI;
 310        out->type = OMAP_DISPLAY_TYPE_SDI;
 311        out->name = "sdi.0";
 312        out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 313        /* We have SDI only on OMAP3, where it's on port 1 */
 314        out->of_port = 1;
 315        out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE     /* 15.5.9.1.2 */
 316                       | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
 317
 318        r = omapdss_device_init_output(out, &sdi->bridge);
 319        if (r < 0) {
 320                sdi_bridge_cleanup(sdi);
 321                return r;
 322        }
 323
 324        omapdss_device_register(out);
 325
 326        return 0;
 327}
 328
 329static void sdi_uninit_output(struct sdi_device *sdi)
 330{
 331        omapdss_device_unregister(&sdi->output);
 332        omapdss_device_cleanup_output(&sdi->output);
 333
 334        sdi_bridge_cleanup(sdi);
 335}
 336
 337int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
 338                  struct device_node *port)
 339{
 340        struct sdi_device *sdi;
 341        struct device_node *ep;
 342        u32 datapairs;
 343        int r;
 344
 345        sdi = kzalloc(sizeof(*sdi), GFP_KERNEL);
 346        if (!sdi)
 347                return -ENOMEM;
 348
 349        ep = of_get_next_child(port, NULL);
 350        if (!ep) {
 351                r = 0;
 352                goto err_free;
 353        }
 354
 355        r = of_property_read_u32(ep, "datapairs", &datapairs);
 356        of_node_put(ep);
 357        if (r) {
 358                DSSERR("failed to parse datapairs\n");
 359                goto err_free;
 360        }
 361
 362        sdi->datapairs = datapairs;
 363        sdi->dss = dss;
 364
 365        sdi->pdev = pdev;
 366        port->data = sdi;
 367
 368        sdi->vdds_sdi_reg = devm_regulator_get(&pdev->dev, "vdds_sdi");
 369        if (IS_ERR(sdi->vdds_sdi_reg)) {
 370                r = PTR_ERR(sdi->vdds_sdi_reg);
 371                if (r != -EPROBE_DEFER)
 372                        DSSERR("can't get VDDS_SDI regulator\n");
 373                goto err_free;
 374        }
 375
 376        r = sdi_init_output(sdi);
 377        if (r)
 378                goto err_free;
 379
 380        return 0;
 381
 382err_free:
 383        kfree(sdi);
 384
 385        return r;
 386}
 387
 388void sdi_uninit_port(struct device_node *port)
 389{
 390        struct sdi_device *sdi = port->data;
 391
 392        if (!sdi)
 393                return;
 394
 395        sdi_uninit_output(sdi);
 396        kfree(sdi);
 397}
 398