diff options
-rw-r--r-- | drivers/gpu/drm/bridge/dw_hdmi.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/dw_hdmi-imx.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 14 | ||||
-rw-r--r-- | include/drm/bridge/dw_hdmi.h | 5 |
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 | ||
180 | static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi, | 182 | static 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 | |||
191 | static 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 | ||
202 | static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk, | 201 | static 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 | ||
362 | static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) | 360 | static 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 | ||
367 | static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) | 367 | static 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 | ||
78 | static const struct dw_hdmi_sym_term imx_sym_term[] = { | 78 | static 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 | ||
84 | static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi) | 84 | static 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, | |||
163 | static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = { | 163 | static 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 = { | |||
171 | static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { | 171 | static 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 | ||
136 | static const struct dw_hdmi_sym_term rockchip_sym_term[] = { | 136 | static 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 | ||
144 | static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) | 144 | static 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 | ||
41 | struct dw_hdmi_sym_term { | 41 | struct 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 | ||
47 | struct dw_hdmi_plat_data { | 48 | struct 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 | }; |