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(DSS_PLL_HDMI, 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(DSS_PLL_HDMI, 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 platform_device *pdev,
 132                              struct hdmi_pll_data *hpll)
 133{
 134        struct dss_pll *pll = &hpll->pll;
 135        struct clk *clk;
 136        int r;
 137
 138        clk = devm_clk_get(&pdev->dev, "sys_clk");
 139        if (IS_ERR(clk)) {
 140                DSSERR("can't get sys_clk\n");
 141                return PTR_ERR(clk);
 142        }
 143
 144        pll->name = "hdmi";
 145        pll->id = DSS_PLL_HDMI;
 146        pll->base = hpll->base;
 147        pll->clkin = clk;
 148
 149        if (hpll->wp->version == 4)
 150                pll->hw = &dss_omap4_hdmi_pll_hw;
 151        else
 152                pll->hw = &dss_omap5_hdmi_pll_hw;
 153
 154        pll->ops = &hdmi_pll_ops;
 155
 156        r = dss_pll_register(pll);
 157        if (r)
 158                return r;
 159
 160        return 0;
 161}
 162
 163int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
 164        struct hdmi_wp_data *wp)
 165{
 166        int r;
 167        struct resource *res;
 168
 169        pll->pdev = pdev;
 170        pll->wp = wp;
 171
 172        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
 173        pll->base = devm_ioremap_resource(&pdev->dev, res);
 174        if (IS_ERR(pll->base))
 175                return PTR_ERR(pll->base);
 176
 177        r = hdmi_init_pll_data(pdev, pll);
 178        if (r) {
 179                DSSERR("failed to init HDMI PLL\n");
 180                return r;
 181        }
 182
 183        return 0;
 184}
 185
 186void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
 187{
 188        struct dss_pll *pll = &hpll->pll;
 189
 190        dss_pll_unregister(pll);
 191}
 192