diff options
author | Dave Airlie <airlied@redhat.com> | 2015-04-16 01:33:30 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-04-16 01:33:30 +0300 |
commit | 52139bdea1558e854123d7a07e7648f5a8c77a5c (patch) | |
tree | 846c411449c8a4f0618ec3426cff697428cc0c51 /drivers/gpu/drm/bridge | |
parent | fc16fc4d69d5f1b67d3d6ac97bd3b4e1cc3f74cc (diff) | |
parent | 1dbee1a3c38a8792c235048df1d709fc5ca3a185 (diff) | |
download | linux-52139bdea1558e854123d7a07e7648f5a8c77a5c.tar.xz |
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
Diffstat (limited to 'drivers/gpu/drm/bridge')
-rw-r--r-- | drivers/gpu/drm/bridge/dw_hdmi.c | 54 |
1 files changed, 29 insertions, 25 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 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/hdmi.h> +#include <linux/mutex.h> #include <linux/of_device.h> #include <drm/drm_of.h> @@ -126,6 +127,7 @@ struct dw_hdmi { struct i2c_adapter *ddc; void __iomem *regs; + struct mutex audio_mutex; unsigned int sample_rate; int ratio; @@ -177,26 +179,23 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, hdmi_modb(hdmi, data << shift, mask, reg); } -static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi, - unsigned int value) +static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, + unsigned int n) { - hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); - hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2); - hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3); + /* Must be set/cleared first */ + hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); /* nshift factor = 0 */ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); -} - -static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts) -{ - /* Must be set/cleared first */ - hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); - hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); - hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); + hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); + hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); + + hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3); + hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); + hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); } 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, __func__, hdmi->sample_rate, hdmi->ratio, pixel_clk, clk_n, clk_cts); - hdmi_set_clock_regenerator_n(hdmi, clk_n); - hdmi_regenerate_cts(hdmi, clk_cts); + hdmi_set_cts_n(hdmi, clk_cts, clk_n); } static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) { + mutex_lock(&hdmi->audio_mutex); hdmi_set_clk_regenerator(hdmi, 74250000); + mutex_unlock(&hdmi->audio_mutex); } static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) { + mutex_lock(&hdmi->audio_mutex); hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); + mutex_unlock(&hdmi->audio_mutex); } /* @@ -753,10 +755,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, { unsigned res_idx, i; u8 val, msec; - const struct dw_hdmi_mpll_config *mpll_config = - hdmi->plat_data->mpll_cfg; - const struct dw_hdmi_curr_ctrl *curr_ctrl = hdmi->plat_data->cur_ctr; - const struct dw_hdmi_sym_term *sym_term = hdmi->plat_data->sym_term; + const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; + const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr; + const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config; if (prep) return -EINVAL; @@ -827,18 +829,18 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); - for (i = 0; sym_term[i].mpixelclock != (~0UL); i++) + for (i = 0; phy_config[i].mpixelclock != (~0UL); i++) if (hdmi->hdmi_data.video_mode.mpixelclock <= - sym_term[i].mpixelclock) + phy_config[i].mpixelclock) break; /* RESISTANCE TERM 133Ohm Cfg */ - hdmi_phy_i2c_write(hdmi, sym_term[i].term, 0x19); /* TXTERM */ + hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19); /* TXTERM */ /* PREEMP Cgf 0.00 */ - hdmi_phy_i2c_write(hdmi, sym_term[i].sym_ctr, 0x09); /* CKSYMTXCTRL */ - + hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */ /* TX/CK LVL 10 */ - hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */ + hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */ + /* REMOVE CLK TERM */ hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ @@ -1569,6 +1571,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, hdmi->ratio = 100; hdmi->encoder = encoder; + mutex_init(&hdmi->audio_mutex); + of_property_read_u32(np, "reg-io-width", &val); switch (val) { |