aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c54
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c12
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c14
-rw-r--r--include/drm/bridge/dw_hdmi.h5
4 files changed, 45 insertions, 40 deletions
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index cd6a70647e32..49cafb61d290 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -16,6 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/hdmi.h> 18#include <linux/hdmi.h>
19#include <linux/mutex.h>
19#include <linux/of_device.h> 20#include <linux/of_device.h>
20 21
21#include <drm/drm_of.h> 22#include <drm/drm_of.h>
@@ -126,6 +127,7 @@ struct dw_hdmi {
126 struct i2c_adapter *ddc; 127 struct i2c_adapter *ddc;
127 void __iomem *regs; 128 void __iomem *regs;
128 129
130 struct mutex audio_mutex;
129 unsigned int sample_rate; 131 unsigned int sample_rate;
130 int ratio; 132 int ratio;
131 133
@@ -177,26 +179,23 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
177 hdmi_modb(hdmi, data << shift, mask, reg); 179 hdmi_modb(hdmi, data << shift, mask, reg);
178} 180}
179 181
180static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi, 182static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
181 unsigned int value) 183 unsigned int n)
182{ 184{
183 hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); 185 /* Must be set/cleared first */
184 hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2); 186 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
185 hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
186 187
187 /* nshift factor = 0 */ 188 /* nshift factor = 0 */
188 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); 189 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
189}
190
191static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts)
192{
193 /* Must be set/cleared first */
194 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
195 190
196 hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
197 hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
198 hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | 191 hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
199 HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); 192 HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
193 hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
194 hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
195
196 hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
197 hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
198 hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
200} 199}
201 200
202static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk, 201static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
@@ -355,18 +354,21 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
355 __func__, hdmi->sample_rate, hdmi->ratio, 354 __func__, hdmi->sample_rate, hdmi->ratio,
356 pixel_clk, clk_n, clk_cts); 355 pixel_clk, clk_n, clk_cts);
357 356
358 hdmi_set_clock_regenerator_n(hdmi, clk_n); 357 hdmi_set_cts_n(hdmi, clk_cts, clk_n);
359 hdmi_regenerate_cts(hdmi, clk_cts);
360} 358}
361 359
362static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) 360static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
363{ 361{
362 mutex_lock(&hdmi->audio_mutex);
364 hdmi_set_clk_regenerator(hdmi, 74250000); 363 hdmi_set_clk_regenerator(hdmi, 74250000);
364 mutex_unlock(&hdmi->audio_mutex);
365} 365}
366 366
367static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) 367static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
368{ 368{
369 mutex_lock(&hdmi->audio_mutex);
369 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); 370 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
371 mutex_unlock(&hdmi->audio_mutex);
370} 372}
371 373
372/* 374/*
@@ -753,10 +755,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
753{ 755{
754 unsigned res_idx, i; 756 unsigned res_idx, i;
755 u8 val, msec; 757 u8 val, msec;
756 const struct dw_hdmi_mpll_config *mpll_config = 758 const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data;
757 hdmi->plat_data->mpll_cfg; 759 const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg;
758 const struct dw_hdmi_curr_ctrl *curr_ctrl = hdmi->plat_data->cur_ctr; 760 const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr;
759 const struct dw_hdmi_sym_term *sym_term = hdmi->plat_data->sym_term; 761 const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config;
760 762
761 if (prep) 763 if (prep)
762 return -EINVAL; 764 return -EINVAL;
@@ -827,18 +829,18 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
827 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ 829 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
828 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); 830 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
829 831
830 for (i = 0; sym_term[i].mpixelclock != (~0UL); i++) 832 for (i = 0; phy_config[i].mpixelclock != (~0UL); i++)
831 if (hdmi->hdmi_data.video_mode.mpixelclock <= 833 if (hdmi->hdmi_data.video_mode.mpixelclock <=
832 sym_term[i].mpixelclock) 834 phy_config[i].mpixelclock)
833 break; 835 break;
834 836
835 /* RESISTANCE TERM 133Ohm Cfg */ 837 /* RESISTANCE TERM 133Ohm Cfg */
836 hdmi_phy_i2c_write(hdmi, sym_term[i].term, 0x19); /* TXTERM */ 838 hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19); /* TXTERM */
837 /* PREEMP Cgf 0.00 */ 839 /* PREEMP Cgf 0.00 */
838 hdmi_phy_i2c_write(hdmi, sym_term[i].sym_ctr, 0x09); /* CKSYMTXCTRL */ 840 hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
839
840 /* TX/CK LVL 10 */ 841 /* TX/CK LVL 10 */
841 hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */ 842 hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
843
842 /* REMOVE CLK TERM */ 844 /* REMOVE CLK TERM */
843 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ 845 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
844 846
@@ -1569,6 +1571,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
1569 hdmi->ratio = 100; 1571 hdmi->ratio = 100;
1570 hdmi->encoder = encoder; 1572 hdmi->encoder = encoder;
1571 1573
1574 mutex_init(&hdmi->audio_mutex);
1575
1572 of_property_read_u32(np, "reg-io-width", &val); 1576 of_property_read_u32(np, "reg-io-width", &val);
1573 1577
1574 switch (val) { 1578 switch (val) {
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 1834ac8998cc..a3ecf1069b76 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -75,10 +75,10 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
75 }, 75 },
76}; 76};
77 77
78static const struct dw_hdmi_sym_term imx_sym_term[] = { 78static const struct dw_hdmi_phy_config imx_phy_config[] = {
79 /*pixelclk symbol term*/ 79 /*pixelclk symbol term vlev */
80 { 148500000, 0x800d, 0x0005 }, 80 { 148500000, 0x800d, 0x0005, 0x01ad},
81 { ~0UL, 0x0000, 0x0000 } 81 { ~0UL, 0x0000, 0x0000, 0x0000}
82}; 82};
83 83
84static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi) 84static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi)
@@ -163,7 +163,7 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
163static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = { 163static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
164 .mpll_cfg = imx_mpll_cfg, 164 .mpll_cfg = imx_mpll_cfg,
165 .cur_ctr = imx_cur_ctr, 165 .cur_ctr = imx_cur_ctr,
166 .sym_term = imx_sym_term, 166 .phy_config = imx_phy_config,
167 .dev_type = IMX6Q_HDMI, 167 .dev_type = IMX6Q_HDMI,
168 .mode_valid = imx6q_hdmi_mode_valid, 168 .mode_valid = imx6q_hdmi_mode_valid,
169}; 169};
@@ -171,7 +171,7 @@ static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
171static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { 171static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
172 .mpll_cfg = imx_mpll_cfg, 172 .mpll_cfg = imx_mpll_cfg,
173 .cur_ctr = imx_cur_ctr, 173 .cur_ctr = imx_cur_ctr,
174 .sym_term = imx_sym_term, 174 .phy_config = imx_phy_config,
175 .dev_type = IMX6DL_HDMI, 175 .dev_type = IMX6DL_HDMI,
176 .mode_valid = imx6dl_hdmi_mode_valid, 176 .mode_valid = imx6dl_hdmi_mode_valid,
177}; 177};
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index d236faa05b19..80d6fc8a5cee 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -133,12 +133,12 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
133 } 133 }
134}; 134};
135 135
136static const struct dw_hdmi_sym_term rockchip_sym_term[] = { 136static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
137 /*pixelclk symbol term*/ 137 /*pixelclk symbol term vlev*/
138 { 74250000, 0x8009, 0x0004 }, 138 { 74250000, 0x8009, 0x0004, 0x0272},
139 { 148500000, 0x8029, 0x0004 }, 139 { 148500000, 0x802b, 0x0004, 0x028d},
140 { 297000000, 0x8039, 0x0005 }, 140 { 297000000, 0x8039, 0x0005, 0x028d},
141 { ~0UL, 0x0000, 0x0000 } 141 { ~0UL, 0x0000, 0x0000, 0x0000}
142}; 142};
143 143
144static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) 144static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
@@ -230,7 +230,7 @@ static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
230 .mode_valid = dw_hdmi_rockchip_mode_valid, 230 .mode_valid = dw_hdmi_rockchip_mode_valid,
231 .mpll_cfg = rockchip_mpll_cfg, 231 .mpll_cfg = rockchip_mpll_cfg,
232 .cur_ctr = rockchip_cur_ctr, 232 .cur_ctr = rockchip_cur_ctr,
233 .sym_term = rockchip_sym_term, 233 .phy_config = rockchip_phy_config,
234 .dev_type = RK3288_HDMI, 234 .dev_type = RK3288_HDMI,
235}; 235};
236 236
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 5a4f49005169..de13bfc35634 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -38,17 +38,18 @@ struct dw_hdmi_curr_ctrl {
38 u16 curr[DW_HDMI_RES_MAX]; 38 u16 curr[DW_HDMI_RES_MAX];
39}; 39};
40 40
41struct dw_hdmi_sym_term { 41struct dw_hdmi_phy_config {
42 unsigned long mpixelclock; 42 unsigned long mpixelclock;
43 u16 sym_ctr; /*clock symbol and transmitter control*/ 43 u16 sym_ctr; /*clock symbol and transmitter control*/
44 u16 term; /*transmission termination value*/ 44 u16 term; /*transmission termination value*/
45 u16 vlev_ctr; /* voltage level control */
45}; 46};
46 47
47struct dw_hdmi_plat_data { 48struct dw_hdmi_plat_data {
48 enum dw_hdmi_devtype dev_type; 49 enum dw_hdmi_devtype dev_type;
49 const struct dw_hdmi_mpll_config *mpll_cfg; 50 const struct dw_hdmi_mpll_config *mpll_cfg;
50 const struct dw_hdmi_curr_ctrl *cur_ctr; 51 const struct dw_hdmi_curr_ctrl *cur_ctr;
51 const struct dw_hdmi_sym_term *sym_term; 52 const struct dw_hdmi_phy_config *phy_config;
52 enum drm_mode_status (*mode_valid)(struct drm_connector *connector, 53 enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
53 struct drm_display_mode *mode); 54 struct drm_display_mode *mode);
54}; 55};