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