diff options
Diffstat (limited to 'drivers/gpu/drm/mediatek/mtk_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/mediatek/mtk_hdmi.c | 413 |
1 files changed, 171 insertions, 242 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 06e4fac152b7..8803cd4a8bc9 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -31,7 +31,6 @@ #include <drm/drm_probe_helper.h> #include "mtk_cec.h" -#include "mtk_hdmi.h" #include "mtk_hdmi_regs.h" #define NCTS_BYTES 7 @@ -165,7 +164,7 @@ struct mtk_hdmi { bool dvi_mode; struct regmap *sys_regmap; unsigned int sys_offset; - void __iomem *regs; + struct regmap *regs; struct platform_device *audio_pdev; struct hdmi_audio_param aud_param; bool audio_enable; @@ -181,50 +180,10 @@ static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) return container_of(b, struct mtk_hdmi, bridge); } -static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset) -{ - return readl(hdmi->regs + offset); -} - -static void mtk_hdmi_write(struct mtk_hdmi *hdmi, u32 offset, u32 val) -{ - writel(val, hdmi->regs + offset); -} - -static void mtk_hdmi_clear_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) -{ - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp &= ~bits; - writel(tmp, reg); -} - -static void mtk_hdmi_set_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) -{ - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp |= bits; - writel(tmp, reg); -} - -static void mtk_hdmi_mask(struct mtk_hdmi *hdmi, u32 offset, u32 val, u32 mask) -{ - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp = (tmp & ~mask) | (val & mask); - writel(tmp, reg); -} - static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) { - mtk_hdmi_mask(hdmi, VIDEO_CFG_4, black ? GEN_RGB : NORMAL_PATH, - VIDEO_SOURCE_SEL); + regmap_update_bits(hdmi->regs, VIDEO_SOURCE_SEL, + VIDEO_CFG_4, black ? GEN_RGB : NORMAL_PATH); } static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) @@ -259,12 +218,12 @@ static void mtk_hdmi_hw_1p4_version_enable(struct mtk_hdmi *hdmi, bool enable) static void mtk_hdmi_hw_aud_mute(struct mtk_hdmi *hdmi) { - mtk_hdmi_set_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO); + regmap_set_bits(hdmi->regs, GRL_AUDIO_CFG, AUDIO_ZERO); } static void mtk_hdmi_hw_aud_unmute(struct mtk_hdmi *hdmi) { - mtk_hdmi_clear_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO); + regmap_clear_bits(hdmi->regs, GRL_AUDIO_CFG, AUDIO_ZERO); } static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi) @@ -273,25 +232,25 @@ static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi) HDMI_RST, HDMI_RST); regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C, HDMI_RST, 0); - mtk_hdmi_clear_bits(hdmi, GRL_CFG3, CFG3_CONTROL_PACKET_DELAY); + regmap_clear_bits(hdmi->regs, GRL_CFG3, CFG3_CONTROL_PACKET_DELAY); regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C, ANLG_ON, ANLG_ON); } static void mtk_hdmi_hw_enable_notice(struct mtk_hdmi *hdmi, bool enable_notice) { - mtk_hdmi_mask(hdmi, GRL_CFG2, enable_notice ? CFG2_NOTICE_EN : 0, - CFG2_NOTICE_EN); + regmap_update_bits(hdmi->regs, GRL_CFG2, CFG2_NOTICE_EN, + enable_notice ? CFG2_NOTICE_EN : 0); } static void mtk_hdmi_hw_write_int_mask(struct mtk_hdmi *hdmi, u32 int_mask) { - mtk_hdmi_write(hdmi, GRL_INT_MASK, int_mask); + regmap_write(hdmi->regs, GRL_INT_MASK, int_mask); } static void mtk_hdmi_hw_enable_dvi_mode(struct mtk_hdmi *hdmi, bool enable) { - mtk_hdmi_mask(hdmi, GRL_CFG1, enable ? CFG1_DVI : 0, CFG1_DVI); + regmap_update_bits(hdmi->regs, GRL_CFG1, CFG1_DVI, enable ? CFG1_DVI : 0); } static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, @@ -337,22 +296,22 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, dev_err(hdmi->dev, "Unknown infoframe type %d\n", frame_type); return; } - mtk_hdmi_clear_bits(hdmi, ctrl_reg, ctrl_frame_en); - mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, frame_type); - mtk_hdmi_write(hdmi, GRL_INFOFRM_VER, frame_ver); - mtk_hdmi_write(hdmi, GRL_INFOFRM_LNG, frame_len); + regmap_clear_bits(hdmi->regs, ctrl_reg, ctrl_frame_en); + regmap_write(hdmi->regs, GRL_INFOFRM_TYPE, frame_type); + regmap_write(hdmi->regs, GRL_INFOFRM_VER, frame_ver); + regmap_write(hdmi->regs, GRL_INFOFRM_LNG, frame_len); - mtk_hdmi_write(hdmi, GRL_IFM_PORT, checksum); + regmap_write(hdmi->regs, GRL_IFM_PORT, checksum); for (i = 0; i < frame_len; i++) - mtk_hdmi_write(hdmi, GRL_IFM_PORT, frame_data[i]); + regmap_write(hdmi->regs, GRL_IFM_PORT, frame_data[i]); - mtk_hdmi_set_bits(hdmi, ctrl_reg, ctrl_frame_en); + regmap_set_bits(hdmi->regs, ctrl_reg, ctrl_frame_en); } static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable) { - mtk_hdmi_mask(hdmi, GRL_SHIFT_R2, enable ? 0 : AUDIO_PACKET_OFF, - AUDIO_PACKET_OFF); + regmap_update_bits(hdmi->regs, AUDIO_PACKET_OFF, + GRL_SHIFT_R2, enable ? 0 : AUDIO_PACKET_OFF); } static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi) @@ -373,44 +332,44 @@ static void mtk_hdmi_hw_set_deep_color_mode(struct mtk_hdmi *hdmi) static void mtk_hdmi_hw_send_av_mute(struct mtk_hdmi *hdmi) { - mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CTRL_AVMUTE); + regmap_clear_bits(hdmi->regs, GRL_CFG4, CTRL_AVMUTE); usleep_range(2000, 4000); - mtk_hdmi_set_bits(hdmi, GRL_CFG4, CTRL_AVMUTE); + regmap_set_bits(hdmi->regs, GRL_CFG4, CTRL_AVMUTE); } static void mtk_hdmi_hw_send_av_unmute(struct mtk_hdmi *hdmi) { - mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_EN, - CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET); + regmap_update_bits(hdmi->regs, GRL_CFG4, CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET, + CFG4_AV_UNMUTE_EN); usleep_range(2000, 4000); - mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_SET, - CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET); + regmap_update_bits(hdmi->regs, GRL_CFG4, CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET, + CFG4_AV_UNMUTE_SET); } static void mtk_hdmi_hw_ncts_enable(struct mtk_hdmi *hdmi, bool on) { - mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, on ? 0 : CTS_CTRL_SOFT, - CTS_CTRL_SOFT); + regmap_update_bits(hdmi->regs, GRL_CTS_CTRL, CTS_CTRL_SOFT, + on ? 0 : CTS_CTRL_SOFT); } static void mtk_hdmi_hw_ncts_auto_write_enable(struct mtk_hdmi *hdmi, bool enable) { - mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, enable ? NCTS_WRI_ANYTIME : 0, - NCTS_WRI_ANYTIME); + regmap_update_bits(hdmi->regs, GRL_CTS_CTRL, NCTS_WRI_ANYTIME, + enable ? NCTS_WRI_ANYTIME : 0); } static void mtk_hdmi_hw_msic_setting(struct mtk_hdmi *hdmi, struct drm_display_mode *mode) { - mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CFG4_MHL_MODE); + regmap_clear_bits(hdmi->regs, GRL_CFG4, CFG4_MHL_MODE); if (mode->flags & DRM_MODE_FLAG_INTERLACE && mode->clock == 74250 && mode->vdisplay == 1080) - mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL); + regmap_clear_bits(hdmi->regs, GRL_CFG2, CFG2_MHL_DE_SEL); else - mtk_hdmi_set_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL); + regmap_set_bits(hdmi->regs, GRL_CFG2, CFG2_MHL_DE_SEL); } static void mtk_hdmi_hw_aud_set_channel_swap(struct mtk_hdmi *hdmi, @@ -438,7 +397,7 @@ static void mtk_hdmi_hw_aud_set_channel_swap(struct mtk_hdmi *hdmi, swap_bit = LFE_CC_SWAP; break; } - mtk_hdmi_mask(hdmi, GRL_CH_SWAP, swap_bit, 0xff); + regmap_update_bits(hdmi->regs, GRL_CH_SWAP, 0xff, swap_bit); } static void mtk_hdmi_hw_aud_set_bit_num(struct mtk_hdmi *hdmi, @@ -459,7 +418,7 @@ static void mtk_hdmi_hw_aud_set_bit_num(struct mtk_hdmi *hdmi, break; } - mtk_hdmi_mask(hdmi, GRL_AOUT_CFG, val, AOUT_BNUM_SEL_MASK); + regmap_update_bits(hdmi->regs, GRL_AOUT_CFG, AOUT_BNUM_SEL_MASK, val); } static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi, @@ -467,7 +426,7 @@ static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG0); + regmap_read(hdmi->regs, GRL_CFG0, &val); val &= ~(CFG0_W_LENGTH_MASK | CFG0_I2S_MODE_MASK); switch (i2s_fmt) { @@ -491,7 +450,7 @@ static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi, val |= CFG0_I2S_MODE_I2S | CFG0_W_LENGTH_16BIT; break; } - mtk_hdmi_write(hdmi, GRL_CFG0, val); + regmap_write(hdmi->regs, GRL_CFG0, val); } static void mtk_hdmi_hw_audio_config(struct mtk_hdmi *hdmi, bool dst) @@ -500,14 +459,14 @@ static void mtk_hdmi_hw_audio_config(struct mtk_hdmi *hdmi, bool dst) u8 val; /* Disable high bitrate, set DST packet normal/double */ - mtk_hdmi_clear_bits(hdmi, GRL_AOUT_CFG, HIGH_BIT_RATE_PACKET_ALIGN); + regmap_clear_bits(hdmi->regs, GRL_AOUT_CFG, HIGH_BIT_RATE_PACKET_ALIGN); if (dst) val = DST_NORMAL_DOUBLE | SACD_DST; else val = 0; - mtk_hdmi_mask(hdmi, GRL_AUDIO_CFG, val, mask); + regmap_update_bits(hdmi->regs, GRL_AUDIO_CFG, mask, val); } static void mtk_hdmi_hw_aud_set_i2s_chan_num(struct mtk_hdmi *hdmi, @@ -548,10 +507,10 @@ static void mtk_hdmi_hw_aud_set_i2s_chan_num(struct mtk_hdmi *hdmi, i2s_uv = I2S_UV_CH_EN(0); } - mtk_hdmi_write(hdmi, GRL_CH_SW0, ch_switch & 0xff); - mtk_hdmi_write(hdmi, GRL_CH_SW1, (ch_switch >> 8) & 0xff); - mtk_hdmi_write(hdmi, GRL_CH_SW2, (ch_switch >> 16) & 0xff); - mtk_hdmi_write(hdmi, GRL_I2S_UV, i2s_uv); + regmap_write(hdmi->regs, GRL_CH_SW0, ch_switch & 0xff); + regmap_write(hdmi->regs, GRL_CH_SW1, (ch_switch >> 8) & 0xff); + regmap_write(hdmi->regs, GRL_CH_SW2, (ch_switch >> 16) & 0xff); + regmap_write(hdmi->regs, GRL_I2S_UV, i2s_uv); } static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi, @@ -559,7 +518,7 @@ static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG1); + regmap_read(hdmi->regs, GRL_CFG1, &val); if (input_type == HDMI_AUD_INPUT_I2S && (val & CFG1_SPDIF) == CFG1_SPDIF) { val &= ~CFG1_SPDIF; @@ -567,7 +526,7 @@ static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi, (val & CFG1_SPDIF) == 0) { val |= CFG1_SPDIF; } - mtk_hdmi_write(hdmi, GRL_CFG1, val); + regmap_write(hdmi->regs, GRL_CFG1, val); } static void mtk_hdmi_hw_aud_set_channel_status(struct mtk_hdmi *hdmi, @@ -576,13 +535,13 @@ static void mtk_hdmi_hw_aud_set_channel_status(struct mtk_hdmi *hdmi, int i; for (i = 0; i < 5; i++) { - mtk_hdmi_write(hdmi, GRL_I2S_C_STA0 + i * 4, channel_status[i]); - mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, channel_status[i]); - mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, channel_status[i]); + regmap_write(hdmi->regs, GRL_I2S_C_STA0 + i * 4, channel_status[i]); + regmap_write(hdmi->regs, GRL_L_STATUS_0 + i * 4, channel_status[i]); + regmap_write(hdmi->regs, GRL_R_STATUS_0 + i * 4, channel_status[i]); } for (; i < 24; i++) { - mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, 0); - mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, 0); + regmap_write(hdmi->regs, GRL_L_STATUS_0 + i * 4, 0); + regmap_write(hdmi->regs, GRL_R_STATUS_0 + i * 4, 0); } } @@ -590,13 +549,13 @@ static void mtk_hdmi_hw_aud_src_reenable(struct mtk_hdmi *hdmi) { u32 val; - val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); + regmap_read(hdmi->regs, GRL_MIX_CTRL, &val); if (val & MIX_CTRL_SRC_EN) { val &= ~MIX_CTRL_SRC_EN; - mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); + regmap_write(hdmi->regs, GRL_MIX_CTRL, val); usleep_range(255, 512); val |= MIX_CTRL_SRC_EN; - mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); + regmap_write(hdmi->regs, GRL_MIX_CTRL, val); } } @@ -604,10 +563,10 @@ static void mtk_hdmi_hw_aud_src_disable(struct mtk_hdmi *hdmi) { u32 val; - val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); + regmap_read(hdmi->regs, GRL_MIX_CTRL, &val); val &= ~MIX_CTRL_SRC_EN; - mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); - mtk_hdmi_write(hdmi, GRL_SHIFT_L1, 0x00); + regmap_write(hdmi->regs, GRL_MIX_CTRL, val); + regmap_write(hdmi->regs, GRL_SHIFT_L1, 0x00); } static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi, @@ -615,7 +574,7 @@ static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG5); + regmap_read(hdmi->regs, GRL_CFG5, &val); val &= CFG5_CD_RATIO_MASK; switch (mclk) { @@ -638,7 +597,7 @@ static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi, val |= CFG5_FS256; break; } - mtk_hdmi_write(hdmi, GRL_CFG5, val); + regmap_write(hdmi->regs, GRL_CFG5, val); } struct hdmi_acr_n { @@ -716,15 +675,22 @@ static unsigned int hdmi_expected_cts(unsigned int audio_sample_rate, 128 * audio_sample_rate); } +static void mtk_hdmi_get_ncts(unsigned int sample_rate, unsigned int clock, + unsigned int *n, unsigned int *cts) +{ + *n = hdmi_recommended_n(sample_rate, clock); + *cts = hdmi_expected_cts(sample_rate, clock, *n); +} + static void do_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, unsigned int n, unsigned int cts) { unsigned char val[NCTS_BYTES]; int i; - mtk_hdmi_write(hdmi, GRL_NCTS, 0); - mtk_hdmi_write(hdmi, GRL_NCTS, 0); - mtk_hdmi_write(hdmi, GRL_NCTS, 0); + regmap_write(hdmi->regs, GRL_NCTS, 0); + regmap_write(hdmi->regs, GRL_NCTS, 0); + regmap_write(hdmi->regs, GRL_NCTS, 0); memset(val, 0, sizeof(val)); val[0] = (cts >> 24) & 0xff; @@ -737,7 +703,7 @@ static void do_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, unsigned int n, val[6] = n & 0xff; for (i = 0; i < NCTS_BYTES; i++) - mtk_hdmi_write(hdmi, GRL_NCTS, val[i]); + regmap_write(hdmi->regs, GRL_NCTS, val[i]); } static void mtk_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, @@ -746,14 +712,12 @@ static void mtk_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, { unsigned int n, cts; - n = hdmi_recommended_n(sample_rate, clock); - cts = hdmi_expected_cts(sample_rate, clock, n); + mtk_hdmi_get_ncts(sample_rate, clock, &n, &cts); dev_dbg(hdmi->dev, "%s: sample_rate=%u, clock=%d, cts=%u, n=%u\n", __func__, sample_rate, clock, n, cts); - mtk_hdmi_mask(hdmi, DUMMY_304, AUDIO_I2S_NCTS_SEL_64, - AUDIO_I2S_NCTS_SEL); + regmap_update_bits(hdmi->regs, DUMMY_304, AUDIO_I2S_NCTS_SEL, AUDIO_I2S_NCTS_SEL_64); do_hdmi_hw_aud_set_ncts(hdmi, n, cts); } @@ -873,7 +837,7 @@ static void mtk_hdmi_aud_set_input(struct mtk_hdmi *hdmi) bool dst; mtk_hdmi_hw_aud_set_channel_swap(hdmi, HDMI_AUD_SWAP_LFE_CC); - mtk_hdmi_set_bits(hdmi, GRL_MIX_CTRL, MIX_CTRL_FLAT); + regmap_set_bits(hdmi->regs, GRL_MIX_CTRL, MIX_CTRL_FLAT); if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF && hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST) { @@ -905,7 +869,7 @@ static int mtk_hdmi_aud_set_src(struct mtk_hdmi *hdmi, mtk_hdmi_hw_ncts_enable(hdmi, false); mtk_hdmi_hw_aud_src_disable(hdmi); - mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_ACLK_INV); + regmap_clear_bits(hdmi->regs, GRL_CFG2, CFG2_ACLK_INV); if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_I2S) { switch (sample_rate) { @@ -1061,20 +1025,6 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi, return 0; } -static int mtk_hdmi_output_init(struct mtk_hdmi *hdmi) -{ - struct hdmi_audio_param *aud_param = &hdmi->aud_param; - - aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; - aud_param->aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; - aud_param->aud_input_type = HDMI_AUD_INPUT_I2S; - aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; - aud_param->aud_mclk = HDMI_AUD_MCLK_128FS; - aud_param->aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; - - return 0; -} - static void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi) { mtk_hdmi_hw_send_aud_packet(hdmi, true); @@ -1087,20 +1037,6 @@ static void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi) hdmi->audio_enable = false; } -static int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi, - struct hdmi_audio_param *param) -{ - if (!hdmi->audio_enable) { - dev_err(hdmi->dev, "hdmi audio is in disable state!\n"); - return -EINVAL; - } - dev_dbg(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n", - param->aud_codec, param->aud_input_type, - param->aud_input_chan_type, param->codec_params.sample_rate); - memcpy(&hdmi->aud_param, param, sizeof(*param)); - return mtk_hdmi_aud_output_config(hdmi, &hdmi->mode); -} - static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi, struct drm_display_mode *mode) { @@ -1269,6 +1205,7 @@ static const struct drm_edid *mtk_hdmi_bridge_edid_read(struct drm_bridge *bridg } static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, enum drm_bridge_attach_flags flags) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); @@ -1281,7 +1218,7 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, } if (hdmi->next_bridge) { - ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, + ret = drm_bridge_attach(encoder, hdmi->next_bridge, bridge, flags); if (ret) return ret; @@ -1407,30 +1344,20 @@ static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = { .edid_read = mtk_hdmi_bridge_edid_read, }; -static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, - struct platform_device *pdev) +static int mtk_hdmi_get_cec_dev(struct mtk_hdmi *hdmi, struct device *dev, struct device_node *np) { - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct device_node *cec_np, *remote, *i2c_np; struct platform_device *cec_pdev; - struct regmap *regmap; + struct device_node *cec_np; int ret; ret = mtk_hdmi_get_all_clk(hdmi, np); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get clocks: %d\n", ret); - - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); /* The CEC module handles HDMI hotplug detection */ cec_np = of_get_compatible_child(np->parent, "mediatek,mt8173-cec"); - if (!cec_np) { - dev_err(dev, "Failed to find CEC node\n"); - return -EINVAL; - } + if (!cec_np) + return dev_err_probe(dev, -EINVAL, "Failed to find CEC node\n"); cec_pdev = of_find_device_by_node(cec_np); if (!cec_pdev) { @@ -1440,82 +1367,77 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, return -EPROBE_DEFER; } of_node_put(cec_np); - hdmi->cec_dev = &cec_pdev->dev; /* * The mediatek,syscon-hdmi property contains a phandle link to the * MMSYS_CONFIG device and the register offset of the HDMI_SYS_CFG * registers it contains. */ - regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,syscon-hdmi"); - ret = of_property_read_u32_index(np, "mediatek,syscon-hdmi", 1, - &hdmi->sys_offset); - if (IS_ERR(regmap)) - ret = PTR_ERR(regmap); - if (ret) { - dev_err(dev, - "Failed to get system configuration registers: %d\n", - ret); - goto put_device; - } - hdmi->sys_regmap = regmap; + hdmi->sys_regmap = syscon_regmap_lookup_by_phandle_args(np, "mediatek,syscon-hdmi", + 1, &hdmi->sys_offset); + if (IS_ERR(hdmi->sys_regmap)) + return dev_err_probe(dev, PTR_ERR(hdmi->sys_regmap), + "Failed to get system configuration registers\n"); - hdmi->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(hdmi->regs)) { - ret = PTR_ERR(hdmi->regs); - goto put_device; - } + hdmi->cec_dev = &cec_pdev->dev; + return 0; +} + +static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *remote, *i2c_np; + int ret; + + ret = mtk_hdmi_get_all_clk(hdmi, np); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + hdmi->regs = device_node_to_regmap(dev->of_node); + if (IS_ERR(hdmi->regs)) + return PTR_ERR(hdmi->regs); remote = of_graph_get_remote_node(np, 1, 0); - if (!remote) { - ret = -EINVAL; - goto put_device; - } + if (!remote) + return -EINVAL; if (!of_device_is_compatible(remote, "hdmi-connector")) { hdmi->next_bridge = of_drm_find_bridge(remote); if (!hdmi->next_bridge) { dev_err(dev, "Waiting for external bridge\n"); of_node_put(remote); - ret = -EPROBE_DEFER; - goto put_device; + return -EPROBE_DEFER; } } i2c_np = of_parse_phandle(remote, "ddc-i2c-bus", 0); - if (!i2c_np) { - dev_err(dev, "Failed to find ddc-i2c-bus node in %pOF\n", - remote); - of_node_put(remote); - ret = -EINVAL; - goto put_device; - } of_node_put(remote); + if (!i2c_np) + return dev_err_probe(dev, -EINVAL, "No ddc-i2c-bus in connector\n"); hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np); of_node_put(i2c_np); - if (!hdmi->ddc_adpt) { - dev_err(dev, "Failed to get ddc i2c adapter by node\n"); - ret = -EINVAL; - goto put_device; - } + if (!hdmi->ddc_adpt) + return dev_err_probe(dev, -EINVAL, "Failed to get ddc i2c adapter by node\n"); + + ret = mtk_hdmi_get_cec_dev(hdmi, dev, np); + if (ret) + return ret; return 0; -put_device: - put_device(hdmi->cec_dev); - return ret; } /* * HDMI audio codec callbacks */ -static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params) +static int mtk_hdmi_audio_params(struct mtk_hdmi *hdmi, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) { - struct mtk_hdmi *hdmi = dev_get_drvdata(dev); - struct hdmi_audio_param hdmi_params; + struct hdmi_audio_param aud_params = { 0 }; unsigned int chan = params->cea.channels; dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n", __func__, @@ -1526,16 +1448,16 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, switch (chan) { case 2: - hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; + aud_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; break; case 4: - hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_4_0; + aud_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_4_0; break; case 6: - hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_5_1; + aud_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_5_1; break; case 8: - hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_7_1; + aud_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_7_1; break; default: dev_err(hdmi->dev, "channel[%d] not supported!\n", chan); @@ -1559,27 +1481,45 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, switch (daifmt->fmt) { case HDMI_I2S: - hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; - hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; - hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S; - hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; - hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; + aud_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; + aud_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + aud_params.aud_input_type = HDMI_AUD_INPUT_I2S; + aud_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; + aud_params.aud_mclk = HDMI_AUD_MCLK_128FS; break; case HDMI_SPDIF: - hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; - hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; - hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; + aud_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; + aud_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + aud_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; break; default: dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__, daifmt->fmt); return -EINVAL; } + memcpy(&aud_params.codec_params, params, sizeof(aud_params.codec_params)); + memcpy(&hdmi->aud_param, &aud_params, sizeof(aud_params)); + + dev_dbg(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n", + aud_params.aud_codec, aud_params.aud_input_type, + aud_params.aud_input_chan_type, aud_params.codec_params.sample_rate); - memcpy(&hdmi_params.codec_params, params, - sizeof(hdmi_params.codec_params)); + return 0; +} + +static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + struct mtk_hdmi *hdmi = dev_get_drvdata(dev); - mtk_hdmi_audio_set_param(hdmi, &hdmi_params); + if (!hdmi->audio_enable) { + dev_err(hdmi->dev, "hdmi audio is in disable state!\n"); + return -EINVAL; + } + + mtk_hdmi_audio_params(hdmi, daifmt, params); + mtk_hdmi_aud_output_config(hdmi, &hdmi->mode); return 0; } @@ -1625,17 +1565,22 @@ static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, return 0; } -static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, - hdmi_codec_plugged_cb fn, +static void mtk_hdmi_audio_set_plugged_cb(struct mtk_hdmi *hdmi, hdmi_codec_plugged_cb fn, struct device *codec_dev) { - struct mtk_hdmi *hdmi = data; - mutex_lock(&hdmi->update_plugged_status_lock); hdmi->plugged_cb = fn; hdmi->codec_dev = codec_dev; mutex_unlock(&hdmi->update_plugged_status_lock); +} + +static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, + hdmi_codec_plugged_cb fn, + struct device *codec_dev) +{ + struct mtk_hdmi *hdmi = data; + mtk_hdmi_audio_set_plugged_cb(hdmi, fn, codec_dev); mtk_hdmi_update_plugged_status(hdmi); return 0; @@ -1658,6 +1603,7 @@ static void mtk_hdmi_unregister_audio_driver(void *data) static int mtk_hdmi_register_audio_driver(struct device *dev) { struct mtk_hdmi *hdmi = dev_get_drvdata(dev); + struct hdmi_audio_param *aud_param = &hdmi->aud_param; struct hdmi_codec_pdata codec_data = { .ops = &mtk_hdmi_audio_codec_ops, .max_i2s_channels = 2, @@ -1667,6 +1613,13 @@ static int mtk_hdmi_register_audio_driver(struct device *dev) }; int ret; + aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; + aud_param->aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + aud_param->aud_input_type = HDMI_AUD_INPUT_I2S; + aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; + aud_param->aud_mclk = HDMI_AUD_MCLK_128FS; + aud_param->aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; + hdmi->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, @@ -1708,11 +1661,6 @@ static int mtk_hdmi_probe(struct platform_device *pdev) mutex_init(&hdmi->update_plugged_status_lock); platform_set_drvdata(pdev, hdmi); - ret = mtk_hdmi_output_init(hdmi); - if (ret) - return dev_err_probe(dev, ret, - "Failed to initialize hdmi output\n"); - ret = mtk_hdmi_register_audio_driver(dev); if (ret) return dev_err_probe(dev, ret, @@ -1789,28 +1737,9 @@ static struct platform_driver mtk_hdmi_driver = { .pm = &mtk_hdmi_pm_ops, }, }; - -static struct platform_driver * const mtk_hdmi_drivers[] = { - &mtk_hdmi_ddc_driver, - &mtk_cec_driver, - &mtk_hdmi_driver, -}; - -static int __init mtk_hdmitx_init(void) -{ - return platform_register_drivers(mtk_hdmi_drivers, - ARRAY_SIZE(mtk_hdmi_drivers)); -} - -static void __exit mtk_hdmitx_exit(void) -{ - platform_unregister_drivers(mtk_hdmi_drivers, - ARRAY_SIZE(mtk_hdmi_drivers)); -} - -module_init(mtk_hdmitx_init); -module_exit(mtk_hdmitx_exit); +module_platform_driver(mtk_hdmi_driver); MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>"); MODULE_DESCRIPTION("MediaTek HDMI Driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("DRM_MTK_HDMI_V1"); |