1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2c2539483SSimon Glass /*
3147fd3acSPhilipp Tomsich * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
4c2539483SSimon Glass * Copyright (c) 2015 Google, Inc
5c2539483SSimon Glass * Copyright 2014 Rockchip Inc.
6c2539483SSimon Glass */
7c2539483SSimon Glass
8c2539483SSimon Glass #include <common.h>
9c2539483SSimon Glass #include <clk.h>
10c2539483SSimon Glass #include <display.h>
11c2539483SSimon Glass #include <dm.h>
12cc232a9dSJernej Skrabec #include <dw_hdmi.h>
13c2539483SSimon Glass #include <edid.h>
14c2539483SSimon Glass #include <regmap.h>
15c2539483SSimon Glass #include <syscon.h>
16c2539483SSimon Glass #include <asm/gpio.h>
1712085239SPhilipp Tomsich #include <asm/hardware.h>
18c2539483SSimon Glass #include <asm/io.h>
19c2539483SSimon Glass #include <asm/arch/clock.h>
20147fd3acSPhilipp Tomsich #include <asm/arch/hardware.h>
21147fd3acSPhilipp Tomsich #include "rk_hdmi.h"
22147fd3acSPhilipp Tomsich #include "rk_vop.h" /* for rk_vop_probe_regulators */
23c2539483SSimon Glass
24c2539483SSimon Glass static const struct hdmi_phy_config rockchip_phy_config[] = {
25c2539483SSimon Glass {
260fc41e55SNickey Yang Nickey Yang .mpixelclock = 74250000,
27c2539483SSimon Glass .sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
28c2539483SSimon Glass }, {
290fc41e55SNickey Yang Nickey Yang .mpixelclock = 148500000,
30c2539483SSimon Glass .sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
31c2539483SSimon Glass }, {
320fc41e55SNickey Yang Nickey Yang .mpixelclock = 297000000,
33c2539483SSimon Glass .sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d,
34c2539483SSimon Glass }, {
35f210e557SPhilipp Tomsich .mpixelclock = 584000000,
36f210e557SPhilipp Tomsich .sym_ctr = 0x8039, .term = 0x0000, .vlev_ctr = 0x019d,
37f210e557SPhilipp Tomsich }, {
38c2539483SSimon Glass .mpixelclock = ~0ul,
39c2539483SSimon Glass .sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000,
40c2539483SSimon Glass }
41c2539483SSimon Glass };
42c2539483SSimon Glass
43c2539483SSimon Glass static const struct hdmi_mpll_config rockchip_mpll_cfg[] = {
44c2539483SSimon Glass {
450fc41e55SNickey Yang Nickey Yang .mpixelclock = 40000000,
46c2539483SSimon Glass .cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
47c2539483SSimon Glass }, {
480fc41e55SNickey Yang Nickey Yang .mpixelclock = 65000000,
49c2539483SSimon Glass .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
50c2539483SSimon Glass }, {
510fc41e55SNickey Yang Nickey Yang .mpixelclock = 66000000,
52c2539483SSimon Glass .cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
53c2539483SSimon Glass }, {
5494412745SNickey Yang Nickey Yang .mpixelclock = 83500000,
55c2539483SSimon Glass .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
56c2539483SSimon Glass }, {
570fc41e55SNickey Yang Nickey Yang .mpixelclock = 146250000,
58c2539483SSimon Glass .cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
59c2539483SSimon Glass }, {
600fc41e55SNickey Yang Nickey Yang .mpixelclock = 148500000,
61c2539483SSimon Glass .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
62c2539483SSimon Glass }, {
63f210e557SPhilipp Tomsich .mpixelclock = 272000000,
64f210e557SPhilipp Tomsich .cpce = 0x0040, .gmp = 0x0003, .curr = 0x0000,
65f210e557SPhilipp Tomsich }, {
66f210e557SPhilipp Tomsich .mpixelclock = 340000000,
67f210e557SPhilipp Tomsich .cpce = 0x0040, .gmp = 0x0003, .curr = 0x0000,
68f210e557SPhilipp Tomsich }, {
69c2539483SSimon Glass .mpixelclock = ~0ul,
70c2539483SSimon Glass .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
71c2539483SSimon Glass }
72c2539483SSimon Glass };
73c2539483SSimon Glass
rk_hdmi_read_edid(struct udevice * dev,u8 * buf,int buf_size)74147fd3acSPhilipp Tomsich int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size)
75c2539483SSimon Glass {
76c2539483SSimon Glass struct rk_hdmi_priv *priv = dev_get_priv(dev);
77c2539483SSimon Glass
78cc232a9dSJernej Skrabec return dw_hdmi_read_edid(&priv->hdmi, buf, buf_size);
79c2539483SSimon Glass }
80c2539483SSimon Glass
rk_hdmi_ofdata_to_platdata(struct udevice * dev)81147fd3acSPhilipp Tomsich int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
82c2539483SSimon Glass {
83c2539483SSimon Glass struct rk_hdmi_priv *priv = dev_get_priv(dev);
84cc232a9dSJernej Skrabec struct dw_hdmi *hdmi = &priv->hdmi;
85c2539483SSimon Glass
8618e48776SPhilipp Tomsich hdmi->ioaddr = (ulong)dev_read_addr(dev);
87cc232a9dSJernej Skrabec hdmi->mpll_cfg = rockchip_mpll_cfg;
88cc232a9dSJernej Skrabec hdmi->phy_cfg = rockchip_phy_config;
89cc232a9dSJernej Skrabec
90147fd3acSPhilipp Tomsich /* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
91147fd3acSPhilipp Tomsich
92cc232a9dSJernej Skrabec hdmi->reg_io_width = 4;
93cc232a9dSJernej Skrabec hdmi->phy_set = dw_hdmi_phy_cfg;
94cc232a9dSJernej Skrabec
95c2539483SSimon Glass priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
96c2539483SSimon Glass
97c2539483SSimon Glass return 0;
98c2539483SSimon Glass }
99c2539483SSimon Glass
rk_hdmi_probe_regulators(struct udevice * dev,const char * const * names,int cnt)100147fd3acSPhilipp Tomsich void rk_hdmi_probe_regulators(struct udevice *dev,
101147fd3acSPhilipp Tomsich const char * const *names, int cnt)
102c2539483SSimon Glass {
103147fd3acSPhilipp Tomsich rk_vop_probe_regulators(dev, names, cnt);
104147fd3acSPhilipp Tomsich }
105147fd3acSPhilipp Tomsich
rk_hdmi_probe(struct udevice * dev)106147fd3acSPhilipp Tomsich int rk_hdmi_probe(struct udevice *dev)
107147fd3acSPhilipp Tomsich {
108c2539483SSimon Glass struct rk_hdmi_priv *priv = dev_get_priv(dev);
109cc232a9dSJernej Skrabec struct dw_hdmi *hdmi = &priv->hdmi;
110c2539483SSimon Glass int ret;
111c2539483SSimon Glass
112cc232a9dSJernej Skrabec ret = dw_hdmi_phy_wait_for_hpd(hdmi);
113c2539483SSimon Glass if (ret < 0) {
114c2539483SSimon Glass debug("hdmi can not get hpd signal\n");
115c2539483SSimon Glass return -1;
116c2539483SSimon Glass }
117c2539483SSimon Glass
118cc232a9dSJernej Skrabec dw_hdmi_init(hdmi);
119cc232a9dSJernej Skrabec dw_hdmi_phy_init(hdmi);
120c2539483SSimon Glass
121c2539483SSimon Glass return 0;
122c2539483SSimon Glass }
123