mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
HDMI: optimize rk3288 hdmi driver
This commit is contained in:
@@ -147,12 +147,13 @@ static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
|
||||
struct rk_screen screen;
|
||||
|
||||
rk_fb_get_prmry_screen(&screen);
|
||||
hdmi_dev->lcdc_id = 0; //hdmi is extend as default,TODO modify if hdmi is primary
|
||||
hdmi_dev->lcdc_id = (screen.lcdc_id == 0) ? 1 : 0; //hdmi is extend as default,TODO modify if hdmi is primary
|
||||
printk("HDMI Source Lcdc id = %d\n", hdmi_dev->lcdc_id);
|
||||
grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id), RK3288_GRF_SOC_CON6); //lcdc source select
|
||||
//if(hdmi_dev->lcdc_id == 0)
|
||||
if(hdmi_dev->lcdc_id == 0)
|
||||
hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
|
||||
//else
|
||||
//hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
|
||||
else
|
||||
hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
|
||||
if(IS_ERR(hdmi_drv->lcdc))
|
||||
{
|
||||
dev_err(hdmi_drv->dev, "can not connect to video source lcdc\n");
|
||||
@@ -260,7 +261,7 @@ static int rk3288_hdmi_probe(struct platform_device *pdev)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
ret = request_irq(dev_drv->irq, hdmi_irq, 0, dev_name(hdmi_dev->dev), dev_drv);
|
||||
ret = devm_request_irq(hdmi_dev->dev, dev_drv->irq, hdmi_irq, 0, dev_name(hdmi_dev->dev), dev_drv);
|
||||
if (ret) {
|
||||
dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
|
||||
goto err2;
|
||||
|
||||
@@ -49,23 +49,23 @@ static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
|
||||
if(hdmi_drv->pwr_mode == mode)
|
||||
return;
|
||||
|
||||
hdmi_dbg(hdmi_drv->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__, hdmi_drv->pwr_mode, mode);
|
||||
hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n",__FUNCTION__, hdmi_drv->pwr_mode, mode);
|
||||
printk("%s change pwr_mode %d --> %d\n",__FUNCTION__, hdmi_drv->pwr_mode, mode);
|
||||
switch(mode)
|
||||
{
|
||||
case NORMAL:
|
||||
hdmi_writel(hdmi_dev, A_HDCPCFG0, 0x21); //cfg to bypass hdcp data encry
|
||||
hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_ENCRYPT_BYPASS, v_ENCRYPT_BYPASS(1)); //cfg to bypass hdcp data encrypt
|
||||
hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0x00);
|
||||
hdmi_writel(hdmi_dev, MC_SWRSTZREQ_2, 0x00);
|
||||
hdmi_writel(hdmi_dev, MC_CLKDIS, 0x00);
|
||||
//rk3288_hdmi_av_mute(hdmi_drv, 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));
|
||||
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_dbg(hdmi_drv->dev, "unkown hdmi pwr mode %d\n",mode);
|
||||
}
|
||||
hdmi_drv->pwr_mode = mode;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
|
||||
}
|
||||
}
|
||||
|
||||
hdmi_dbg(hdmi_drv->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
|
||||
hdmi_err(hdmi_drv->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_ad
|
||||
}
|
||||
msleep(100);
|
||||
#endif
|
||||
msleep(1000);
|
||||
msleep(500);
|
||||
return 0; //delete
|
||||
}
|
||||
|
||||
@@ -456,45 +456,33 @@ static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_ad
|
||||
static int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
|
||||
{
|
||||
int stat = 0, i = 0;
|
||||
//char color_depth = COLOR_DEPTH_24BIT;//COLOR_DEPTH_24BIT_DEFAULT;
|
||||
char pix_repet = NO_PIXEL_REPET;
|
||||
const struct phy_mpll_config_tab *phy_mpll = NULL;
|
||||
struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
|
||||
|
||||
hdmi_writel(hdmi_dev, PHY_I2CM_DIV, 0x03);
|
||||
hdmi_msk_reg(hdmi_dev, PHY_I2CM_DIV, m_PHY_I2CM_FAST_STD, v_PHY_I2CM_FAST_STD(0));
|
||||
|
||||
//power on PHY
|
||||
hdmi_writel(hdmi_dev, PHY_CONF0, 0x3a);
|
||||
//hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG, v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
|
||||
|
||||
//reset PHY
|
||||
hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
|
||||
//the resolution that we used is no pixel repet,refer to the CEA-861 specification.
|
||||
//hdmi_writel(hdmi_dev, VP_PR_CD, v_COLOR_DEPTH(color_depth) | v_DESIRED_PR_FACTOR(pix_repet));
|
||||
msleep(5);
|
||||
hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
|
||||
|
||||
//Set slave address as PHY GEN2 address
|
||||
//hdmi_msk_reg(hdmi_dev, PHY_TST0, m_TEST_CLR_SIG, 1 << 5);
|
||||
hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_GEN2_ADDR); //TODO Daisen wait to modify
|
||||
//hdmi_msk_reg(hdmi_dev, PHY_TST0, m_TEST_CLR_SIG, 0 << 5);
|
||||
#if 0
|
||||
rk3288_hdmi_write_phy(hdmi_dev, 0x13, 0x0000); /* PLLPHBYCTRL */
|
||||
rk3288_hdmi_write_phy(hdmi_dev, 0x17, 0x0006);
|
||||
/* RESISTANCE TERM 133Ohm Cfg */
|
||||
rk3288_hdmi_write_phy(hdmi_dev, 0x19, 0x0005); /* TXTERM */
|
||||
/* REMOVE CLK TERM */
|
||||
rk3288_hdmi_write_phy(hdmi_dev, 0x05, 0x8000); /* CKCALCTRL */
|
||||
#endif
|
||||
hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_GEN2_ADDR);
|
||||
|
||||
//config the required PHY I2C register
|
||||
phy_mpll = get_phy_mpll_tab(hdmi_drv->tmdsclk, pix_repet, 8);
|
||||
phy_mpll = get_phy_mpll_tab(hdmi_drv->tmdsclk, pix_repet, 8); //TODO Modify if color depth is 24bit
|
||||
if(phy_mpll) {
|
||||
rk3288_hdmi_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG, v_PREP_DIV(phy_mpll->prep_div) | v_TMDS_CNTRL(phy_mpll->tmdsmhl_cntrl) | v_OPMODE(phy_mpll->opmode) |
|
||||
v_FBDIV2_CNTRL(phy_mpll->fbdiv2_cntrl) | v_FBDIV1_CNTRL(phy_mpll->fbdiv1_cntrl) | v_REF_CNTRL(phy_mpll->ref_cntrl) | v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
|
||||
stat = rk3288_hdmi_read_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG);
|
||||
rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL, v_MPLL_PROP_CNTRL(phy_mpll->prop_cntrl) | v_MPLL_INT_CNTRL(phy_mpll->int_cntrl));
|
||||
stat = rk3288_hdmi_read_phy(hdmi_dev, PHYTX_PLLCURRCTRL);
|
||||
rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL, v_MPLL_GMP_CNTRL(phy_mpll->gmp_cntrl));
|
||||
stat = rk3288_hdmi_read_phy(hdmi_dev, PHYTX_PLLGMPCTRL);
|
||||
}
|
||||
//rk3288_hdmi_write_phy(hdmi_dev, 0x09, 0x8009);
|
||||
//rk3288_hdmi_write_phy(hdmi_dev, 0x0E, 0x0210);
|
||||
|
||||
//power on PHY
|
||||
hdmi_writel(hdmi_dev, PHY_CONF0, 0x6e);
|
||||
//hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
|
||||
@@ -720,13 +708,12 @@ static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *
|
||||
|
||||
int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
|
||||
{
|
||||
//if(hdmi_drv->pwr_mode == LOWER_PWR)
|
||||
rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
|
||||
rk3288_hdmi_av_mute(hdmi_drv, 1);
|
||||
|
||||
vpara->output_color = VIDEO_OUTPUT_RGB444;
|
||||
//Color space convert
|
||||
//if (rk3288_hdmi_video_forceOutput(hdmi_drv, 1) < 0)
|
||||
//return -1;
|
||||
if (rk3288_hdmi_video_forceOutput(hdmi_drv, 1) < 0)
|
||||
return -1;
|
||||
if (rk3288_hdmi_video_frameComposer(hdmi_drv, vpara) < 0)
|
||||
return -1;
|
||||
if (rk3288_hdmi_video_packetizer(hdmi_drv, vpara) < 0)
|
||||
@@ -908,19 +895,18 @@ 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) {
|
||||
//rk3288_hdmi_av_mute(hdmi_drv, 1);
|
||||
rk3288_hdmi_av_mute(hdmi_drv, 1);
|
||||
}
|
||||
else {
|
||||
//if(hdmi_drv->pwr_mode == LOWER_PWR)
|
||||
if(hdmi_drv->pwr_mode == LOWER_PWR)
|
||||
rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
|
||||
|
||||
/* disable blue screen transmission after turning on all necessary blocks*/
|
||||
//rk3288_hdmi_video_forceOutput(hdmi_drv, 0);
|
||||
//rk3288_hdmi_av_mute(hdmi_drv, 0);
|
||||
rk3288_hdmi_video_forceOutput(hdmi_drv, 0);
|
||||
rk3288_hdmi_av_mute(hdmi_drv, 0);
|
||||
}
|
||||
hdmi_writel(hdmi_dev, A_HDCPCFG0, 0x21);
|
||||
}
|
||||
|
||||
int rk3288_hdmi_insert(struct hdmi *hdmi_drv)
|
||||
@@ -928,7 +914,7 @@ int rk3288_hdmi_insert(struct hdmi *hdmi_drv)
|
||||
struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
|
||||
|
||||
/* report HPD state to HDCP (after configuration) */
|
||||
//hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
|
||||
hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -944,6 +930,7 @@ int rk3288_hdmi_initial(struct hdmi *hdmi_drv)
|
||||
{
|
||||
int rc = HDMI_ERROR_SUCESS;
|
||||
|
||||
hdmi_drv->pwr_mode = LOWER_PWR;
|
||||
hdmi_drv->insert = rk3288_hdmi_insert;
|
||||
hdmi_drv->remove = rk3288_hdmi_removed;
|
||||
hdmi_drv->control_output = rk3288_hdmi_control_output;
|
||||
@@ -965,7 +952,6 @@ irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
int phy_int = 0, i2cm_int = 0, phy_i2cm_int = 0, cec_int = 0;
|
||||
int aud_dma_int = 0;
|
||||
|
||||
printk(">>>>>>%s:\n",__FUNCTION__);
|
||||
//read interrupt
|
||||
phy_int = hdmi_readl(hdmi_dev, IH_PHY_STAT0);
|
||||
i2cm_int = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
|
||||
@@ -983,7 +969,7 @@ irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
//hdmi_writel(hdmi_dev, A_APIINTCLR, hdcp_int);
|
||||
|
||||
//HPD
|
||||
if(phy_int & m_HPD) {
|
||||
if((phy_int & m_HPD) || ((phy_int & 0x3c) == 0x3c)) {
|
||||
if(hdmi_drv->state == HDMI_SLEEP)
|
||||
hdmi_drv->state = WAIT_HOTPLUG;
|
||||
queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, msecs_to_jiffies(5));
|
||||
|
||||
@@ -871,6 +871,7 @@ static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
|
||||
v |= (lcdc_dev->id << 3);
|
||||
break;
|
||||
case SCREEN_HDMI:
|
||||
face = OUT_RGB_AAA;
|
||||
mask = m_HDMI_OUT_EN;
|
||||
val = v_HDMI_OUT_EN(1);
|
||||
/*v = 1 << (4+16);
|
||||
|
||||
Reference in New Issue
Block a user