From: zwl Date: Tue, 11 Mar 2014 08:14:11 +0000 (+0800) Subject: HDMI: optimize rk3288 hdmi driver code X-Git-Tag: firefly_0821_release~6148 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=fa14d67d10dc42a35ceff36b5c1b0d897083f43c;p=firefly-linux-kernel-4.4.55.git HDMI: optimize rk3288 hdmi driver code --- diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.c index ce511d69c907..a8ea1871a1bd 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.c +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.c @@ -27,9 +27,16 @@ #include #endif +#include "../../../../../../arch/arm/mach-rockchip/grf.h" +#include "../../../../../../arch/arm/mach-rockchip/iomap.h" #include "rk3288_hdmi_hw.h" #include "rk3288_hdmi.h" + +#define grf_readl(offset) readl_relaxed(RK_GRF_VIRT + offset) +#define grf_writel(v,offset) do{ writel_relaxed(v, RK_GRF_VIRT + offset);dsb();} while (0) + + extern irqreturn_t hdmi_irq(int irq, void *priv); static struct rk3288_hdmi_device *hdmi_dev = NULL; @@ -118,7 +125,7 @@ static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv) int ret = 0; //struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk_hdmi_device, driver); - //grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id),GRF_SOC_CON6); //lcdc source select-->have config at lcdc driver so delete it + grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id), RK3288_GRF_SOC_CON6); //lcdc source select if(hdmi_dev->lcdc_id == 0) hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0"); else diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.h index b2d7b2124417..1ba67a2136fe 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.h +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.h @@ -4,6 +4,8 @@ #include "../../rk_hdmi.h" +#define ENABLE 16 +#define HDMI_SEL_LCDC(x) ((((x)&1)<<4)|(1<<(4+ENABLE))) #endif /* __RK3288_HDMI_H__ */ diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c index 99fbc09c346c..3cb08a18230a 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c @@ -29,6 +29,32 @@ const struct phy_mpll_config_tab* get_phy_mpll_tab(int pixClock, char pixRepet, return NULL; } +static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode) +{ + if(hdmi_drv->pwr_mode == mode) + return; + + hdmi_dbg(hdmi->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__, hdmi_drv->pwr_mode, mode); + switch(mode) + { + case NORMAL: + hdmi_msk_reg(hdmi_dev, MC_SWRSTZREQ, m_TMDS_SWRST | m_PIXEL_SWRST, + v_TMDS_SWRST(0) | v_PIXEL_SWRST(0)); + hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE, + v_AUDCLK_DISABLE(0) | v_PREPCLK_DISABLE(0) | v_TMDSCLK_DISABLE(0) | v_PIXELCLK_DISABLE(0)); + hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(1)); + hdmi_msk_reg(hdmi_dev, FC_GCP, m_FC_SET_AVMUTE, v_FC_SET_AVMUTE(1)); + break; + case LOWER_PWR: + hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE, + v_AUDCLK_DISABLE(1) | v_PREPCLK_DISABLE(1) | v_TMDSCLK_DISABLE(1) | v_PIXELCLK_DISABLE(1)); + hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(0)); + break; + default: + hdmi_dbg(hdmi_drv->dev,"unkown hdmi pwr mode %d\n",mode); + } + hdmi_drv->pwr_mode = mode; +} //i2c master reset void rk3288_hdmi_i2cm_reset(struct rk3288_hdmi_device *hdmi_dev) @@ -204,6 +230,8 @@ static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic, uns y1y0 = AVI_COLOR_MODE_YCBCR444; else if(output_color == VIDEO_OUTPUT_YCBCR422) y1y0 = AVI_COLOR_MODE_YCBCR422; + else if(output_color == VIDEO_OUTPUT_YCBCR420) + y1y0 = AVI_COLOR_MODE_YCBCR420; else y1y0 = AVI_COLOR_MODE_RGB; @@ -298,6 +326,7 @@ static void rk3288_hdmi_config_csc(struct hdmi *hdmi_drv, struct hdmi_video_para if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) || ((vpara->input_color == VIDEO_INPUT_COLOR_YCBCR) && (vpara->output_color != VIDEO_OUTPUT_RGB444) )) { + hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(0)); return; } @@ -335,6 +364,7 @@ static void rk3288_hdmi_config_csc(struct hdmi *hdmi_drv, struct hdmi_video_para hdmi_writel(hdmi_dev, CSC_COEF_A1_MSB + i, coeff[i]); //enable CSC TODO Daisen wait to add + hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(1)); } @@ -348,6 +378,9 @@ int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpar int de_pol = hdmi_drv->lcdc->cur_screen->pin_den; struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver); + if(hdmi_drv->pwr_mode == LOWER_PWR) + rk3288_hdmi_set_pwr_mode(NORMAL); + switch(vpara->input_color) { case VIDEO_OUTPUT_RGB444: @@ -433,16 +466,25 @@ int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpar static void rk3288_hdmi_config_aai(struct hdmi *hdmi_drv, struct hdmi_audio *audio) { - //struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver); + struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver); + + //Refer to CEA861-E Audio infoFrame + //Set both Audio Channel Count and Audio Coding Type Refer to Stream Head for HDMI + hdmi_msk_reg(hdmi_dev, FC_AUDICONF0, m_FC_CHN_CNT | m_FC_CODING_TYEP, v_FC_CHN_CNT(0) | v_FC_CODING_TYEP(0)); + + //Set both Audio Sample Size and Sample Frequency Refer to Stream Head for HDMI + hdmi_msk_reg(hdmi_dev, FC_AUDICONF1, m_FC_SAMPLE_SIZE | m_FC_SAMPLE_FREQ, v_FC_SAMPLE_SIZE(0) | v_FC_SAMPLE_FREQ(0)); - //hdmi_writel(hdmi_dev, FC_AUDICONF0, m_FC_CHN_CNT | m_FC_CODING_TYEP, v_FC_CHN_CNT(audio->channel) | v_FC_CODING_TYEP()); + //Set Channel Allocation + hdmi_writel(hdmi_dev, FC_AUDICONF2, 0x00); - //TODO Daisen wait to add + //Set LFEPBL¡¢DOWN-MIX INH and LSV + hdmi_writel(hdmi_dev, FC_AUDICONF3, 0x00); } int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) { - int word_length = 0,channel = 0,N = 0; + int word_length = 0, channel = 0, N = 0, mclk_fs; struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver); if(audio->channel < 3) //TODO Daisen @@ -457,6 +499,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) switch(audio->rate) { case HDMI_AUDIO_FS_32000: + mclk_fs = FS_128; if(hdmi_drv->tmdsclk >= 594000000) N = N_32K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) @@ -465,6 +508,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_32K_LOWCLK; break; case HDMI_AUDIO_FS_44100: + mclk_fs = FS_128; if(hdmi_drv->tmdsclk >= 594000000) N = N_441K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) @@ -473,7 +517,8 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_441K_LOWCLK; break; case HDMI_AUDIO_FS_48000: - if(hdmi_drv->tmdsclk >= 594000000) + mclk_fs = FS_128; + if(hdmi_drv->tmdsclk >= 594000000) //FS_153.6 N = N_48K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) N = N_48K_MIDCLK; @@ -481,6 +526,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_48K_LOWCLK; break; case HDMI_AUDIO_FS_88200: + mclk_fs = FS_128; if(hdmi_drv->tmdsclk >= 594000000) N = N_882K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) @@ -489,7 +535,8 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_882K_LOWCLK; break; case HDMI_AUDIO_FS_96000: - if(hdmi_drv->tmdsclk >= 594000000) + mclk_fs = FS_128; + if(hdmi_drv->tmdsclk >= 594000000) //FS_153.6 N = N_96K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) N = N_96K_MIDCLK; @@ -497,6 +544,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_96K_LOWCLK; break; case HDMI_AUDIO_FS_176400: + mclk_fs = FS_128; if(hdmi_drv->tmdsclk >= 594000000) N = N_1764K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) @@ -505,7 +553,8 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) N = N_1764K_LOWCLK; break; case HDMI_AUDIO_FS_192000: - if(hdmi_drv->tmdsclk >= 594000000) + mclk_fs = FS_128; + if(hdmi_drv->tmdsclk >= 594000000) //FS_153.6 N = N_192K_HIGHCLK; else if(hdmi_drv->tmdsclk == 297000000) N = N_192K_MIDCLK; @@ -541,7 +590,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) hdmi_writel(hdmi_dev, AUD_CONF1, v_I2S_MODE(I2S_STANDARD_MODE) | v_I2S_WIDTH(word_length)); } - hdmi_msk_reg(hdmi_dev, AUD_INPUTCLKFS, m_LFS_FACTOR, v_LFS_FACTOR(FS_128)); + hdmi_msk_reg(hdmi_dev, AUD_INPUTCLKFS, m_LFS_FACTOR, v_LFS_FACTOR(mclk_fs)); //Set N value hdmi_msk_reg(hdmi_dev, AUD_N3, m_AUD_N3, v_AUD_N3(N >> 16)); @@ -550,6 +599,7 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) //Set Automatic CTS generation hdmi_msk_reg(hdmi_dev, AUD_CTS3, m_CTS_MANUAL, v_CTS_MANUAL(0)); + hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE, v_AUDCLK_DISABLE(0)); rk3288_hdmi_config_aai(hdmi_drv, audio); return 0; @@ -557,11 +607,23 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio) void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable) { + struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver); + hdmi_dbg(hdmi_drv->dev, "[%s] %d\n", __FUNCTION__, enable); + if(enable == 0) { + hdmi_msk_reg(hdmi_dev, FC_GCP, m_FC_SET_AVMUTE, v_FC_SET_AVMUTE(1)); + } + else { + if(hdmi_drv->pwr_mode == LOWER_PWR) + rk3288_hdmi_set_pwr_mode(NORMAL); + hdmi_msk_reg(hdmi_dev, FC_GCP, m_FC_SET_AVMUTE, v_FC_SET_AVMUTE(0)); + } } int rk3288_hdmi_removed(struct hdmi *hdmi_drv) { + rk3288_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR); + dev_printk(KERN_INFO , hdmi_drv->dev , "Removed.\n"); return 0; } diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h index 74e494fe6a48..c1b38c2623fc 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h @@ -431,7 +431,8 @@ enum IT_CONTENT_TYPE { enum { AVI_COLOR_MODE_RGB = 0, AVI_COLOR_MODE_YCBCR422, - AVI_COLOR_MODE_YCBCR444 + AVI_COLOR_MODE_YCBCR444, + AVI_COLOR_MODE_YCBCR420 }; enum { AVI_COLORIMETRY_NO_DATA = 0, diff --git a/drivers/video/rockchip/hdmi/rk_hdmi.h b/drivers/video/rockchip/hdmi/rk_hdmi.h index ff20d4d900cb..3173275fe1f4 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi.h +++ b/drivers/video/rockchip/hdmi/rk_hdmi.h @@ -50,7 +50,8 @@ enum { enum { VIDEO_OUTPUT_RGB444 = 0, VIDEO_OUTPUT_YCBCR444, - VIDEO_OUTPUT_YCBCR422 + VIDEO_OUTPUT_YCBCR422, + VIDEO_OUTPUT_YCBCR420 }; enum {