Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 and
  6 * only version 2 as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11 * GNU General Public License for more details.
 12 */
 13
 14#include <linux/clk-provider.h>
 15
 16#include "hdmi.h"
 17
 18#define HDMI_VCO_MAX_FREQ			12000000000UL
 19#define HDMI_VCO_MIN_FREQ			8000000000UL
 20
 21#define HDMI_PCLK_MAX_FREQ			600000000
 22#define HDMI_PCLK_MIN_FREQ			25000000
 23
 24#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD	3400000000UL
 25#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD		1500000000UL
 26#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD		750000000UL
 27#define HDMI_CORECLK_DIV			5
 28#define HDMI_DEFAULT_REF_CLOCK			19200000
 29#define HDMI_PLL_CMP_CNT			1024
 30
 31#define HDMI_PLL_POLL_MAX_READS			100
 32#define HDMI_PLL_POLL_TIMEOUT_US		150
 33
 34#define HDMI_NUM_TX_CHANNEL			4
 35
 36struct hdmi_pll_8996 {
 37	struct platform_device *pdev;
 38	struct clk_hw clk_hw;
 39
 40	/* pll mmio base */
 41	void __iomem *mmio_qserdes_com;
 42	/* tx channel base */
 43	void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
 44};
 45
 46#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw)
 47
 48struct hdmi_8996_phy_pll_reg_cfg {
 49	u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL];
 50	u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
 51	u32 com_svs_mode_clk_sel;
 52	u32 com_hsclk_sel;
 53	u32 com_pll_cctrl_mode0;
 54	u32 com_pll_rctrl_mode0;
 55	u32 com_cp_ctrl_mode0;
 56	u32 com_dec_start_mode0;
 57	u32 com_div_frac_start1_mode0;
 58	u32 com_div_frac_start2_mode0;
 59	u32 com_div_frac_start3_mode0;
 60	u32 com_integloop_gain0_mode0;
 61	u32 com_integloop_gain1_mode0;
 62	u32 com_lock_cmp_en;
 63	u32 com_lock_cmp1_mode0;
 64	u32 com_lock_cmp2_mode0;
 65	u32 com_lock_cmp3_mode0;
 66	u32 com_core_clk_en;
 67	u32 com_coreclk_div;
 68	u32 com_vco_tune_ctrl;
 69
 70	u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
 71	u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
 72	u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL];
 73	u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL];
 74	u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL];
 75	u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL];
 76
 77	u32 phy_mode;
 78};
 79
 80struct hdmi_8996_post_divider {
 81	u64 vco_freq;
 82	int hsclk_divsel;
 83	int vco_ratio;
 84	int tx_band_sel;
 85	int half_rate_mode;
 86};
 87
 88static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
 89{
 90	return platform_get_drvdata(pll->pdev);
 91}
 92
 93static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset,
 94				  u32 data)
 95{
 96	msm_writel(data, pll->mmio_qserdes_com + offset);
 97}
 98
 99static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
