linux/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
<<
>>
Prefs
   1/*
   2 * HDMI PLL
   3 *
   4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 */
  10
  11#define DSS_SUBSYS_NAME "HDMIPLL"
  12
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/err.h>
  16#include <linux/io.h>
  17#include <linux/platform_device.h>
  18#include <linux/clk.h>
  19#include <linux/seq_file.h>
  20#include <linux/pm_runtime.h>
  21
  22#include "omapdss.h"
  23#include "dss.h"
  24#include "hdmi.h"
  25
  26void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
  27{
  28#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
  29                hdmi_read_reg(pll->base, r))
  30
  31        DUMPPLL(PLLCTRL_PLL_CONTROL);
  32        DUMPPLL(PLLCTRL_PLL_STATUS);
  33        DUMPPLL(PLLCTRL_PLL_GO);
  34        DUMPPLL(PLLCTRL_CFG1);
  35        DUMPPLL(PLLCTRL_CFG2);
  36        DUMPPLL(PLLCTRL_CFG3);
  37        DUMPPLL(PLLCTRL_SSC_CFG1);
  38        DUMPPLL(PLLCTRL_SSC_CFG2);
  39        DUMPPLL(PLLCTRL_CFG4);
  40}
  41
  42static int hdmi_pll_enable(struct dss_pll *dsspll)
  43{
  44        struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
  45        struct hdmi_wp_data *wp = pll->wp;
  46        int r;
  47
  48        r = pm_runtime_get_sync(&pll->pdev->dev);
  49        WARN_ON(r < 0);
  50
  51        dss_ctrl_pll_enable(dsspll, true);
  52
  53        r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
  54        if (r)
  55                return r;
  56
  57        return 0;
  58}
  59
  60static void hdmi_pll_disable(struct dss_pll *dsspll)
  61{
  62        struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
  63        struct hdmi_wp_data *wp = pll->wp;
  64        int r;
  65
  66        hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
  67
  68        dss_ctrl_pll_enable(dsspll, false);
  69
  70        r = pm_runtime_put_sync(&pll->pdev->dev);
  71        WARN_ON(r < 0 && r != -ENOSYS);
  72}
  73
  74static const struct dss_pll_ops hdmi_pll_ops = {
  75        .enable = hdmi_pll_enable,
  76        .disable = hdmi_pll_disable,
  77        .set_config = dss_pll_write_config_type_b,
  78};
  79
  80static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
  81        .type = DSS_PLL_TYPE_B,
  82
  83        .n_max = 255,
  84        .m_min = 20,
  85        .m_max = 4095,
  86        .mX_max = 127,
  87        .fint_min = 500000,
  88        .fint_max = 2500000,
  89
  90        .clkdco_min = 500000000,
  91        .clkdco_low = 1000000000,
  92        .clkdco_max = 2000000000,
  93
  94        .n_msb = 8,
  95        .n_lsb = 1,
  96        .m_msb = 20,
  97        .m_lsb = 9,
  98
  99        .mX_msb[0] = 24,
 100        .mX_lsb[0] = 18,
 101
 102        .has_selfreqdco = true,
 103};
 104
 105static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
 106        .type = DSS_PLL_TYPE_B,
 107
 108        .n_max = 255,
 109        .m_min = 20,
 110        .m_max = 2045,
 111        .mX_max = 127,
 112        .fint_min = 620000,
 113        .fint_max = 2500000,
 114
 115        .clkdco_min = 750000000,
 116        .clkdco_low = 1500000000,
 117        .clkdco_max = 2500000000UL,
 118
 119        .n_msb = 8,
 120        .n_lsb = 1,
 121        .m_msb = 20,
 122        .m_lsb = 9,
 123
 124        .mX_msb[0] = 24,
 125        .mX_lsb[0] = 18,
 126
 127        .has_selfreqdco = true,
 128        .has_refsel = true,
 129};
 130
 131static int hdmi_init_pll_data(struct dss_device *dss,
 132                              struct platform_device *pdev,
 133                              struct hdmi_pll_data *hpll)
 134{
 135        struct dss_pll *pll = &hpll->pll;
 136        struct clk *clk;
 137        int r;
 138
 139        clk = devm_clk_get(&pdev->dev, "sys_clk");
 140        if (IS_ERR(clk)) {
 141                DSSERR("can't get sys_clk\n");
 142                return PTR_ERR(clk);
 143        }
 144
 145        pll->name = "hdmi";
 146        pll->id = DSS_PLL_HDMI;
 147        pll->base = hpll->base;
 148        pll->clkin = clk;
 149
 150        if (hpll->wp->version == 4)
 151                pll->hw = &dss_omap4_hdmi_pll_hw;
 152        else
 153                pll->hw = &dss_omap5_hdmi_pll_hw;
 154
 155        pll->ops = &hdmi_pll_ops;
 156
 157        r = dss_pll_register(dss, pll);
 158        if (r)
 159                return r;
 160
 161        return 0;
 162}
 163
 164int hdmi_pll_init(struct dss_device *dss, struct platform_device *pdev,
 165                  struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
 166{
 167        int r;
 168        struct resource *res;
 169
 170        pll->pdev = pdev;
 171        pll->wp = wp;
 172
 173        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
 174        pll->base = devm_ioremap_resource(&pdev->dev, res);
 175        if (IS_ERR(pll->base))
 176                return PTR_ERR(pll->base);
 177
 178        r = hdmi_init_pll_data(dss, pdev, pll);
 179        if (r) {
 180                DSSERR("failed to init HDMI PLL\n");
 181                return r;
 182        }
 183
 184        return 0;
 185}
 186
 187void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
 188{
 189        struct dss_pll *pll = &hpll->pll;
 190
 191        dss_pll_unregister(pll);
 192}
 193