]> Git Repo - linux.git/blob - drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
net: bgmac: Fix return value check for fixed_phy_register()
[linux.git] / drivers / gpu / drm / msm / hdmi / hdmi_pll_8960.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
4  * Copyright (C) 2013 Red Hat
5  * Author: Rob Clark <[email protected]>
6  */
7
8 #include <linux/clk-provider.h>
9 #include <linux/delay.h>
10
11 #include "hdmi.h"
12
13 struct hdmi_pll_8960 {
14         struct platform_device *pdev;
15         struct clk_hw clk_hw;
16         void __iomem *mmio;
17
18         unsigned long pixclk;
19 };
20
21 #define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8960, clk_hw)
22
23 /*
24  * HDMI PLL:
25  *
26  * To get the parent clock setup properly, we need to plug in hdmi pll
27  * configuration into common-clock-framework.
28  */
29
30 struct pll_rate {
31         unsigned long rate;
32         int num_reg;
33         struct {
34                 u32 val;
35                 u32 reg;
36         } conf[32];
37 };
38
39 /* NOTE: keep sorted highest freq to lowest: */
40 static const struct pll_rate freqtbl[] = {
41         { 154000000, 14, {
42                 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
43                 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
44                 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
45                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
46                 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
47                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
48                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
49                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
50                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
51                 { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
52                 { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
53                 { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
54                 { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
55                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
56                         }
57         },
58         /* 1080p60/1080p50 case */
59         { 148500000, 27, {
60                 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
61                 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
62                 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
63                 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
64                 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
65                 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
66                 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
67                 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
68                 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
69                 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
70                 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
71                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
72                 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
73                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
74                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
75                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
76                 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
77                 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
78                 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
79                 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
80                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
81                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
82                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
83                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
84                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
85                 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
86                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
87                         }
88         },
89         { 108000000, 13, {
90                 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
91                 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
92                 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
93                 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
94                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
95                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
96                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
97                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
98                 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
99                 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
100                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
101                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
102                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
103                         }
104         },
105         /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
106         { 74250000, 8, {
107                 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
108                 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
109                 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
110                 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
111                 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
112                 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
113                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
114                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
115                         }
116         },
117         { 74176000, 14, {
118                 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
119                 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
120                 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
121                 { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
122                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
123                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
124                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
125                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
126                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
127                 { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
128                 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
129                 { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
130                 { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
131                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
132                         }
133         },
134         { 65000000, 14, {
135                 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
136                 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
137                 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
138                 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
139                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
140                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
141                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
142                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
143                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
144                 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
145                 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
146                 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
147                 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
148                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
149                         }
150         },
151         /* 480p60/480i60 */
152         { 27030000, 18, {
153                 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
154                 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
155                 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
156                 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
157                 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
158                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
159                 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
160                 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
161                 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
162                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
163                 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
164                 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
165                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
166                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
167                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
168                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
169                 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
170                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
171                         }
172         },
173         /* 576p50/576i50 */
174         { 27000000, 27, {
175                 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
176                 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
177                 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
178                 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
179                 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
180                 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
181                 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
182                 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
183                 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
184                 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
185                 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
186                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
187                 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
188                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
189                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
190                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
191                 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
192                 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
193                 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
194                 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
195                 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
196                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
197                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
198                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
199                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
200                 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
201                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
202                         }
203         },
204         /* 640x480p60 */
205         { 25200000, 27, {
206                 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
207                 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
208                 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
209                 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
210                 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
211                 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
212                 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
213                 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
214                 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
215                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
216                 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
217                 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
218                 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
219                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
220                 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
221                 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
222                 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
223                 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
224                 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
225                 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
226                 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
227                 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
228                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
229                 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
230                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
231                 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
232                 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
233                         }
234         },
235 };
236
237 static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data)
238 {
239         msm_writel(data, pll->mmio + reg);
240 }
241
242 static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg)
243 {
244         return msm_readl(pll->mmio + reg);
245 }
246
247 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll)
248 {
249         return platform_get_drvdata(pll->pdev);
250 }
251
252 static int hdmi_pll_enable(struct clk_hw *hw)
253 {
254         struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
255         struct hdmi_phy *phy = pll_get_phy(pll);
256         int timeout_count, pll_lock_retry = 10;
257         unsigned int val;
258
259         DBG("");
260
261         /* Assert PLL S/W reset */
262         pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
263         pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
264         pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
265
266         /* Wait for a short time before de-asserting
267          * to allow the hardware to complete its job.
268          * This much of delay should be fine for hardware
269          * to assert and de-assert.
270          */
271         udelay(10);
272
273         /* De-assert PLL S/W reset */
274         pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
275
276         val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
277         val |= HDMI_8960_PHY_REG12_SW_RESET;
278         /* Assert PHY S/W reset */
279         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
280         val &= ~HDMI_8960_PHY_REG12_SW_RESET;
281         /*
282          * Wait for a short time before de-asserting to allow the hardware to
283          * complete its job. This much of delay should be fine for hardware to
284          * assert and de-assert.
285          */
286         udelay(10);
287         /* De-assert PHY S/W reset */
288         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
289         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2,  0x3f);
290
291         val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
292         val |= HDMI_8960_PHY_REG12_PWRDN_B;
293         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
294         /* Wait 10 us for enabling global power for PHY */
295         mb();
296         udelay(10);
297
298         val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
299         val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
300         val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
301         pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
302         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80);
303
304         timeout_count = 1000;
305         while (--pll_lock_retry > 0) {
306                 /* are we there yet? */
307                 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_STATUS0);
308                 if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
309                         break;
310
311                 udelay(1);
312
313                 if (--timeout_count > 0)
314                         continue;
315
316                 /*
317                  * PLL has still not locked.
318                  * Do a software reset and try again
319                  * Assert PLL S/W reset first
320                  */
321                 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
322                 udelay(10);
323                 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
324
325                 /*
326                  * Wait for a short duration for the PLL calibration
327                  * before checking if the PLL gets locked
328                  */
329                 udelay(350);
330
331                 timeout_count = 1000;
332         }
333
334         return 0;
335 }
336
337 static void hdmi_pll_disable(struct clk_hw *hw)
338 {
339         struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
340         struct hdmi_phy *phy = pll_get_phy(pll);
341         unsigned int val;
342
343         DBG("");
344
345         val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
346         val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
347         hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
348
349         val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
350         val |= HDMI_8960_PHY_REG12_SW_RESET;
351         val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
352         pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
353         /* Make sure HDMI PHY/PLL are powered down */
354         mb();
355 }
356
357 static const struct pll_rate *find_rate(unsigned long rate)
358 {
359         int i;
360
361         for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
362                 if (rate > freqtbl[i].rate)
363                         return &freqtbl[i - 1];
364
365         return &freqtbl[i - 1];
366 }
367
368 static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
369                                           unsigned long parent_rate)
370 {
371         struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
372
373         return pll->pixclk;
374 }
375
376 static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
377                                 unsigned long *parent_rate)
378 {
379         const struct pll_rate *pll_rate = find_rate(rate);
380
381         return pll_rate->rate;
382 }
383
384 static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
385                              unsigned long parent_rate)
386 {
387         struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
388         const struct pll_rate *pll_rate = find_rate(rate);
389         int i;
390
391         DBG("rate=%lu", rate);
392
393         for (i = 0; i < pll_rate->num_reg; i++)
394                 pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val);
395
396         pll->pixclk = rate;
397
398         return 0;
399 }
400
401 static const struct clk_ops hdmi_pll_ops = {
402         .enable = hdmi_pll_enable,
403         .disable = hdmi_pll_disable,
404         .recalc_rate = hdmi_pll_recalc_rate,
405         .round_rate = hdmi_pll_round_rate,
406         .set_rate = hdmi_pll_set_rate,
407 };
408
409 static const struct clk_parent_data hdmi_pll_parents[] = {
410         { .fw_name = "pxo", .name = "pxo_board" },
411 };
412
413 static struct clk_init_data pll_init = {
414         .name = "hdmi_pll",
415         .ops = &hdmi_pll_ops,
416         .parent_data = hdmi_pll_parents,
417         .num_parents = ARRAY_SIZE(hdmi_pll_parents),
418         .flags = CLK_IGNORE_UNUSED,
419 };
420
421 int msm_hdmi_pll_8960_init(struct platform_device *pdev)
422 {
423         struct device *dev = &pdev->dev;
424         struct hdmi_pll_8960 *pll;
425         int i, ret;
426
427         /* sanity check: */
428         for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
429                 if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate))
430                         return -EINVAL;
431
432         pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
433         if (!pll)
434                 return -ENOMEM;
435
436         pll->mmio = msm_ioremap(pdev, "hdmi_pll");
437         if (IS_ERR(pll->mmio)) {
438                 DRM_DEV_ERROR(dev, "failed to map pll base\n");
439                 return -ENOMEM;
440         }
441
442         pll->pdev = pdev;
443         pll->clk_hw.init = &pll_init;
444
445         ret = devm_clk_hw_register(dev, &pll->clk_hw);
446         if (ret < 0) {
447                 DRM_DEV_ERROR(dev, "failed to register pll clock\n");
448                 return ret;
449         }
450
451         ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
452         if (ret) {
453                 DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);
454                 return ret;
455         }
456
457         return 0;
458 }
This page took 0.063888 seconds and 4 git commands to generate.