aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-04-15 18:33:30 -0400
committerDave Airlie <airlied@redhat.com>2015-04-15 18:33:30 -0400
commit52139bdea1558e854123d7a07e7648f5a8c77a5c (patch)
tree846c411449c8a4f0618ec3426cff697428cc0c51
parentfc16fc4d69d5f1b67d3d6ac97bd3b4e1cc3f74cc (diff)
parent1dbee1a3c38a8792c235048df1d709fc5ca3a185 (diff)
Merge branch 'drm-dwhdmi-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into drm-next
This set of patches adjust the setup of the HDMI CTS/N values for audio support to be compliant with the work-around given in the iMX6 errata documentation as part of the preparation for integrating audio support for this driver, and also update the HDMI phy configuration for Rockchip devices to improve the HDMI eye pattern. * 'drm-dwhdmi-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: drm: rockchip/dw_hdmi-rockchip: improve for HDMI electrical test drm: bridge/dw_hdmi: separate VLEVCTRL settting into platform driver drm: bridge/dw_hdmi: fixed codec style drm: bridge/dw_hdmi: adjust n/cts setting order drm: bridge/dw_hdmi: protect n/cts setting with a mutex drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts() Conflicts: drivers/gpu/drm/imx/dw_hdmi-imx.c
-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};