brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · 83c8781 Raw
459 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.4 * Copyright (C) 2013 Red Hat5 * Author: Rob Clark <robdclark@gmail.com>6 */7 8#include <linux/clk-provider.h>9#include <linux/delay.h>10 11#include "hdmi.h"12 13struct 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 pll27 * configuration into common-clock-framework.28 */29 30struct 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: */40static 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 237static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data)238{239	writel(data, pll->mmio + reg);240}241 242static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg)243{244	return readl(pll->mmio + reg);245}246 247static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll)248{249	return platform_get_drvdata(pll->pdev);250}251 252static 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-asserting267	 * to allow the hardware to complete its job.268	 * This much of delay should be fine for hardware269	 * 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 to283	 * complete its job. This much of delay should be fine for hardware to284	 * 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 again319		 * Assert PLL S/W reset first320		 */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 calibration327		 * before checking if the PLL gets locked328		 */329		udelay(350);330 331		timeout_count = 1000;332	}333 334	return 0;335}336 337static 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 357static 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 368static 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 376static 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 384static 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 401static 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 409static const struct clk_parent_data hdmi_pll_parents[] = {410	{ .fw_name = "pxo", .name = "pxo_board" },411};412 413static 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 421int 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}459