| .. | .. | 
|---|
| 153 | 153 |  | 
|---|
| 154 | 154 | enum inno_hdmi_phy_type { | 
|---|
| 155 | 155 | INNO_HDMI_PHY_RK3228, | 
|---|
| 156 |  | -	INNO_HDMI_PHY_RK3328 | 
|---|
|  | 156 | +	INNO_HDMI_PHY_RK3328, | 
|---|
|  | 157 | +	INNO_HDMI_PHY_RK3528 | 
|---|
| 157 | 158 | }; | 
|---|
| 158 | 159 |  | 
|---|
| 159 | 160 | struct phy_config { | 
|---|
| .. | .. | 
|---|
| 287 | 288 | {33750000,  1, 10, 2, 4}, | 
|---|
| 288 | 289 | {74250000,  1, 40, 8, 1}, | 
|---|
| 289 | 290 | {74250000, 18, 80, 8, 2}, | 
|---|
|  | 291 | +	{74250000,  1, 20, 4, 8}, | 
|---|
| 290 | 292 | {148500000, 2, 40, 4, 3}, | 
|---|
|  | 293 | +	{148500000, 1, 10, 2, 8}, | 
|---|
| 291 | 294 | {297000000, 4, 40, 2, 3}, | 
|---|
|  | 295 | +	{297000000, 2, 20, 2, 8}, | 
|---|
| 292 | 296 | {594000000, 8, 40, 1, 3}, | 
|---|
|  | 297 | +	{594000000, 4, 20, 1, 8}, | 
|---|
| 293 | 298 | {     ~0UL, 0,  0, 0, 0} | 
|---|
| 294 | 299 | }; | 
|---|
| 295 | 300 |  | 
|---|
| .. | .. | 
|---|
| 330 | 335 | 594000000, { | 
|---|
| 331 | 336 | 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08, | 
|---|
| 332 | 337 | 0x00, 0xac, 0xcc, 0xcc, 0xcc, | 
|---|
|  | 338 | +		}, | 
|---|
|  | 339 | +	}, { | 
|---|
|  | 340 | +		~0UL, { | 
|---|
|  | 341 | +			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 342 | +			0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 343 | +		}, | 
|---|
|  | 344 | +	} | 
|---|
|  | 345 | +}; | 
|---|
|  | 346 | + | 
|---|
|  | 347 | +static const struct phy_config rk3528_phy_cfg[] = { | 
|---|
|  | 348 | +	/* tmdsclk bias-clk bias-data voltage-clk voltage-data pre-emphasis-data */ | 
|---|
|  | 349 | +	{	165000000, { | 
|---|
|  | 350 | +			0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 351 | +			0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 352 | +		}, | 
|---|
|  | 353 | +	}, { | 
|---|
|  | 354 | +		340000000, { | 
|---|
|  | 355 | +			0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 356 | +			0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 357 | +		}, | 
|---|
|  | 358 | +	}, { | 
|---|
|  | 359 | +		594000000, { | 
|---|
|  | 360 | +			0x02, 0x08, 0x0d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
|  | 361 | +			0x00, 0x00, 0x00, 0x00, 0x00, | 
|---|
| 333 | 362 | }, | 
|---|
| 334 | 363 | }, { | 
|---|
| 335 | 364 | ~0UL, { | 
|---|
| .. | .. | 
|---|
| 462 | 491 | else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 && | 
|---|
| 463 | 492 | tmdsclock <= 33750000 && inno->efuse_flag) | 
|---|
| 464 | 493 | chipversion = 4; | 
|---|
|  | 494 | +	else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3528) | 
|---|
|  | 495 | +		chipversion = 8; | 
|---|
| 465 | 496 |  | 
|---|
| 466 | 497 | for (; cfg->tmdsclock != ~0UL; cfg++) | 
|---|
| 467 | 498 | if (tmdsclock <= cfg->tmdsclock && | 
|---|
| .. | .. | 
|---|
| 631 | 662 | { | 
|---|
| 632 | 663 | struct device *dev = inno->dev; | 
|---|
| 633 | 664 | struct device_node *np = dev->of_node; | 
|---|
|  | 665 | +	struct device_node *clk_np = NULL; | 
|---|
| 634 | 666 | struct clk_init_data init = {}; | 
|---|
| 635 | 667 | struct clk *refclk; | 
|---|
| 636 | 668 | const char *parent_name; | 
|---|
| 637 | 669 | int ret; | 
|---|
|  | 670 | + | 
|---|
|  | 671 | +	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3528) | 
|---|
|  | 672 | +		clk_np = of_get_child_by_name(np, "clk-port"); | 
|---|
|  | 673 | + | 
|---|
|  | 674 | +	if (!clk_np) | 
|---|
|  | 675 | +		clk_np = np; | 
|---|
| 638 | 676 |  | 
|---|
| 639 | 677 | refclk = devm_clk_get(dev, "refclk"); | 
|---|
| 640 | 678 | if (IS_ERR(refclk)) { | 
|---|
| .. | .. | 
|---|
| 651 | 689 | init.ops = &inno_hdmi_phy_clk_ops; | 
|---|
| 652 | 690 |  | 
|---|
| 653 | 691 | /* optional override of the clock name */ | 
|---|
| 654 |  | -	of_property_read_string(np, "clock-output-names", &init.name); | 
|---|
|  | 692 | +	of_property_read_string(clk_np, "clock-output-names", &init.name); | 
|---|
| 655 | 693 |  | 
|---|
| 656 | 694 | inno->hw.init = &init; | 
|---|
| 657 | 695 |  | 
|---|
| .. | .. | 
|---|
| 662 | 700 | return ret; | 
|---|
| 663 | 701 | } | 
|---|
| 664 | 702 |  | 
|---|
| 665 |  | -	ret = of_clk_add_provider(np, of_clk_src_simple_get, inno->pclk); | 
|---|
|  | 703 | +	ret = of_clk_add_provider(clk_np, of_clk_src_simple_get, inno->pclk); | 
|---|
| 666 | 704 | if (ret) { | 
|---|
| 667 | 705 | dev_err(dev, "failed to register OF clock provider: %d\n", ret); | 
|---|
| 668 | 706 | return ret; | 
|---|
| .. | .. | 
|---|
| 1078 | 1116 | return frac; | 
|---|
| 1079 | 1117 | } | 
|---|
| 1080 | 1118 |  | 
|---|
|  | 1119 | +static int | 
|---|
|  | 1120 | +inno_hdmi_phy_rk3528_power_on(struct inno_hdmi_phy *inno, | 
|---|
|  | 1121 | +			      const struct post_pll_config *cfg, | 
|---|
|  | 1122 | +			      const struct phy_config *phy_cfg) | 
|---|
|  | 1123 | +{ | 
|---|
|  | 1124 | +	u32 val; | 
|---|
|  | 1125 | +	u64 temp; | 
|---|
|  | 1126 | + | 
|---|
|  | 1127 | +	/* Power off post PLL */ | 
|---|
|  | 1128 | +	inno_update_bits(inno, 0xaa, 1, 0); | 
|---|
|  | 1129 | + | 
|---|
|  | 1130 | +	val = cfg->prediv; | 
|---|
|  | 1131 | +	inno_write(inno, 0xab, val); | 
|---|
|  | 1132 | + | 
|---|
|  | 1133 | +	if (cfg->postdiv == 1) { | 
|---|
|  | 1134 | +		inno_write(inno, 0xad, 0x8); | 
|---|
|  | 1135 | +		inno_write(inno, 0xaa, 2); | 
|---|
|  | 1136 | +	} else { | 
|---|
|  | 1137 | +		val = (cfg->postdiv / 2) - 1; | 
|---|
|  | 1138 | +		inno_write(inno, 0xad, val); | 
|---|
|  | 1139 | +		inno_write(inno, 0xaa, 0x0e); | 
|---|
|  | 1140 | +	} | 
|---|
|  | 1141 | + | 
|---|
|  | 1142 | +	val = cfg->fbdiv & 0xff; | 
|---|
|  | 1143 | +	inno_write(inno, 0xac, val); | 
|---|
|  | 1144 | +	val = (cfg->fbdiv >> 8) & BIT(0); | 
|---|
|  | 1145 | +	inno_update_bits(inno, 0xad, BIT(4), val); | 
|---|
|  | 1146 | + | 
|---|
|  | 1147 | +	/* current bias clk/data 2 */ | 
|---|
|  | 1148 | +	val = phy_cfg->regs[0] << 4 | phy_cfg->regs[1]; | 
|---|
|  | 1149 | +	inno_write(inno, 0xbf, val); | 
|---|
|  | 1150 | + | 
|---|
|  | 1151 | +	/* current bias data 1/0 */ | 
|---|
|  | 1152 | +	val = phy_cfg->regs[1] << 4 | phy_cfg->regs[1]; | 
|---|
|  | 1153 | +	inno_write(inno, 0xc0, val); | 
|---|
|  | 1154 | + | 
|---|
|  | 1155 | +	/* output voltage */ | 
|---|
|  | 1156 | +	inno_write(inno, 0xb5, phy_cfg->regs[2]); | 
|---|
|  | 1157 | +	inno_write(inno, 0xb6, phy_cfg->regs[3]); | 
|---|
|  | 1158 | +	inno_write(inno, 0xb7, phy_cfg->regs[3]); | 
|---|
|  | 1159 | +	inno_write(inno, 0xb8, phy_cfg->regs[3]); | 
|---|
|  | 1160 | + | 
|---|
|  | 1161 | +	/* pre-emphasis */ | 
|---|
|  | 1162 | +	inno_write(inno, 0xbb, phy_cfg->regs[4]); | 
|---|
|  | 1163 | +	inno_write(inno, 0xbc, phy_cfg->regs[4]); | 
|---|
|  | 1164 | +	inno_write(inno, 0xbd, phy_cfg->regs[4]); | 
|---|
|  | 1165 | + | 
|---|
|  | 1166 | +	/* enable LDO */ | 
|---|
|  | 1167 | +	inno_write(inno, 0xb4, 0x7); | 
|---|
|  | 1168 | + | 
|---|
|  | 1169 | +	/* enable serializer */ | 
|---|
|  | 1170 | +	inno_write(inno, 0xbe, 0x70); | 
|---|
|  | 1171 | + | 
|---|
|  | 1172 | +	inno_write(inno, 0xb2, 0x0f); | 
|---|
|  | 1173 | + | 
|---|
|  | 1174 | +	for (val = 0; val < 5; val++) { | 
|---|
|  | 1175 | +		if (inno_read(inno, 0xaf) & 1) | 
|---|
|  | 1176 | +			break; | 
|---|
|  | 1177 | +		udelay(1000); | 
|---|
|  | 1178 | +	} | 
|---|
|  | 1179 | +	if (!(inno_read(inno, 0xaf) & 1)) { | 
|---|
|  | 1180 | +		dev_err(inno->dev, "HDMI PHY Post PLL unlock\n"); | 
|---|
|  | 1181 | +		return -ETIMEDOUT; | 
|---|
|  | 1182 | +	} | 
|---|
|  | 1183 | + | 
|---|
|  | 1184 | +	/* set termination resistance */ | 
|---|
|  | 1185 | +	if (phy_cfg->tmdsclock > 340000000) { | 
|---|
|  | 1186 | +		inno_write(inno, 0xc7, 0x76); | 
|---|
|  | 1187 | +		inno_write(inno, 0xc5, 0x83); | 
|---|
|  | 1188 | +		inno_write(inno, 0xc8, 0x00); | 
|---|
|  | 1189 | +		inno_write(inno, 0xc9, 0x2f); | 
|---|
|  | 1190 | +		inno_write(inno, 0xca, 0x2f); | 
|---|
|  | 1191 | +		inno_write(inno, 0xcb, 0x2f); | 
|---|
|  | 1192 | +	} else { | 
|---|
|  | 1193 | +		inno_write(inno, 0xc7, 0x76); | 
|---|
|  | 1194 | +		inno_write(inno, 0xc5, 0x83); | 
|---|
|  | 1195 | +		inno_write(inno, 0xc8, 0x00); | 
|---|
|  | 1196 | +		inno_write(inno, 0xc9, 0x0f); | 
|---|
|  | 1197 | +		inno_write(inno, 0xca, 0x0f); | 
|---|
|  | 1198 | +		inno_write(inno, 0xcb, 0x0f); | 
|---|
|  | 1199 | +	} | 
|---|
|  | 1200 | + | 
|---|
|  | 1201 | +	/* set TMDS sync detection counter length */ | 
|---|
|  | 1202 | +	temp = 47520000000; | 
|---|
|  | 1203 | +	do_div(temp, inno->tmdsclock); | 
|---|
|  | 1204 | +	inno_write(inno, 0xd8, (temp >> 8) & 0xff); | 
|---|
|  | 1205 | +	inno_write(inno, 0xd9, temp & 0xff); | 
|---|
|  | 1206 | + | 
|---|
|  | 1207 | +	/* Power up post PLL */ | 
|---|
|  | 1208 | +	inno_update_bits(inno, 0xaa, 1, 0); | 
|---|
|  | 1209 | +	/* Power up tmds driver */ | 
|---|
|  | 1210 | +	inno_update_bits(inno, 0xb0, 4, 4); | 
|---|
|  | 1211 | +	inno_write(inno, 0xb2, 0x0f); | 
|---|
|  | 1212 | + | 
|---|
|  | 1213 | +	if (phy_cfg->tmdsclock > 340000000) | 
|---|
|  | 1214 | +		msleep(100); | 
|---|
|  | 1215 | +	/* set pdata_en to 0/1 */ | 
|---|
|  | 1216 | +	inno_update_bits(inno, 0x02, 1, 0); | 
|---|
|  | 1217 | +	inno_update_bits(inno, 0x02, 1, 1); | 
|---|
|  | 1218 | + | 
|---|
|  | 1219 | +	/* Enable PHY IRQ */ | 
|---|
|  | 1220 | +	inno_write(inno, 0x05, 0x22); | 
|---|
|  | 1221 | +	inno_write(inno, 0x07, 0x22); | 
|---|
|  | 1222 | +	inno_write(inno, 0xcc, 0x0f); | 
|---|
|  | 1223 | + | 
|---|
|  | 1224 | +	return 0; | 
|---|
|  | 1225 | +} | 
|---|
|  | 1226 | + | 
|---|
|  | 1227 | +static void inno_hdmi_phy_rk3528_power_off(struct inno_hdmi_phy *inno) | 
|---|
|  | 1228 | +{ | 
|---|
|  | 1229 | +	/* Power off driver */ | 
|---|
|  | 1230 | +	inno_write(inno, 0xb2, 0); | 
|---|
|  | 1231 | +	/* Power off serializer */ | 
|---|
|  | 1232 | +	inno_write(inno, 0xbe, 0); | 
|---|
|  | 1233 | +	/* Power off post pll */ | 
|---|
|  | 1234 | +	inno_update_bits(inno, 0xaa, 1, 1); | 
|---|
|  | 1235 | +	/* Power off rxsense detection circuit */ | 
|---|
|  | 1236 | +	inno_write(inno, 0xcc, 0); | 
|---|
|  | 1237 | +	/* Power off band gap */ | 
|---|
|  | 1238 | +	inno_update_bits(inno, 0xb0, 4, 0); | 
|---|
|  | 1239 | +	/* Disable PHY IRQ */ | 
|---|
|  | 1240 | +	inno_write(inno, 0x05, 0); | 
|---|
|  | 1241 | +	inno_write(inno, 0x07, 0); | 
|---|
|  | 1242 | +} | 
|---|
|  | 1243 | + | 
|---|
|  | 1244 | +static void inno_hdmi_phy_rk3528_init(struct inno_hdmi_phy *inno) | 
|---|
|  | 1245 | +{ | 
|---|
|  | 1246 | +	/* | 
|---|
|  | 1247 | +	 * Use phy internal register control | 
|---|
|  | 1248 | +	 * rxsense/poweron/pllpd/pdataen signal. | 
|---|
|  | 1249 | +	 */ | 
|---|
|  | 1250 | +	inno_write(inno, 0x02, 0x81); | 
|---|
|  | 1251 | + | 
|---|
|  | 1252 | +	/* if phy had been set in uboot, pll is locked */ | 
|---|
|  | 1253 | +	if (inno_read(inno, 0xa9) & BIT(0)) { | 
|---|
|  | 1254 | +		dev_info(inno->dev, "phy had been powered up\n"); | 
|---|
|  | 1255 | +		inno->phy->power_count = 1; | 
|---|
|  | 1256 | +	} else { | 
|---|
|  | 1257 | +		/* manual power down post-PLL */ | 
|---|
|  | 1258 | +		inno_hdmi_phy_rk3528_power_off(inno); | 
|---|
|  | 1259 | +	} | 
|---|
|  | 1260 | +} | 
|---|
|  | 1261 | + | 
|---|
|  | 1262 | +static int | 
|---|
|  | 1263 | +inno_hdmi_phy_rk3528_pre_pll_update(struct inno_hdmi_phy *inno, | 
|---|
|  | 1264 | +				    const struct pre_pll_config *cfg) | 
|---|
|  | 1265 | +{ | 
|---|
|  | 1266 | +	u32 val; | 
|---|
|  | 1267 | + | 
|---|
|  | 1268 | +	inno_update_bits(inno, 0xb0, 4, 4); | 
|---|
|  | 1269 | +	inno_write(inno, 0xcc, 0x0f); | 
|---|
|  | 1270 | + | 
|---|
|  | 1271 | +	/* Power on PLL */ | 
|---|
|  | 1272 | +	inno_update_bits(inno, 0xa0, 1, 0); | 
|---|
|  | 1273 | +	/* Configure pre-pll */ | 
|---|
|  | 1274 | +	inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1); | 
|---|
|  | 1275 | +	inno_write(inno, 0xa1, cfg->prediv); | 
|---|
|  | 1276 | +	if (cfg->fracdiv) | 
|---|
|  | 1277 | +		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0; | 
|---|
|  | 1278 | +	else | 
|---|
|  | 1279 | +		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0; | 
|---|
|  | 1280 | +	inno_write(inno, 0xa2, val); | 
|---|
|  | 1281 | +	inno_write(inno, 0xa3, cfg->fbdiv & 0xff); | 
|---|
|  | 1282 | +	val = (cfg->pclk_div_a & 0x1f) | | 
|---|
|  | 1283 | +	      ((cfg->pclk_div_b & 3) << 5); | 
|---|
|  | 1284 | +	inno_write(inno, 0xa5, val); | 
|---|
|  | 1285 | +	val = (cfg->pclk_div_d & 0x1f) | | 
|---|
|  | 1286 | +	      ((cfg->pclk_div_c & 3) << 5); | 
|---|
|  | 1287 | +	inno_write(inno, 0xa6, val); | 
|---|
|  | 1288 | +	val = ((cfg->tmds_div_a & 3) << 4) | | 
|---|
|  | 1289 | +	      ((cfg->tmds_div_b & 3) << 2) | | 
|---|
|  | 1290 | +	      (cfg->tmds_div_c & 3); | 
|---|
|  | 1291 | +	inno_write(inno, 0xa4, val); | 
|---|
|  | 1292 | + | 
|---|
|  | 1293 | +	if (cfg->fracdiv) { | 
|---|
|  | 1294 | +		val = cfg->fracdiv & 0xff; | 
|---|
|  | 1295 | +		inno_write(inno, 0xd3, val); | 
|---|
|  | 1296 | +		val = (cfg->fracdiv >> 8) & 0xff; | 
|---|
|  | 1297 | +		inno_write(inno, 0xd2, val); | 
|---|
|  | 1298 | +		val = (cfg->fracdiv >> 16) & 0xff; | 
|---|
|  | 1299 | +		inno_write(inno, 0xd1, val); | 
|---|
|  | 1300 | +	} else { | 
|---|
|  | 1301 | +		inno_write(inno, 0xd3, 0); | 
|---|
|  | 1302 | +		inno_write(inno, 0xd2, 0); | 
|---|
|  | 1303 | +		inno_write(inno, 0xd1, 0); | 
|---|
|  | 1304 | +	} | 
|---|
|  | 1305 | + | 
|---|
|  | 1306 | +	/* Wait for PLL lock */ | 
|---|
|  | 1307 | +	for (val = 0; val < 5; val++) { | 
|---|
|  | 1308 | +		if (inno_read(inno, 0xa9) & 1) | 
|---|
|  | 1309 | +			break; | 
|---|
|  | 1310 | +		usleep_range(1000, 2000); | 
|---|
|  | 1311 | +	} | 
|---|
|  | 1312 | +	if (val == 5) { | 
|---|
|  | 1313 | +		dev_err(inno->dev, "Pre-PLL unlock\n"); | 
|---|
|  | 1314 | +		return -ETIMEDOUT; | 
|---|
|  | 1315 | +	} | 
|---|
|  | 1316 | + | 
|---|
|  | 1317 | +	return 0; | 
|---|
|  | 1318 | +} | 
|---|
|  | 1319 | + | 
|---|
|  | 1320 | +static unsigned long | 
|---|
|  | 1321 | +inno_hdmi_rk3528_phy_pll_recalc_rate(struct inno_hdmi_phy *inno, | 
|---|
|  | 1322 | +				     unsigned long parent_rate) | 
|---|
|  | 1323 | +{ | 
|---|
|  | 1324 | +	unsigned long frac; | 
|---|
|  | 1325 | +	u8 nd, no_a, no_b, no_d; | 
|---|
|  | 1326 | +	u16 nf; | 
|---|
|  | 1327 | +	u64 vco = parent_rate; | 
|---|
|  | 1328 | + | 
|---|
|  | 1329 | +	nd = inno_read(inno, 0xa1) & 0x3f; | 
|---|
|  | 1330 | +	nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3); | 
|---|
|  | 1331 | +	vco *= nf; | 
|---|
|  | 1332 | +	if ((inno_read(inno, 0xa2) & 0x30) == 0) { | 
|---|
|  | 1333 | +		frac = inno_read(inno, 0xd3) | | 
|---|
|  | 1334 | +		       (inno_read(inno, 0xd2) << 8) | | 
|---|
|  | 1335 | +		       (inno_read(inno, 0xd1) << 16); | 
|---|
|  | 1336 | +		vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24)); | 
|---|
|  | 1337 | +	} | 
|---|
|  | 1338 | +	if (inno_read(inno, 0xa0) & 2) { | 
|---|
|  | 1339 | +		do_div(vco, nd * 5); | 
|---|
|  | 1340 | +	} else { | 
|---|
|  | 1341 | +		no_a = inno_read(inno, 0xa5) & 0x1f; | 
|---|
|  | 1342 | +		no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2; | 
|---|
|  | 1343 | +		no_d = inno_read(inno, 0xa6) & 0x1f; | 
|---|
|  | 1344 | +		if (no_a == 1) | 
|---|
|  | 1345 | +			do_div(vco, nd * no_b * no_d * 2); | 
|---|
|  | 1346 | +		else | 
|---|
|  | 1347 | +			do_div(vco, nd * no_a * no_d * 2); | 
|---|
|  | 1348 | +	} | 
|---|
|  | 1349 | + | 
|---|
|  | 1350 | +	frac = vco; | 
|---|
|  | 1351 | +	inno->pixclock = DIV_ROUND_CLOSEST(frac, 1000) * 1000; | 
|---|
|  | 1352 | + | 
|---|
|  | 1353 | +	dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock); | 
|---|
|  | 1354 | + | 
|---|
|  | 1355 | +	return frac; | 
|---|
|  | 1356 | +} | 
|---|
|  | 1357 | + | 
|---|
| 1081 | 1358 | static unsigned long | 
|---|
| 1082 | 1359 | inno_hdmi_rk3228_phy_pll_recalc_rate(struct inno_hdmi_phy *inno, | 
|---|
| 1083 | 1360 | unsigned long parent_rate) | 
|---|
| .. | .. | 
|---|
| 1128 | 1405 | .recalc_rate = inno_hdmi_rk3328_phy_pll_recalc_rate, | 
|---|
| 1129 | 1406 | }; | 
|---|
| 1130 | 1407 |  | 
|---|
|  | 1408 | +static const struct inno_hdmi_phy_ops rk3528_hdmi_phy_ops = { | 
|---|
|  | 1409 | +	.init = inno_hdmi_phy_rk3528_init, | 
|---|
|  | 1410 | +	.power_on = inno_hdmi_phy_rk3528_power_on, | 
|---|
|  | 1411 | +	.power_off = inno_hdmi_phy_rk3528_power_off, | 
|---|
|  | 1412 | +	.pre_pll_update = inno_hdmi_phy_rk3528_pre_pll_update, | 
|---|
|  | 1413 | +	.recalc_rate = inno_hdmi_rk3528_phy_pll_recalc_rate, | 
|---|
|  | 1414 | +}; | 
|---|
|  | 1415 | + | 
|---|
| 1131 | 1416 | static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = { | 
|---|
| 1132 | 1417 | .dev_type = INNO_HDMI_PHY_RK3228, | 
|---|
| 1133 | 1418 | .ops = &rk3228_hdmi_phy_ops, | 
|---|
| .. | .. | 
|---|
| 1140 | 1425 | .phy_cfg_table = rk3328_phy_cfg, | 
|---|
| 1141 | 1426 | }; | 
|---|
| 1142 | 1427 |  | 
|---|
|  | 1428 | +static const struct inno_hdmi_phy_drv_data rk3528_hdmi_phy_drv_data = { | 
|---|
|  | 1429 | +	.dev_type = INNO_HDMI_PHY_RK3528, | 
|---|
|  | 1430 | +	.ops = &rk3528_hdmi_phy_ops, | 
|---|
|  | 1431 | +	.phy_cfg_table = rk3528_phy_cfg, | 
|---|
|  | 1432 | +}; | 
|---|
|  | 1433 | + | 
|---|
| 1143 | 1434 | static const struct of_device_id inno_hdmi_phy_of_match[] = { | 
|---|
| 1144 | 1435 | { .compatible = "rockchip,rk3228-hdmi-phy", | 
|---|
| 1145 | 1436 | .data = &rk3228_hdmi_phy_drv_data | 
|---|
| 1146 | 1437 | }, | 
|---|
| 1147 | 1438 | { .compatible = "rockchip,rk3328-hdmi-phy", | 
|---|
| 1148 | 1439 | .data = &rk3328_hdmi_phy_drv_data | 
|---|
|  | 1440 | +	}, | 
|---|
|  | 1441 | +	{ .compatible = "rockchip,rk3528-hdmi-phy", | 
|---|
|  | 1442 | +	  .data = &rk3528_hdmi_phy_drv_data | 
|---|
| 1149 | 1443 | }, | 
|---|
| 1150 | 1444 | {} | 
|---|
| 1151 | 1445 | }; | 
|---|
| .. | .. | 
|---|
| 1244 | 1538 | if (of_get_property(np, "rockchip,phy-table", &val)) { | 
|---|
| 1245 | 1539 | if (val % PHY_TAB_LEN || !val) { | 
|---|
| 1246 | 1540 | dev_err(dev, "Invalid phy cfg table format!\n"); | 
|---|
| 1247 |  | -			return -EINVAL; | 
|---|
|  | 1541 | +			ret = -EINVAL; | 
|---|
|  | 1542 | +			goto err_regsmap; | 
|---|
| 1248 | 1543 | } | 
|---|
| 1249 | 1544 |  | 
|---|
| 1250 | 1545 | phy_config = kmalloc(val, GFP_KERNEL); | 
|---|
| 1251 | 1546 | if (!phy_config) { | 
|---|
| 1252 | 1547 | dev_err(dev, "kmalloc phy table failed\n"); | 
|---|
| 1253 |  | -			return -ENOMEM; | 
|---|
|  | 1548 | +			ret = -ENOMEM; | 
|---|
|  | 1549 | +			goto err_regsmap; | 
|---|
| 1254 | 1550 | } | 
|---|
| 1255 | 1551 |  | 
|---|
| 1256 | 1552 | phy_table_size = val / PHY_TAB_LEN; | 
|---|
| .. | .. | 
|---|
| 1259 | 1555 | GFP_KERNEL); | 
|---|
| 1260 | 1556 | if (!inno->phy_cfg) { | 
|---|
| 1261 | 1557 | kfree(phy_config); | 
|---|
| 1262 |  | -			return -ENOMEM; | 
|---|
|  | 1558 | +			ret = -ENOMEM; | 
|---|
|  | 1559 | +			goto err_regsmap; | 
|---|
| 1263 | 1560 | } | 
|---|
| 1264 | 1561 | of_property_read_u32_array(np, "rockchip,phy-table", | 
|---|
| 1265 | 1562 | phy_config, val / sizeof(u32)); | 
|---|
| .. | .. | 
|---|
| 1268 | 1565 | phy_table_size); | 
|---|
| 1269 | 1566 | if (ret) { | 
|---|
| 1270 | 1567 | kfree(phy_config); | 
|---|
| 1271 |  | -			return ret; | 
|---|
|  | 1568 | +			goto err_regsmap; | 
|---|
| 1272 | 1569 | } | 
|---|
| 1273 | 1570 | kfree(phy_config); | 
|---|
| 1274 | 1571 | } else { | 
|---|