1c2539483SSimon Glass /*
2*147fd3acSPhilipp Tomsich  * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
3c2539483SSimon Glass  * Copyright (c) 2015 Google, Inc
4c2539483SSimon Glass  * Copyright 2014 Rockchip Inc.
5c2539483SSimon Glass  *
6c2539483SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
7c2539483SSimon Glass  */
8c2539483SSimon Glass 
9c2539483SSimon Glass #include <common.h>
10c2539483SSimon Glass #include <clk.h>
11c2539483SSimon Glass #include <display.h>
12c2539483SSimon Glass #include <dm.h>
13cc232a9dSJernej Skrabec #include <dw_hdmi.h>
14c2539483SSimon Glass #include <edid.h>
15c2539483SSimon Glass #include <regmap.h>
16c2539483SSimon Glass #include <syscon.h>
17c2539483SSimon Glass #include <asm/gpio.h>
1812085239SPhilipp Tomsich #include <asm/hardware.h>
19c2539483SSimon Glass #include <asm/io.h>
20c2539483SSimon Glass #include <asm/arch/clock.h>
21*147fd3acSPhilipp Tomsich #include <asm/arch/hardware.h>
22*147fd3acSPhilipp Tomsich #include "rk_hdmi.h"
23*147fd3acSPhilipp Tomsich #include "rk_vop.h" /* for rk_vop_probe_regulators */
24c2539483SSimon Glass 
25c2539483SSimon Glass static const struct hdmi_phy_config rockchip_phy_config[] = {
26c2539483SSimon Glass 	{
270fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 74250000,
28c2539483SSimon Glass 		.sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
29c2539483SSimon Glass 	}, {
300fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 148500000,
31c2539483SSimon Glass 		.sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
32c2539483SSimon Glass 	}, {
330fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 297000000,
34c2539483SSimon Glass 		.sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d,
35c2539483SSimon Glass 	}, {
36f210e557SPhilipp Tomsich 		.mpixelclock = 584000000,
37f210e557SPhilipp Tomsich 		.sym_ctr = 0x8039, .term = 0x0000, .vlev_ctr = 0x019d,
38f210e557SPhilipp Tomsich 	}, {
39c2539483SSimon Glass 		.mpixelclock = ~0ul,
40c2539483SSimon Glass 		.sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000,
41c2539483SSimon Glass 	}
42c2539483SSimon Glass };
43c2539483SSimon Glass 
44c2539483SSimon Glass static const struct hdmi_mpll_config rockchip_mpll_cfg[] = {
45c2539483SSimon Glass 	{
460fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 40000000,
47c2539483SSimon Glass 		.cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
48c2539483SSimon Glass 	}, {
490fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 65000000,
50c2539483SSimon Glass 		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
51c2539483SSimon Glass 	}, {
520fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 66000000,
53c2539483SSimon Glass 		.cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
54c2539483SSimon Glass 	}, {
5594412745SNickey Yang Nickey Yang 		.mpixelclock = 83500000,
56c2539483SSimon Glass 		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
57c2539483SSimon Glass 	}, {
580fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 146250000,
59c2539483SSimon Glass 		.cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
60c2539483SSimon Glass 	}, {
610fc41e55SNickey Yang Nickey Yang 		.mpixelclock = 148500000,
62c2539483SSimon Glass 		.cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
63c2539483SSimon Glass 	}, {
64f210e557SPhilipp Tomsich 		.mpixelclock = 272000000,
65f210e557SPhilipp Tomsich 		.cpce = 0x0040, .gmp = 0x0003, .curr = 0x0000,
66f210e557SPhilipp Tomsich 	}, {
67f210e557SPhilipp Tomsich 		.mpixelclock = 340000000,
68f210e557SPhilipp Tomsich 		.cpce = 0x0040, .gmp = 0x0003, .curr = 0x0000,
69f210e557SPhilipp Tomsich 	}, {
70c2539483SSimon Glass 		.mpixelclock = ~0ul,
71c2539483SSimon Glass 		.cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
72c2539483SSimon Glass 	}
73c2539483SSimon Glass };
74c2539483SSimon Glass 
75*147fd3acSPhilipp Tomsich int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size)
76c2539483SSimon Glass {
77c2539483SSimon Glass 	struct rk_hdmi_priv *priv = dev_get_priv(dev);
78c2539483SSimon Glass 
79cc232a9dSJernej Skrabec 	return dw_hdmi_read_edid(&priv->hdmi, buf, buf_size);
80c2539483SSimon Glass }
81c2539483SSimon Glass 
82*147fd3acSPhilipp Tomsich int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
83c2539483SSimon Glass {
84c2539483SSimon Glass 	struct rk_hdmi_priv *priv = dev_get_priv(dev);
85cc232a9dSJernej Skrabec 	struct dw_hdmi *hdmi = &priv->hdmi;
86c2539483SSimon Glass 
87a821c4afSSimon Glass 	hdmi->ioaddr = (ulong)devfdt_get_addr(dev);
88cc232a9dSJernej Skrabec 	hdmi->mpll_cfg = rockchip_mpll_cfg;
89cc232a9dSJernej Skrabec 	hdmi->phy_cfg = rockchip_phy_config;
90cc232a9dSJernej Skrabec 
91*147fd3acSPhilipp Tomsich 	/* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
92*147fd3acSPhilipp Tomsich 
93cc232a9dSJernej Skrabec 	hdmi->reg_io_width = 4;
94cc232a9dSJernej Skrabec 	hdmi->phy_set = dw_hdmi_phy_cfg;
95cc232a9dSJernej Skrabec 
96c2539483SSimon Glass 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
97c2539483SSimon Glass 
98c2539483SSimon Glass 	return 0;
99c2539483SSimon Glass }
100c2539483SSimon Glass 
101*147fd3acSPhilipp Tomsich void rk_hdmi_probe_regulators(struct udevice *dev,
102*147fd3acSPhilipp Tomsich 			      const char * const *names, int cnt)
103c2539483SSimon Glass {
104*147fd3acSPhilipp Tomsich 	rk_vop_probe_regulators(dev, names, cnt);
105*147fd3acSPhilipp Tomsich }
106*147fd3acSPhilipp Tomsich 
107*147fd3acSPhilipp Tomsich int rk_hdmi_probe(struct udevice *dev)
108*147fd3acSPhilipp Tomsich {
109c2539483SSimon Glass 	struct rk_hdmi_priv *priv = dev_get_priv(dev);
110cc232a9dSJernej Skrabec 	struct dw_hdmi *hdmi = &priv->hdmi;
111c2539483SSimon Glass 	int ret;
112c2539483SSimon Glass 
113cc232a9dSJernej Skrabec 	ret = dw_hdmi_phy_wait_for_hpd(hdmi);
114c2539483SSimon Glass 	if (ret < 0) {
115c2539483SSimon Glass 		debug("hdmi can not get hpd signal\n");
116c2539483SSimon Glass 		return -1;
117c2539483SSimon Glass 	}
118c2539483SSimon Glass 
119cc232a9dSJernej Skrabec 	dw_hdmi_init(hdmi);
120cc232a9dSJernej Skrabec 	dw_hdmi_phy_init(hdmi);
121c2539483SSimon Glass 
122c2539483SSimon Glass 	return 0;
123c2539483SSimon Glass }
124