HDMI: optimize rk3288 hdmi driver code

This commit is contained in:
zwl
2014-03-11 16:14:11 +08:00
parent e3a0fd5f7d
commit fa14d67d10
5 changed files with 84 additions and 11 deletions

View File

@@ -27,9 +27,16 @@
#include <linux/seq_file.h>
#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

View File

@@ -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__ */

View File

@@ -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);
//hdmi_writel(hdmi_dev, FC_AUDICONF0, m_FC_CHN_CNT | m_FC_CODING_TYEP, v_FC_CHN_CNT(audio->channel) | v_FC_CODING_TYEP());
//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));
//TODO Daisen wait to add
//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));
//Set Channel Allocation
hdmi_writel(hdmi_dev, FC_AUDICONF2, 0x00);
//Set LFEPBL<42><4C>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;
}

View File

@@ -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,

View File

@@ -50,7 +50,8 @@ enum {
enum {
VIDEO_OUTPUT_RGB444 = 0,
VIDEO_OUTPUT_YCBCR444,
VIDEO_OUTPUT_YCBCR422
VIDEO_OUTPUT_YCBCR422,
VIDEO_OUTPUT_YCBCR420
};
enum {