Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2024 Freebox SAS
  5 */
  6
  7#include <linux/clk-provider.h>
  8#include <linux/delay.h>
  9
 10#include "hdmi.h"
 11
 12#define HDMI_VCO_MAX_FREQ			12000000000UL
 13#define HDMI_VCO_MIN_FREQ			8000000000UL
 14
 15#define HDMI_PCLK_MAX_FREQ			600000000
 16#define HDMI_PCLK_MIN_FREQ			25000000
 17
 18#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD	3400000000UL
 19#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD		1500000000UL
 20#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD		750000000UL
 21#define HDMI_CORECLK_DIV			5
 22#define HDMI_DEFAULT_REF_CLOCK			19200000
 23#define HDMI_PLL_CMP_CNT			1024
 24
 25#define HDMI_PLL_POLL_MAX_READS			100
 26#define HDMI_PLL_POLL_TIMEOUT_US		150
 27
 28#define HDMI_NUM_TX_CHANNEL			4
 29
 30struct hdmi_pll_8998 {
 31	struct platform_device *pdev;
 32	struct clk_hw clk_hw;
 33	unsigned long rate;
 34
 35	/* pll mmio base */
 36	void __iomem *mmio_qserdes_com;
 37	/* tx channel base */
 38	void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
 39};
 40
 41#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8998, clk_hw)
 42
 43struct hdmi_8998_phy_pll_reg_cfg {
 44	u32 com_svs_mode_clk_sel;
 45	u32 com_hsclk_sel;
 46	u32 com_pll_cctrl_mode0;
 47	u32 com_pll_rctrl_mode0;
 48	u32 com_cp_ctrl_mode0;
 49	u32 com_dec_start_mode0;
 50	u32 com_div_frac_start1_mode0;
 51	u32 com_div_frac_start2_mode0;
 52	u32 com_div_frac_start3_mode0;
 53	u32 com_integloop_gain0_mode0;
 54	u32 com_integloop_gain1_mode0;
 55	u32 com_lock_cmp_en;
 56	u32 com_lock_cmp1_mode0;
 57	u32 com_lock_cmp2_mode0;
 58	u32 com_lock_cmp3_mode0;
 59	u32 com_core_clk_en;
 60	u32 com_coreclk_div_mode0;
 61
 62	u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
 63	u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
 64	u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
 65	u32 tx_lx_pre_driver_1[HDMI_NUM_TX_CHANNEL];
 66	u32 tx_lx_pre_driver_2[HDMI_NUM_TX_CHANNEL];
 67	u32 tx_lx_res_code_offset[HDMI_NUM_TX_CHANNEL];
 68
 69	u32 phy_mode;
 70};
 71
 72struct hdmi_8998_post_divider {
 73	u64 vco_freq;
 74	int hsclk_divsel;
 75	int vco_ratio;
 76	int tx_band_sel;
 77	int half_rate_mode;
 78};
 79
 80static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8998 *pll)
 81{
 82	return platform_get_drvdata(pll->pdev);
 83}
 84
 85static inline void hdmi_pll_write(struct hdmi_pll_8998 *pll, int offset,
 86				  u32 data)
 87{
 88	writel(data, pll->mmio_qserdes_com + offset);
 89}
 90
 91static inline u32 hdmi_pll_read(struct hdmi_pll_8998 *pll, int offset)
 92{
 93	return readl(pll->mmio_qserdes_com + offset);
 94}
 95
 96static inline void hdmi_tx_chan_write(struct hdmi_pll_8998 *pll, int channel,
 97				      int offset, int data)
 98{
 99	 writel(data, pll->mmio_qserdes_tx[channel] + offset);
100}
101
102static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
103				 bool gen_ssc)
104{
105	if ((frac_start != 0) || gen_ssc)
106		return 0x8;
107
108	return 0x30;
109}
110
111static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
112{
113	if ((frac_start != 0) || gen_ssc)
114		return 0x16;
115
116	return 0x18;
117}
118
119static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
120{
121	if ((frac_start != 0) || gen_ssc)
122		return 0x34;
123
124	return 0x2;
125}
126
127static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
128					 bool gen_ssc)
129{
130	int digclk_divsel = bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
131	u64 base;
132
133	if ((frac_start != 0) || gen_ssc)
134		base = 0x3F;
135	else
136		base = 0xC4;
137
138	base <<= (digclk_divsel == 2 ? 1 : 0);
139
140	return base;
141}
142
143static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
144{
145	u64 dividend = HDMI_PLL_CMP_CNT * fdata;
146	u32 divisor = ref_clk * 10;
147	u32 rem;
148
149	rem = do_div(dividend, divisor);
150	if (rem > (divisor >> 1))
151		dividend++;
152
153	return dividend - 1;
154}
155
156#define HDMI_REF_CLOCK_HZ ((u64)19200000)
157#define HDMI_MHZ_TO_HZ ((u64)1000000)
158static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
159{
160	static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25};
161	static const u32 band_list[] = {0, 1, 2, 3};
162	u32 const sz_ratio = ARRAY_SIZE(ratio_list);
163	u32 const sz_band = ARRAY_SIZE(band_list);
164	u32 const cmp_cnt = 1024;
165	u32 const th_min = 500, th_max = 1000;
166	u32 half_rate_mode = 0;
167	u32 list_elements;
168	int optimal_index;
169	u32 i, j, k;
170	u32 found_hsclk_divsel = 0, found_vco_ratio;
171	u32 found_tx_band_sel;
172	u64 const min_freq = HDMI_VCO_MIN_FREQ, max_freq = HDMI_VCO_MAX_FREQ;
173	u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)];
174	u64 found_vco_freq;
175	u64 freq_optimal;
176
177find_optimal_index:
178	freq_optimal = max_freq;
179	optimal_index = -1;
180	list_elements = 0;
181
182	for (i = 0; i < sz_ratio; i++) {
183		for (j = 0; j < sz_band; j++) {
184			u64 freq = div_u64(bclk, (1 << half_rate_mode));
185
186			freq *= (ratio_list[i] * (1 << band_list[j]));
187			freq_list[list_elements++] = freq;
188		}
189	}
190
191	for (k = 0; k < ARRAY_SIZE(freq_list); k++) {
192		u32 const clks_pll_div = 2, core_clk_div = 5;
193		u32 const rng1 = 16, rng2 = 8;
194		u32 th1, th2;
195		u64 core_clk, rvar1, rem;
196
197		core_clk = div_u64(freq_list[k],
198				   ratio_list[k / sz_band] * clks_pll_div *
199				   core_clk_div);
200
201		rvar1 = HDMI_REF_CLOCK_HZ * rng1 * HDMI_MHZ_TO_HZ;
202		rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
203		if (rem > ((cmp_cnt * core_clk) >> 1))
204			rvar1++;
205		th1 = rvar1;
206
207		rvar1 = HDMI_REF_CLOCK_HZ * rng2 * HDMI_MHZ_TO_HZ;
208		rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
209		if (rem > ((cmp_cnt * core_clk) >> 1))
210			rvar1++;
211		th2 = rvar1;
212
213		if (freq_list[k] >= min_freq &&
214				freq_list[k] <= max_freq) {
215			if ((th1 >= th_min && th1 <= th_max) ||
216					(th2 >= th_min && th2 <= th_max)) {
217				if (freq_list[k] <= freq_optimal) {
218					freq_optimal = freq_list[k];
219					optimal_index = k;
220				}
221			}
222		}
223	}
224
225	if (optimal_index == -1) {
226		if (!half_rate_mode) {
227			half_rate_mode = 1;
228			goto find_optimal_index;
229		} else {
230			return -EINVAL;
231		}
232	} else {
233		found_vco_ratio = ratio_list[optimal_index / sz_band];
234		found_tx_band_sel = band_list[optimal_index % sz_band];
235		found_vco_freq = freq_optimal;
236	}
237
238	switch (found_vco_ratio) {
239	case 1:
240		found_hsclk_divsel = 15;
241		break;
242	case 2:
243		found_hsclk_divsel = 0;
244		break;
245	case 3:
246		found_hsclk_divsel = 4;
247		break;
248	case 4:
249		found_hsclk_divsel = 8;
250		break;
251	case 5:
252		found_hsclk_divsel = 12;
253		break;
254	case 6:
255		found_hsclk_divsel = 1;
256		break;
257	case 9:
258		found_hsclk_divsel = 5;
259		break;
260	case 10:
261		found_hsclk_divsel = 2;
262		break;
263	case 12:
264		found_hsclk_divsel = 9;
265		break;
266	case 15:
267		found_hsclk_divsel = 13;
268		break;
269	case 25:
270		found_hsclk_divsel = 14;
271		break;
272	}
273
274	pd->vco_freq = found_vco_freq;
275	pd->tx_band_sel = found_tx_band_sel;
276	pd->vco_ratio = found_vco_ratio;
277	pd->hsclk_divsel = found_hsclk_divsel;
278
279	return 0;
280}
281
282static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
283			 struct hdmi_8998_phy_pll_reg_cfg *cfg)
284{
285	struct hdmi_8998_post_divider pd;
286	u64 bclk;
287	u64 dec_start;
288	u64 frac_start;
289	u64 fdata;
290	u32 pll_divisor;
291	u32 rem;
292	u32 cpctrl;
293	u32 rctrl;
294	u32 cctrl;
295	u32 integloop_gain;
296	u32 pll_cmp;
297	int i, ret;
298
299	/* bit clk = 10 * pix_clk */
300	bclk = ((u64)pix_clk) * 10;
301
302	ret = pll_get_post_div(&pd, bclk);
303	if (ret)
304		return ret;
305
306	dec_start = pd.vco_freq;
307	pll_divisor = 4 * ref_clk;
308	do_div(dec_start, pll_divisor);
309
310	frac_start = pd.vco_freq * (1 << 20);
311
312	rem = do_div(frac_start, pll_divisor);
313	frac_start -= dec_start * (1 << 20);
314	if (rem > (pll_divisor >> 1))
315		frac_start++;
316
317	cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
318	rctrl = pll_get_rctrl(frac_start, false);
319	cctrl = pll_get_cctrl(frac_start, false);
320	integloop_gain = pll_get_integloop_gain(frac_start, bclk,
321						ref_clk, false);
322
323	fdata = pd.vco_freq;
324	do_div(fdata, pd.vco_ratio);
325
326	pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
327
328	/* Convert these values to register specific values */
329	if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
330		cfg->com_svs_mode_clk_sel = 1;
331	else
332		cfg->com_svs_mode_clk_sel = 2;
333
334	cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
335	cfg->com_pll_cctrl_mode0 = cctrl;
336	cfg->com_pll_rctrl_mode0 = rctrl;
337	cfg->com_cp_ctrl_mode0 = cpctrl;
338	cfg->com_dec_start_mode0 = dec_start;
339	cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
340	cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
341	cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
342	cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
343	cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
344	cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
345	cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
346	cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
347	cfg->com_lock_cmp_en = 0x0;
348	cfg->com_core_clk_en = 0x2c;
349	cfg->com_coreclk_div_mode0 = HDMI_CORECLK_DIV;
350	cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x5 : 0x4;
351
352	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
353		cfg->tx_lx_tx_band[i] = pd.tx_band_sel;
354
355	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
356		cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
357		cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
358		cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
359		cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
360		cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
361		cfg->tx_lx_tx_emp_post1_lvl[1] = 0x02;
362		cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
363		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
364		cfg->tx_lx_pre_driver_1[0] = 0x00;
365		cfg->tx_lx_pre_driver_1[1] = 0x00;
366		cfg->tx_lx_pre_driver_1[2] = 0x00;
367		cfg->tx_lx_pre_driver_1[3] = 0x00;
368		cfg->tx_lx_pre_driver_2[0] = 0x1C;
369		cfg->tx_lx_pre_driver_2[1] = 0x1C;
370		cfg->tx_lx_pre_driver_2[2] = 0x1C;
371		cfg->tx_lx_pre_driver_2[3] = 0x00;
372		cfg->tx_lx_res_code_offset[0] = 0x03;
373		cfg->tx_lx_res_code_offset[1] = 0x00;
374		cfg->tx_lx_res_code_offset[2] = 0x00;
375		cfg->tx_lx_res_code_offset[3] = 0x03;
376	} else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) {
377		cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
378		cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
379		cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
380		cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
381		cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
382		cfg->tx_lx_tx_emp_post1_lvl[1] = 0x03;
383		cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
384		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
385		cfg->tx_lx_pre_driver_1[0] = 0x00;
386		cfg->tx_lx_pre_driver_1[1] = 0x00;
387		cfg->tx_lx_pre_driver_1[2] = 0x00;
388		cfg->tx_lx_pre_driver_1[3] = 0x00;
389		cfg->tx_lx_pre_driver_2[0] = 0x16;
390		cfg->tx_lx_pre_driver_2[1] = 0x16;
391		cfg->tx_lx_pre_driver_2[2] = 0x16;
392		cfg->tx_lx_pre_driver_2[3] = 0x18;
393		cfg->tx_lx_res_code_offset[0] = 0x03;
394		cfg->tx_lx_res_code_offset[1] = 0x00;
395		cfg->tx_lx_res_code_offset[2] = 0x00;
396		cfg->tx_lx_res_code_offset[3] = 0x00;
397	} else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
398		cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
399		cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
400		cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
401		cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
402		cfg->tx_lx_tx_emp_post1_lvl[0] = 0x05;
403		cfg->tx_lx_tx_emp_post1_lvl[1] = 0x05;
404		cfg->tx_lx_tx_emp_post1_lvl[2] = 0x05;
405		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
406		cfg->tx_lx_pre_driver_1[0] = 0x00;
407		cfg->tx_lx_pre_driver_1[1] = 0x00;
408		cfg->tx_lx_pre_driver_1[2] = 0x00;
409		cfg->tx_lx_pre_driver_1[3] = 0x00;
410		cfg->tx_lx_pre_driver_2[0] = 0x0E;
411		cfg->tx_lx_pre_driver_2[1] = 0x0E;
412		cfg->tx_lx_pre_driver_2[2] = 0x0E;
413		cfg->tx_lx_pre_driver_2[3] = 0x0E;
414		cfg->tx_lx_res_code_offset[0] = 0x00;
415		cfg->tx_lx_res_code_offset[1] = 0x00;
416		cfg->tx_lx_res_code_offset[2] = 0x00;
417		cfg->tx_lx_res_code_offset[3] = 0x00;
418	} else {
419		cfg->tx_lx_tx_drv_lvl[0] = 0x01;
420		cfg->tx_lx_tx_drv_lvl[1] = 0x01;
421		cfg->tx_lx_tx_drv_lvl[2] = 0x01;
422		cfg->tx_lx_tx_drv_lvl[3] = 0x00;
423		cfg->tx_lx_tx_emp_post1_lvl[0] = 0x00;
424		cfg->tx_lx_tx_emp_post1_lvl[1] = 0x00;
425		cfg->tx_lx_tx_emp_post1_lvl[2] = 0x00;
426		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
427		cfg->tx_lx_pre_driver_1[0] = 0x00;
428		cfg->tx_lx_pre_driver_1[1] = 0x00;
429		cfg->tx_lx_pre_driver_1[2] = 0x00;
430		cfg->tx_lx_pre_driver_1[3] = 0x00;
431		cfg->tx_lx_pre_driver_2[0] = 0x16;
432		cfg->tx_lx_pre_driver_2[1] = 0x16;
433		cfg->tx_lx_pre_driver_2[2] = 0x16;
434		cfg->tx_lx_pre_driver_2[3] = 0x18;
435		cfg->tx_lx_res_code_offset[0] = 0x00;
436		cfg->tx_lx_res_code_offset[1] = 0x00;
437		cfg->tx_lx_res_code_offset[2] = 0x00;
438		cfg->tx_lx_res_code_offset[3] = 0x00;
439	}
440
441	return 0;
442}
443
444static int hdmi_8998_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
445				      unsigned long parent_rate)
446{
447	struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
448	struct hdmi_phy *phy = pll_get_phy(pll);
449	struct hdmi_8998_phy_pll_reg_cfg cfg = {};
450	int i, ret;
451
452	ret = pll_calculate(rate, parent_rate, &cfg);
453	if (ret) {
454		DRM_ERROR("PLL calculation failed\n");
455		return ret;
456	}
457
458	/* Initially shut down PHY */
459	hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x0);
460	udelay(500);
461
462	/* Power up sequence */
463	hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x1);
464	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
465	hdmi_phy_write(phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6);
466
467	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
468		hdmi_tx_chan_write(pll, i,
469				   REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND,
470				   cfg.tx_lx_tx_band[i]);
471		hdmi_tx_chan_write(pll, i,
472				   REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE,
473				   0x1);
474		hdmi_tx_chan_write(pll, i,
475				   REG_HDMI_8998_PHY_TXn_LANE_MODE,
476				   0x20);
477	}
478
479	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x02);
480	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0B);
481	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
482	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
483	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
484
485	/* Bypass VCO calibration */
486	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
487		       cfg.com_svs_mode_clk_sel);
488
489	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_IVCO, 0x07);
490	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_CTRL, 0x00);
491
492	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_SEL, 0x30);
493	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_HSCLK_SEL,
494		       cfg.com_hsclk_sel);
495	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP_EN,
496		       cfg.com_lock_cmp_en);
497
498	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
499		       cfg.com_pll_cctrl_mode0);
500	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
501		       cfg.com_pll_rctrl_mode0);
502	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CP_CTRL_MODE0,
503		       cfg.com_cp_ctrl_mode0);
504	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DEC_START_MODE0,
505		       cfg.com_dec_start_mode0);
506	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
507		       cfg.com_div_frac_start1_mode0);
508	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
509		       cfg.com_div_frac_start2_mode0);
510	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
511		       cfg.com_div_frac_start3_mode0);
512
513	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
514		       cfg.com_integloop_gain0_mode0);
515	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
516		       cfg.com_integloop_gain1_mode0);
517
518	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
519		       cfg.com_lock_cmp1_mode0);
520	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
521		       cfg.com_lock_cmp2_mode0);
522	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
523		       cfg.com_lock_cmp3_mode0);
524
525	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
526	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORE_CLK_EN,
527		       cfg.com_core_clk_en);
528	hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORECLK_DIV_MODE0,
529		       cfg.com_coreclk_div_mode0);
530
531	/* TX lanes setup (TX 0/1/2/3) */
532	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
533		hdmi_tx_chan_write(pll, i,
534				   REG_HDMI_8998_PHY_TXn_DRV_LVL,
535				   cfg.tx_lx_tx_drv_lvl[i]);
536		hdmi_tx_chan_write(pll, i,
537				   REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL,
538				   cfg.tx_lx_tx_emp_post1_lvl[i]);
539		hdmi_tx_chan_write(pll, i,
540				   REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1,
541				   cfg.tx_lx_pre_driver_1[i]);
542		hdmi_tx_chan_write(pll, i,
543				   REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2,
544				   cfg.tx_lx_pre_driver_2[i]);
545		hdmi_tx_chan_write(pll, i,
546				   REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET,
547				   cfg.tx_lx_res_code_offset[i]);
548	}
549
550	hdmi_phy_write(phy, REG_HDMI_8998_PHY_MODE, cfg.phy_mode);
551
552	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
553		hdmi_tx_chan_write(pll, i,
554				   REG_HDMI_8998_PHY_TXn_LANE_CONFIG,
555				   0x10);
556	}
557
558	/*
559	 * Ensure that vco configuration gets flushed to hardware before
560	 * enabling the PLL
561	 */
562	wmb();
563
564	pll->rate = rate;
565
566	return 0;
567}
568
569static int hdmi_8998_phy_ready_status(struct hdmi_phy *phy)
570{
571	u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
572	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
573	u32 status;
574	int phy_ready = 0;
575
576	while (nb_tries--) {
577		status = hdmi_phy_read(phy, REG_HDMI_8998_PHY_STATUS);
578		phy_ready = status & BIT(0);
579
580		if (phy_ready)
581			break;
582
583		udelay(timeout);
584	}
585
586	return phy_ready;
587}
588
589static int hdmi_8998_pll_lock_status(struct hdmi_pll_8998 *pll)
590{
591	u32 status;
592	int nb_tries = HDMI_PLL_POLL_MAX_READS;
593	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
594	int pll_locked = 0;
595
596	while (nb_tries--) {
597		status = hdmi_pll_read(pll,
598				       REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
599		pll_locked = status & BIT(0);
600
601		if (pll_locked)
602			break;
603
604		udelay(timeout);
605	}
606
607	return pll_locked;
608}
609
610static int hdmi_8998_pll_prepare(struct clk_hw *hw)
611{
612	struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
613	struct hdmi_phy *phy = pll_get_phy(pll);
614	int i, ret = 0;
615
616	hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x1);
617	udelay(100);
618
619	hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
620	udelay(100);
621
622	ret = hdmi_8998_pll_lock_status(pll);
623	if (!ret)
624		return ret;
625
626	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
627		hdmi_tx_chan_write(pll, i,
628				   REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1F);
629	}
630
631	/* Ensure all registers are flushed to hardware */
632	wmb();
633
634	ret = hdmi_8998_phy_ready_status(phy);
635	if (!ret)
636		return ret;
637
638	/* Restart the retiming buffer */
639	hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x58);
640	udelay(1);
641	hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
642
643	/* Ensure all registers are flushed to hardware */
644	wmb();
645
646	return 0;
647}
648
649static long hdmi_8998_pll_round_rate(struct clk_hw *hw,
650				     unsigned long rate,
651				     unsigned long *parent_rate)
652{
653	if (rate < HDMI_PCLK_MIN_FREQ)
654		return HDMI_PCLK_MIN_FREQ;
655	else if (rate > HDMI_PCLK_MAX_FREQ)
656		return HDMI_PCLK_MAX_FREQ;
657	else
658		return rate;
659}
660
661static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw,
662					       unsigned long parent_rate)
663{
664	struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
665	return pll->rate;
666}
667
668static void hdmi_8998_pll_unprepare(struct clk_hw *hw)
669{
670	struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
671	struct hdmi_phy *phy = pll_get_phy(pll);
672
673	hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0);
674	usleep_range(100, 150);
675}
676
677static int hdmi_8998_pll_is_enabled(struct clk_hw *hw)
678{
679	struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
680	u32 status;
681	int pll_locked;
682
683	status = hdmi_pll_read(pll, REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
684	pll_locked = status & BIT(0);
685
686	return pll_locked;
687}
688
689static const struct clk_ops hdmi_8998_pll_ops = {
690	.set_rate = hdmi_8998_pll_set_clk_rate,
691	.round_rate = hdmi_8998_pll_round_rate,
692	.recalc_rate = hdmi_8998_pll_recalc_rate,
693	.prepare = hdmi_8998_pll_prepare,
694	.unprepare = hdmi_8998_pll_unprepare,
695	.is_enabled = hdmi_8998_pll_is_enabled,
696};
697
698static const struct clk_init_data pll_init = {
699	.name = "hdmipll",
700	.ops = &hdmi_8998_pll_ops,
701	.parent_data = (const struct clk_parent_data[]){
702		{ .fw_name = "xo", .name = "xo_board" },
703	},
704	.num_parents = 1,
705	.flags = CLK_IGNORE_UNUSED,
706};
707
708int msm_hdmi_pll_8998_init(struct platform_device *pdev)
709{
710	struct device *dev = &pdev->dev;
711	struct hdmi_pll_8998 *pll;
712	int ret, i;
713
714	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
715	if (!pll)
716		return -ENOMEM;
717
718	pll->pdev = pdev;
719
720	pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
721	if (IS_ERR(pll->mmio_qserdes_com)) {
722		DRM_DEV_ERROR(dev, "failed to map pll base\n");
723		return -ENOMEM;
724	}
725
726	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
727		char name[32];
728
729		snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
730
731		pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
732		if (IS_ERR(pll->mmio_qserdes_tx[i])) {
733			DRM_DEV_ERROR(dev, "failed to map pll base\n");
734			return -ENOMEM;
735		}
736	}
737	pll->clk_hw.init = &pll_init;
738
739	ret = devm_clk_hw_register(dev, &pll->clk_hw);
740	if (ret) {
741		DRM_DEV_ERROR(dev, "failed to register pll clock\n");
742		return ret;
743	}
744
745	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
746	if (ret) {
747		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
748		return ret;
749	}
750
751	return 0;
752}
753
754static const char * const hdmi_phy_8998_reg_names[] = {
755	"vddio",
756	"vcca",
757};
758
759static const char * const hdmi_phy_8998_clk_names[] = {
760	"iface", "ref", "xo",
761};
762
763const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg = {
764	.type = MSM_HDMI_PHY_8998,
765	.reg_names = hdmi_phy_8998_reg_names,
766	.num_regs = ARRAY_SIZE(hdmi_phy_8998_reg_names),
767	.clk_names = hdmi_phy_8998_clk_names,
768	.num_clks = ARRAY_SIZE(hdmi_phy_8998_clk_names),
769};