uboot/drivers/video/rockchip/rk3288_hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <clk.h>
   9#include <display.h>
  10#include <dm.h>
  11#include <dw_hdmi.h>
  12#include <edid.h>
  13#include <regmap.h>
  14#include <syscon.h>
  15#include <asm/gpio.h>
  16#include <asm/io.h>
  17#include <asm/arch/clock.h>
  18#include <asm/arch/hardware.h>
  19#include <asm/arch/grf_rk3288.h>
  20#include <power/regulator.h>
  21#include "rk_hdmi.h"
  22
  23static int rk3288_hdmi_enable(struct udevice *dev, int panel_bpp,
  24                              const struct display_timing *edid)
  25{
  26        struct rk_hdmi_priv *priv = dev_get_priv(dev);
  27        struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
  28        int vop_id = uc_plat->source_id;
  29        struct rk3288_grf *grf = priv->grf;
  30
  31        /* hdmi source select hdmi controller */
  32        rk_setreg(&grf->soc_con6, 1 << 15);
  33
  34        /* hdmi data from vop id */
  35        rk_clrsetreg(&grf->soc_con6, 1 << 4, (vop_id == 1) ? (1 << 4) : 0);
  36
  37        return 0;
  38}
  39
  40static int rk3288_hdmi_ofdata_to_platdata(struct udevice *dev)
  41{
  42        struct rk_hdmi_priv *priv = dev_get_priv(dev);
  43        struct dw_hdmi *hdmi = &priv->hdmi;
  44
  45        hdmi->i2c_clk_high = 0x7a;
  46        hdmi->i2c_clk_low = 0x8d;
  47
  48        /*
  49         * TODO(sjg@chromium.org): The above values don't work - these
  50         * ones work better, but generate lots of errors in the data.
  51         */
  52        hdmi->i2c_clk_high = 0x0d;
  53        hdmi->i2c_clk_low = 0x0d;
  54
  55        return rk_hdmi_ofdata_to_platdata(dev);
  56}
  57
  58static int rk3288_clk_config(struct udevice *dev)
  59{
  60        struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
  61        struct clk clk;
  62        int ret;
  63
  64        /*
  65         * Configure the maximum clock to permit whatever resolution the
  66         * monitor wants
  67         */
  68        ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
  69        if (ret >= 0) {
  70                ret = clk_set_rate(&clk, 384000000);
  71                clk_free(&clk);
  72        }
  73        if (ret < 0) {
  74                debug("%s: Failed to set clock in source device '%s': ret=%d\n",
  75                      __func__, uc_plat->src_dev->name, ret);
  76                return ret;
  77        }
  78
  79        return 0;
  80}
  81
  82static const char * const rk3288_regulator_names[] = {
  83        "vcc50_hdmi"
  84};
  85
  86static int rk3288_hdmi_probe(struct udevice *dev)
  87{
  88        /* Enable VOP clock for RK3288 */
  89        rk3288_clk_config(dev);
  90
  91        /* Enable regulators required for HDMI */
  92        rk_hdmi_probe_regulators(dev, rk3288_regulator_names,
  93                                 ARRAY_SIZE(rk3288_regulator_names));
  94
  95        return rk_hdmi_probe(dev);
  96}
  97
  98static const struct dm_display_ops rk3288_hdmi_ops = {
  99        .read_edid = rk_hdmi_read_edid,
 100        .enable = rk3288_hdmi_enable,
 101};
 102
 103static const struct udevice_id rk3288_hdmi_ids[] = {
 104        { .compatible = "rockchip,rk3288-dw-hdmi" },
 105        { }
 106};
 107
 108U_BOOT_DRIVER(rk3288_hdmi_rockchip) = {
 109        .name = "rk3288_hdmi_rockchip",
 110        .id = UCLASS_DISPLAY,
 111        .of_match = rk3288_hdmi_ids,
 112        .ops = &rk3288_hdmi_ops,
 113        .ofdata_to_platdata = rk3288_hdmi_ofdata_to_platdata,
 114        .probe = rk3288_hdmi_probe,
 115        .priv_auto_alloc_size = sizeof(struct rk_hdmi_priv),
 116};
 117