0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/delay.h>
0010
0011 #include "hdmi.h"
0012
0013 struct hdmi_pll_8960 {
0014 struct platform_device *pdev;
0015 struct clk_hw clk_hw;
0016 void __iomem *mmio;
0017
0018 unsigned long pixclk;
0019 };
0020
0021 #define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8960, clk_hw)
0022
0023
0024
0025
0026
0027
0028
0029
0030 struct pll_rate {
0031 unsigned long rate;
0032 int num_reg;
0033 struct {
0034 u32 val;
0035 u32 reg;
0036 } conf[32];
0037 };
0038
0039
0040 static const struct pll_rate freqtbl[] = {
0041 { 154000000, 14, {
0042 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0043 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0044 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0045 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0046 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0047 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0048 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0049 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0050 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0051 { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0052 { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0053 { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0054 { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0055 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0056 }
0057 },
0058
0059 { 148500000, 27, {
0060 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0061 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
0062 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0063 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0064 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
0065 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
0066 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
0067 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0068 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0069 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0070 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0071 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0072 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
0073 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
0074 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
0075 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
0076 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
0077 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
0078 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
0079 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0080 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0081 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0082 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0083 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0084 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0085 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
0086 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
0087 }
0088 },
0089 { 108000000, 13, {
0090 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0091 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0092 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0093 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0094 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0095 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0096 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0097 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0098 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0099 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0100 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0101 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0102 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0103 }
0104 },
0105
0106 { 74250000, 8, {
0107 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
0108 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0109 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0110 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0111 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0112 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0113 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0114 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0115 }
0116 },
0117 { 74176000, 14, {
0118 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0119 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0120 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0121 { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0122 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0123 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0124 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0125 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0126 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0127 { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0128 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0129 { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0130 { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0131 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0132 }
0133 },
0134 { 65000000, 14, {
0135 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0136 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0137 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0138 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0139 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0140 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0141 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0142 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0143 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0144 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0145 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0146 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0147 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0148 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0149 }
0150 },
0151
0152 { 27030000, 18, {
0153 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
0154 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0155 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
0156 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0157 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0158 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0159 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0160 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0161 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0162 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0163 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0164 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0165 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0166 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0167 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0168 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0169 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
0170 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
0171 }
0172 },
0173
0174 { 27000000, 27, {
0175 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0176 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
0177 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0178 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0179 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
0180 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
0181 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
0182 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0183 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0184 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0185 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0186 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0187 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
0188 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
0189 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
0190 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
0191 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
0192 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
0193 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
0194 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0195 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0196 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0197 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0198 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0199 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0200 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
0201 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
0202 }
0203 },
0204
0205 { 25200000, 27, {
0206 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
0207 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
0208 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
0209 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
0210 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
0211 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
0212 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
0213 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
0214 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
0215 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
0216 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
0217 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
0218 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
0219 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
0220 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
0221 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
0222 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
0223 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
0224 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
0225 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
0226 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
0227 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
0228 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
0229 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
0230 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
0231 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
0232 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
0233 }
0234 },
0235 };
0236
0237 static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data)
0238 {
0239 msm_writel(data, pll->mmio + reg);
0240 }
0241
0242 static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg)
0243 {
0244 return msm_readl(pll->mmio + reg);
0245 }
0246
0247 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll)
0248 {
0249 return platform_get_drvdata(pll->pdev);
0250 }
0251
0252 static int hdmi_pll_enable(struct clk_hw *hw)
0253 {
0254 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
0255 struct hdmi_phy *phy = pll_get_phy(pll);
0256 int timeout_count, pll_lock_retry = 10;
0257 unsigned int val;
0258
0259 DBG("");
0260
0261
0262 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
0263 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
0264 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
0265
0266
0267
0268
0269
0270
0271 udelay(10);
0272
0273
0274 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
0275
0276 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
0277 val |= HDMI_8960_PHY_REG12_SW_RESET;
0278
0279 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
0280 val &= ~HDMI_8960_PHY_REG12_SW_RESET;
0281
0282
0283
0284
0285
0286 udelay(10);
0287
0288 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
0289 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x3f);
0290
0291 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
0292 val |= HDMI_8960_PHY_REG12_PWRDN_B;
0293 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
0294
0295 mb();
0296 udelay(10);
0297
0298 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
0299 val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
0300 val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
0301 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
0302 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80);
0303
0304 timeout_count = 1000;
0305 while (--pll_lock_retry > 0) {
0306
0307 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_STATUS0);
0308 if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
0309 break;
0310
0311 udelay(1);
0312
0313 if (--timeout_count > 0)
0314 continue;
0315
0316
0317
0318
0319
0320
0321 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
0322 udelay(10);
0323 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
0324
0325
0326
0327
0328
0329 udelay(350);
0330
0331 timeout_count = 1000;
0332 }
0333
0334 return 0;
0335 }
0336
0337 static void hdmi_pll_disable(struct clk_hw *hw)
0338 {
0339 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
0340 struct hdmi_phy *phy = pll_get_phy(pll);
0341 unsigned int val;
0342
0343 DBG("");
0344
0345 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
0346 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
0347 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
0348
0349 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
0350 val |= HDMI_8960_PHY_REG12_SW_RESET;
0351 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
0352 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
0353
0354 mb();
0355 }
0356
0357 static const struct pll_rate *find_rate(unsigned long rate)
0358 {
0359 int i;
0360
0361 for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
0362 if (rate > freqtbl[i].rate)
0363 return &freqtbl[i - 1];
0364
0365 return &freqtbl[i - 1];
0366 }
0367
0368 static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
0369 unsigned long parent_rate)
0370 {
0371 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
0372
0373 return pll->pixclk;
0374 }
0375
0376 static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
0377 unsigned long *parent_rate)
0378 {
0379 const struct pll_rate *pll_rate = find_rate(rate);
0380
0381 return pll_rate->rate;
0382 }
0383
0384 static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
0385 unsigned long parent_rate)
0386 {
0387 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
0388 const struct pll_rate *pll_rate = find_rate(rate);
0389 int i;
0390
0391 DBG("rate=%lu", rate);
0392
0393 for (i = 0; i < pll_rate->num_reg; i++)
0394 pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val);
0395
0396 pll->pixclk = rate;
0397
0398 return 0;
0399 }
0400
0401 static const struct clk_ops hdmi_pll_ops = {
0402 .enable = hdmi_pll_enable,
0403 .disable = hdmi_pll_disable,
0404 .recalc_rate = hdmi_pll_recalc_rate,
0405 .round_rate = hdmi_pll_round_rate,
0406 .set_rate = hdmi_pll_set_rate,
0407 };
0408
0409 static const char * const hdmi_pll_parents[] = {
0410 "pxo",
0411 };
0412
0413 static struct clk_init_data pll_init = {
0414 .name = "hdmi_pll",
0415 .ops = &hdmi_pll_ops,
0416 .parent_names = hdmi_pll_parents,
0417 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
0418 .flags = CLK_IGNORE_UNUSED,
0419 };
0420
0421 int msm_hdmi_pll_8960_init(struct platform_device *pdev)
0422 {
0423 struct device *dev = &pdev->dev;
0424 struct hdmi_pll_8960 *pll;
0425 struct clk *clk;
0426 int i;
0427
0428
0429 for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
0430 if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate))
0431 return -EINVAL;
0432
0433 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
0434 if (!pll)
0435 return -ENOMEM;
0436
0437 pll->mmio = msm_ioremap(pdev, "hdmi_pll");
0438 if (IS_ERR(pll->mmio)) {
0439 DRM_DEV_ERROR(dev, "failed to map pll base\n");
0440 return -ENOMEM;
0441 }
0442
0443 pll->pdev = pdev;
0444 pll->clk_hw.init = &pll_init;
0445
0446 clk = devm_clk_register(dev, &pll->clk_hw);
0447 if (IS_ERR(clk)) {
0448 DRM_DEV_ERROR(dev, "failed to register pll clock\n");
0449 return -EINVAL;
0450 }
0451
0452 return 0;
0453 }