100{
101	return msm_readl(pll->mmio_qserdes_com + offset);
102}
103
104static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel,
105				      int offset, int data)
106{
107	 msm_writel(data, pll->mmio_qserdes_tx[channel] + offset);
108}
109
110static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
111				 bool gen_ssc)
112{
113	if ((frac_start != 0) || gen_ssc)
114		return (11000000 / (ref_clk / 20));
115
116	return 0x23;
117}
118
119static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
120{
121	if ((frac_start != 0) || gen_ssc)
122		return 0x16;
123
124	return 0x10;
125}
126
127static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
128{
129	if ((frac_start != 0) || gen_ssc)
130		return 0x28;
131
132	return 0x1;
133}
134
135static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
136					 bool gen_ssc)
137{
138	int digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
139	u64 base;
140
141	if ((frac_start != 0) || gen_ssc)
142		base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK;
143	else
144		base = (1022 * ref_clk) / 100;
145
146	base <<= digclk_divsel;
147
148	return (base <= 2046 ? base : 2046);
149}
150
151static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
152{
153	u64 dividend = HDMI_PLL_CMP_CNT * fdata;
154	u32 divisor = ref_clk * 10;
155	u32 rem;
156
157	rem = do_div(dividend, divisor);
158	if (rem > (divisor >> 1))
159		dividend++;
160
161	return dividend - 1;
162}
163
164static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
165{
166	u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
167
168	do_div(fdata, HDMI_PLL_CMP_CNT);
169
170	return fdata;
171}
172
173static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk)
174{
175	int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 };
176	int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 };
177	int tx_band_sel[] = { 0, 1, 2, 3 };
178	u64 vco_freq[60];
179	u64 vco, vco_optimal;
180	int half_rate_mode = 0;
181	int vco_optimal_index, vco_freq_index;
182	int i, j;
183
184retry:
185	vco_optimal = HDMI_VCO_MAX_FREQ;
186	vco_optimal_index = -1;
187	vco_freq_index = 0;
188	for (i = 0; i < 15; i++) {
189		for (j = 0; j < 4; j++) {
190			u32 ratio_mult = ratio[i] << tx_band_sel[j];
191
192			vco = bclk >> half_rate_mode;
193			vco *= ratio_mult;
194			vco_freq[vco_freq_index++] = vco;
195		}
196	}
197
198	for (i = 0; i < 60; i++) {
199		u64 vco_tmp = vco_freq[i];
200
201		if ((vco_tmp >= HDMI_VCO_MIN_FREQ) &&
202		    (vco_tmp <= vco_optimal)) {
203			vco_optimal = vco_tmp;
204			vco_optimal_index = i;
205		}
206	}
207
208	if (vco_optimal_index == -1) {
209		if (!half_rate_mode) {
210			half_rate_mode = 1;
211			goto retry;
212		}
213	} else {
214		pd->vco_freq = vco_optimal;
215		pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4];
216		pd->vco_ratio = ratio[vco_optimal_index / 4];
217		pd->hsclk_divsel = hs_divsel[vco_optimal_index / 4];
218
219		return 0;
220	}
221
222	return -EINVAL;
223}
224
225static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
226			 struct hdmi_8996_phy_pll_reg_cfg *cfg)
227{
228	struct hdmi_8996_post_divider pd;
229	u64 bclk;
230	u64 tmds_clk;
231	u64 dec_start;
232	u64 frac_start;
233	u64 fdata;
234	u32 pll_divisor;
235	u32 rem;
236	u32 cpctrl;
237	u32 rctrl;
238	u32 cctrl;
239	u32 integloop_gain;
240	u32 pll_cmp;
241	int i, ret;
242
243	/* bit clk = 10 * pix_clk */
244	bclk = ((u64)pix_clk) * 10;
245
246	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
247		tmds_clk = pix_clk >> 2;
248	else
249		tmds_clk = pix_clk;
250
251	ret = pll_get_post_div(&pd, bclk);
252	if (ret)
253		return ret;
254
255	dec_start = pd.vco_freq;
256	pll_divisor = 4 * ref_clk;
257	do_div(dec_start, pll_divisor);
258
259	frac_start = pd.vco_freq * (1 << 20);
260
261	rem = do_div(frac_start, pll_divisor);
262	frac_start -= dec_start * (1 << 20);
263	if (rem > (pll_divisor >> 1))
264		frac_start++;
265
266	cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
267	rctrl = pll_get_rctrl(frac_start, false);
268	cctrl = pll_get_cctrl(frac_start, false);
269	integloop_gain = pll_get_integloop_gain(frac_start, bclk,
270						ref_clk, false);
271
272	fdata = pd.vco_freq;
273	do_div(fdata, pd.vco_ratio);
274
275	pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
276
277	DBG("VCO freq: %llu", pd.vco_freq);
278	DBG("fdata: %llu", fdata);
279	DBG("pix_clk: %lu", pix_clk);
280	DBG("tmds clk: %llu", tmds_clk);
281	DBG("HSCLK_SEL: %d", pd.hsclk_divsel);
282	DBG("DEC_START: %llu", dec_start);
283	DBG("DIV_FRAC_START: %llu", frac_start);
284	DBG("PLL_CPCTRL: %u", cpctrl);
285	DBG("PLL_RCTRL: %u", rctrl);
286	DBG("PLL_CCTRL: %u", cctrl);
287	DBG("INTEGLOOP_GAIN: %u", integloop_gain);
288	DBG("TX_BAND: %d", pd.tx_band_sel);
289	DBG("PLL_CMP: %u", pll_cmp);
290
291	/* Convert these values to register specific values */
292	if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
293		cfg->com_svs_mode_clk_sel = 1;
294	else
295		cfg->com_svs_mode_clk_sel = 2;
296
297	cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
298	cfg->com_pll_cctrl_mode0 = cctrl;
299	cfg->com_pll_rctrl_mode0 = rctrl;
300	cfg->com_cp_ctrl_mode0 = cpctrl;
301	cfg->com_dec_start_mode0 = dec_start;
302	cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
303	cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
304	cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
305	cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
306	cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
307	cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
308	cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
309	cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
310	cfg->com_lock_cmp_en = 0x0;
311	cfg->com_core_clk_en = 0x2c;
312	cfg->com_coreclk_div = HDMI_CORECLK_DIV;
313	cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
314	cfg->com_vco_tune_ctrl = 0x0;
315
316	cfg->tx_lx_lane_mode[0] =
317		cfg->tx_lx_lane_mode[2] = 0x43;
318
319	cfg->tx_lx_hp_pd_enables[0] =
320		cfg->tx_lx_hp_pd_enables[1] =
321		cfg->tx_lx_hp_pd_enables[2] = 0x0c;
322	cfg->tx_lx_hp_pd_enables[3] = 0x3;
323
324	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
325		cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4;
326
327	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
328		cfg->tx_lx_tx_drv_lvl[0] =
329			cfg->tx_lx_tx_drv_lvl[1] =
330			cfg->tx_lx_tx_drv_lvl[2] = 0x25;
331		cfg->tx_lx_tx_drv_lvl[3] = 0x22;
332
333		cfg->tx_lx_tx_emp_post1_lvl[0] =
334			cfg->tx_lx_tx_emp_post1_lvl[1] =
335			cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23;
336		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27;
337
338		cfg->tx_lx_vmode_ctrl1[0] =
339			cfg->tx_lx_vmode_ctrl1[1] =
340			cfg->tx_lx_vmode_ctrl1[2] =
341			cfg->tx_lx_vmode_ctrl1[3] = 0x00;
342
343		cfg->tx_lx_vmode_ctrl2[0] =
344			cfg->tx_lx_vmode_ctrl2[1] =
345			cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
346
347		cfg->tx_lx_vmode_ctrl2[3] = 0x00;
348	} else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
349		for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
350			cfg->tx_lx_tx_drv_lvl[i] = 0x25;
351			cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23;
352			cfg->tx_lx_vmode_ctrl1[i] = 0x00;
353		}
354
355		cfg->tx_lx_vmode_ctrl2[0] =
356			cfg->tx_lx_vmode_ctrl2[1] =
357			cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
358		cfg->tx_lx_vmode_ctrl2[3] = 0x00;
359	} else {
360		for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
361			cfg->tx_lx_tx_drv_lvl[i] = 0x20;
362			cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20;
363			cfg->tx_lx_vmode_ctrl1[i] = 0x00;
364			cfg->tx_lx_vmode_ctrl2[i] = 0x0E;
365		}
366	}
367
368	DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel);
369	DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel);
370	DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en);
371	DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0);
372	DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0);
373	DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0);
374	DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0);
375	DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0);
376	DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0);
377	DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0);
378	DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0);
379	DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0);
380	DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0);
381	DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0);
382	DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0);
383	DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en);
384	DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div);
385	DBG("phy_mode = 0x%x", cfg->phy_mode);
386
387	DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]);
388	DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]);
389
390	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
391		DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]);
392		DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]);
393		DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i,
394		    cfg->tx_lx_tx_emp_post1_lvl[i]);
395		DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]);
396		DBG("tx_l%d_vmode_ctrl2 = 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]);
397	}
398
399	return 0;
400}
401
402static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
403				      unsigned long parent_rate)
404{
405	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
406	struct hdmi_phy *phy = pll_get_phy(pll);
407	struct hdmi_8996_phy_pll_reg_cfg cfg;
408	int i, ret;
409
410	memset(&cfg, 0x00, sizeof(cfg));
411
412	ret = pll_calculate(rate, parent_rate, &cfg);
413	if (ret) {
414		DRM_ERROR("PLL calculation failed\n");
415		return ret;
416	}
417
418	/* Initially shut down PHY */
419	DBG("Disabling PHY");
420	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0);
421	udelay(500);
422
423	/* Power up sequence */
424	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04);
425
426	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1);
427	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
428	hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F);
429	hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F);
430
431	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
432		hdmi_tx_chan_write(pll, i,
433				   REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE,
434				   0x03);
435		hdmi_tx_chan_write(pll, i,
436				   REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND,
437				   cfg.tx_lx_tx_band[i]);
438		hdmi_tx_chan_write(pll, i,
439				   REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN,
440				   0x03);
441	}
442
443	hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
444			   cfg.tx_lx_lane_mode[0]);
445	hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
446			   cfg.tx_lx_lane_mode[2]);
447
448	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E);
449	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
450	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
451	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
452	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
453
454	/* Bypass VCO calibration */
455	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
456		       cfg.com_svs_mode_clk_sel);
457
458	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F);
459	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F);
460	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL,
461		       cfg.com_vco_tune_ctrl);
462
463	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06);
464
465	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30);
466	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL,
467		       cfg.com_hsclk_sel);
468	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN,
469		       cfg.com_lock_cmp_en);
470
471	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
472		       cfg.com_pll_cctrl_mode0);
473	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
474		       cfg.com_pll_rctrl_mode0);
475	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0,
476		       cfg.com_cp_ctrl_mode0);
477	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0,
478		       cfg.com_dec_start_mode0);
479	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
480		       cfg.com_div_frac_start1_mode0);
481	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
482		       cfg.com_div_frac_start2_mode0);
483	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
484		       cfg.com_div_frac_start3_mode0);
485
486	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
487		       cfg.com_integloop_gain0_mode0);
488	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
489		       cfg.com_integloop_gain1_mode0);
490
491	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
492		       cfg.com_lock_cmp1_mode0);
493	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
494		       cfg.com_lock_cmp2_mode0);
495	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
496		       cfg.com_lock_cmp3_mode0);
497
498	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
499	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN,
500		       cfg.com_core_clk_en);
501	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV,
502		       cfg.com_coreclk_div);
503	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02);
504
505	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15);
506
507	/* TX lanes setup (TX 0/1/2/3) */
508	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
509		hdmi_tx_chan_write(pll, i,
510				   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL,
511				   cfg.tx_lx_tx_drv_lvl[i]);
512		hdmi_tx_chan_write(pll, i,
513				   REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL,
514				   cfg.tx_lx_tx_emp_post1_lvl[i]);
515		hdmi_tx_chan_write(pll, i,
516				   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1,
517				   cfg.tx_lx_vmode_ctrl1[i]);
518		hdmi_tx_chan_write(pll, i,
519				   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2,
520				   cfg.tx_lx_vmode_ctrl2[i]);
521		hdmi_tx_chan_write(pll, i,
522				   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET,
523				   0x00);
524		hdmi_tx_chan_write(pll, i,
525			REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET,
526			0x00);
527		hdmi_tx_chan_write(pll, i,
528			REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN,
529			0x03);
530		hdmi_tx_chan_write(pll, i,
531			REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN,
532			0x40);
533		hdmi_tx_chan_write(pll, i,
534				   REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES,
535				   cfg.tx_lx_hp_pd_enables[i]);
536	}
537
538	hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode);
539	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F);
540
541	/*
542	 * Ensure that vco configuration gets flushed to hardware before
543	 * enabling the PLL
544	 */
545	wmb();
546
547	return 0;
548}
549
550static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy)
551{
552	u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
553	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
554	u32 status;
555	int phy_ready = 0;
556
557	DBG("Waiting for PHY ready");
558
559	while (nb_tries--) {
560		status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS);
561		phy_ready = status & BIT(0);
562
563		if (phy_ready)
564			break;
565
566		udelay(timeout);
567	}
568
569	DBG("PHY is %sready", phy_ready ? "" : "*not* ");
570
571	return phy_ready;
572}
573
574static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll)
575{
576	u32 status;
577	int nb_tries = HDMI_PLL_POLL_MAX_READS;
578	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
579	int pll_locked = 0;
580
581	DBG("Waiting for PLL lock");
582
583	while (nb_tries--) {
584		status = hdmi_pll_read(pll,
585				       REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
586		pll_locked = status & BIT(0);
587
588		if (pll_locked)
589			break;
590
591		udelay(timeout);
592	}
593
594	DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* ");
595
596	return pll_locked;
597}
598
599static int hdmi_8996_pll_prepare(struct clk_hw *hw)
600{
601	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
602	struct hdmi_phy *phy = pll_get_phy(pll);
603	int i, ret = 0;
604
605	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1);
606	udelay(100);
607
608	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
609	udelay(100);
610
611	ret = hdmi_8996_pll_lock_status(pll);
612	if (!ret)
613		return ret;
614
615	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
616		hdmi_tx_chan_write(pll, i,
617			REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
618			0x6F);
619
620	/* Disable SSC */
621	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0);
622	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0);
623	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0);
624	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0);
625	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2);
626
627	ret = hdmi_8996_phy_ready_status(phy);
628	if (!ret)
629		return ret;
630
631	/* Restart the retiming buffer */
632	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18);
633	udelay(1);
634	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
635
636	return 0;
637}
638
639static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
640				     unsigned long rate,
641				     unsigned long *parent_rate)
642{
643	if (rate < HDMI_PCLK_MIN_FREQ)
644		return HDMI_PCLK_MIN_FREQ;
645	else if (rate > HDMI_PCLK_MAX_FREQ)
646		return HDMI_PCLK_MAX_FREQ;
647	else
648		return rate;
649}
650
651static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
652					       unsigned long parent_rate)
653{
654	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
655	u64 fdata;
656	u32 cmp1, cmp2, cmp3, pll_cmp;
657
658	cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0);
659	cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0);
660	cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0);
661
662	pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16);
663
664	fdata = pll_cmp_to_fdata(pll_cmp + 1, parent_rate);
665
666	do_div(fdata, 10);
667
668	return fdata;
669}
670
671static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
672{
673}
674
675static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
676{
677	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
678	u32 status;
679	int pll_locked;
680
681	status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
682	pll_locked = status & BIT(0);
683
684	return pll_locked;
685}
686
687static struct clk_ops hdmi_8996_pll_ops = {
688	.set_rate = hdmi_8996_pll_set_clk_rate,
689	.round_rate = hdmi_8996_pll_round_rate,
690	.recalc_rate = hdmi_8996_pll_recalc_rate,
691	.prepare = hdmi_8996_pll_prepare,
692	.unprepare = hdmi_8996_pll_unprepare,
693	.is_enabled = hdmi_8996_pll_is_enabled,
694};
695
696static const char * const hdmi_pll_parents[] = {
697	"xo",
698};
699
700static struct clk_init_data pll_init = {
701	.name = "hdmipll",
702	.ops = &hdmi_8996_pll_ops,
703	.parent_names = hdmi_pll_parents,
704	.num_parents = ARRAY_SIZE(hdmi_pll_parents),
705	.flags = CLK_IGNORE_UNUSED,
706};
707
708int msm_hdmi_pll_8996_init(struct platform_device *pdev)
709{
710	struct device *dev = &pdev->dev;
711	struct hdmi_pll_8996 *pll;
712	struct clk *clk;
713	int i;
714
715	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
716	if (!pll)
717		return -ENOMEM;
718
719	pll->pdev = pdev;
720
721	pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
722	if (IS_ERR(pll->mmio_qserdes_com)) {
723		dev_err(dev, "failed to map pll base\n");
724		return -ENOMEM;
725	}
726
727	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
728		char name[32], label[32];
729
730		snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
731		snprintf(label, sizeof(label), "HDMI_TX_L%d", i);
732
733		pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name, label);
734		if (IS_ERR(pll->mmio_qserdes_tx[i])) {
735			dev_err(dev, "failed to map pll base\n");
736			return -ENOMEM;
737		}
738	}
739	pll->clk_hw.init = &pll_init;
740
741	clk = devm_clk_register(dev, &pll->clk_hw);
742	if (IS_ERR(clk)) {
743		dev_err(dev, "failed to register pll clock\n");
744		return -EINVAL;
745	}
746
747	return 0;
748}
749
750static const char * const hdmi_phy_8996_reg_names[] = {
751	"vddio",
752	"vcca",
753};
754
755static const char * const hdmi_phy_8996_clk_names[] = {
756	"mmagic_iface_clk",
757	"iface_clk",
758	"ref_clk",
759};
760
761const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
762	.type = MSM_HDMI_PHY_8996,
763	.reg_names = hdmi_phy_8996_reg_names,
764	.num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
765	.clk_names = hdmi_phy_8996_clk_names,
766	.num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
767};