root/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c

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

DEFINITIONS

This source file includes following definitions.
  1. hdmi_pll_dump
  2. hdmi_pll_compute
  3. hdmi_pll_enable
  4. hdmi_pll_disable
  5. dsi_init_pll_data
  6. hdmi_pll_init
  7. hdmi_pll_uninit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * HDMI PLL
   4  *
   5  * Copyright (C) 2013 Texas Instruments Incorporated
   6  */
   7 
   8 #define DSS_SUBSYS_NAME "HDMIPLL"
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/err.h>
  13 #include <linux/io.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/clk.h>
  16 #include <linux/seq_file.h>
  17 
  18 #include <video/omapfb_dss.h>
  19 
  20 #include "dss.h"
  21 #include "hdmi.h"
  22 
  23 void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
  24 {
  25 #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
  26                 hdmi_read_reg(pll->base, r))
  27 
  28         DUMPPLL(PLLCTRL_PLL_CONTROL);
  29         DUMPPLL(PLLCTRL_PLL_STATUS);
  30         DUMPPLL(PLLCTRL_PLL_GO);
  31         DUMPPLL(PLLCTRL_CFG1);
  32         DUMPPLL(PLLCTRL_CFG2);
  33         DUMPPLL(PLLCTRL_CFG3);
  34         DUMPPLL(PLLCTRL_SSC_CFG1);
  35         DUMPPLL(PLLCTRL_SSC_CFG2);
  36         DUMPPLL(PLLCTRL_CFG4);
  37 }
  38 
  39 void hdmi_pll_compute(struct hdmi_pll_data *pll,
  40         unsigned long target_tmds, struct dss_pll_clock_info *pi)
  41 {
  42         unsigned long fint, clkdco, clkout;
  43         unsigned long target_bitclk, target_clkdco;
  44         unsigned long min_dco;
  45         unsigned n, m, mf, m2, sd;
  46         unsigned long clkin;
  47         const struct dss_pll_hw *hw = pll->pll.hw;
  48 
  49         clkin = clk_get_rate(pll->pll.clkin);
  50 
  51         DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
  52 
  53         target_bitclk = target_tmds * 10;
  54 
  55         /* Fint */
  56         n = DIV_ROUND_UP(clkin, hw->fint_max);
  57         fint = clkin / n;
  58 
  59         /* adjust m2 so that the clkdco will be high enough */
  60         min_dco = roundup(hw->clkdco_min, fint);
  61         m2 = DIV_ROUND_UP(min_dco, target_bitclk);
  62         if (m2 == 0)
  63                 m2 = 1;
  64 
  65         target_clkdco = target_bitclk * m2;
  66         m = target_clkdco / fint;
  67 
  68         clkdco = fint * m;
  69 
  70         /* adjust clkdco with fractional mf */
  71         if (WARN_ON(target_clkdco - clkdco > fint))
  72                 mf = 0;
  73         else
  74                 mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
  75 
  76         if (mf > 0)
  77                 clkdco += (u32)div_u64((u64)mf * fint, 262144);
  78 
  79         clkout = clkdco / m2;
  80 
  81         /* sigma-delta */
  82         sd = DIV_ROUND_UP(fint * m, 250000000);
  83 
  84         DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
  85                 n, m, mf, m2, sd);
  86         DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
  87 
  88         pi->n = n;
  89         pi->m = m;
  90         pi->mf = mf;
  91         pi->mX[0] = m2;
  92         pi->sd = sd;
  93 
  94         pi->fint = fint;
  95         pi->clkdco = clkdco;
  96         pi->clkout[0] = clkout;
  97 }
  98 
  99 static int hdmi_pll_enable(struct dss_pll *dsspll)
 100 {
 101         struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
 102         struct hdmi_wp_data *wp = pll->wp;
 103         u16 r = 0;
 104 
 105         dss_ctrl_pll_enable(DSS_PLL_HDMI, true);
 106 
 107         r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
 108         if (r)
 109                 return r;
 110 
 111         return 0;
 112 }
 113 
 114 static void hdmi_pll_disable(struct dss_pll *dsspll)
 115 {
 116         struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
 117         struct hdmi_wp_data *wp = pll->wp;
 118 
 119         hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
 120 
 121         dss_ctrl_pll_enable(DSS_PLL_HDMI, false);
 122 }
 123 
 124 static const struct dss_pll_ops dsi_pll_ops = {
 125         .enable = hdmi_pll_enable,
 126         .disable = hdmi_pll_disable,
 127         .set_config = dss_pll_write_config_type_b,
 128 };
 129 
 130 static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
 131         .n_max = 255,
 132         .m_min = 20,
 133         .m_max = 4095,
 134         .mX_max = 127,
 135         .fint_min = 500000,
 136         .fint_max = 2500000,
 137 
 138         .clkdco_min = 500000000,
 139         .clkdco_low = 1000000000,
 140         .clkdco_max = 2000000000,
 141 
 142         .n_msb = 8,
 143         .n_lsb = 1,
 144         .m_msb = 20,
 145         .m_lsb = 9,
 146 
 147         .mX_msb[0] = 24,
 148         .mX_lsb[0] = 18,
 149 
 150         .has_selfreqdco = true,
 151 };
 152 
 153 static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
 154         .n_max = 255,
 155         .m_min = 20,
 156         .m_max = 2045,
 157         .mX_max = 127,
 158         .fint_min = 620000,
 159         .fint_max = 2500000,
 160 
 161         .clkdco_min = 750000000,
 162         .clkdco_low = 1500000000,
 163         .clkdco_max = 2500000000UL,
 164 
 165         .n_msb = 8,
 166         .n_lsb = 1,
 167         .m_msb = 20,
 168         .m_lsb = 9,
 169 
 170         .mX_msb[0] = 24,
 171         .mX_lsb[0] = 18,
 172 
 173         .has_selfreqdco = true,
 174         .has_refsel = true,
 175 };
 176 
 177 static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll)
 178 {
 179         struct dss_pll *pll = &hpll->pll;
 180         struct clk *clk;
 181         int r;
 182 
 183         clk = devm_clk_get(&pdev->dev, "sys_clk");
 184         if (IS_ERR(clk)) {
 185                 DSSERR("can't get sys_clk\n");
 186                 return PTR_ERR(clk);
 187         }
 188 
 189         pll->name = "hdmi";
 190         pll->id = DSS_PLL_HDMI;
 191         pll->base = hpll->base;
 192         pll->clkin = clk;
 193 
 194         switch (omapdss_get_version()) {
 195         case OMAPDSS_VER_OMAP4430_ES1:
 196         case OMAPDSS_VER_OMAP4430_ES2:
 197         case OMAPDSS_VER_OMAP4:
 198                 pll->hw = &dss_omap4_hdmi_pll_hw;
 199                 break;
 200 
 201         case OMAPDSS_VER_OMAP5:
 202         case OMAPDSS_VER_DRA7xx:
 203                 pll->hw = &dss_omap5_hdmi_pll_hw;
 204                 break;
 205 
 206         default:
 207                 return -ENODEV;
 208         }
 209 
 210         pll->ops = &dsi_pll_ops;
 211 
 212         r = dss_pll_register(pll);
 213         if (r)
 214                 return r;
 215 
 216         return 0;
 217 }
 218 
 219 int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
 220         struct hdmi_wp_data *wp)
 221 {
 222         int r;
 223         struct resource *res;
 224 
 225         pll->wp = wp;
 226 
 227         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
 228         if (!res) {
 229                 DSSERR("can't get PLL mem resource\n");
 230                 return -EINVAL;
 231         }
 232 
 233         pll->base = devm_ioremap_resource(&pdev->dev, res);
 234         if (IS_ERR(pll->base)) {
 235                 DSSERR("can't ioremap PLLCTRL\n");
 236                 return PTR_ERR(pll->base);
 237         }
 238 
 239         r = dsi_init_pll_data(pdev, pll);
 240         if (r) {
 241                 DSSERR("failed to init HDMI PLL\n");
 242                 return r;
 243         }
 244 
 245         return 0;
 246 }
 247 
 248 void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
 249 {
 250         struct dss_pll *pll = &hpll->pll;
 251 
 252         dss_pll_unregister(pll);
 253 }

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