From 8987772dd90195d6a6ad8194b7ab1ae33cd43810 Mon Sep 17 00:00:00 2001 From: yzq Date: Sat, 20 Apr 2013 20:47:00 +0800 Subject: [PATCH] mfd:rk616:hdmi: display ok --- .../rockchip/hdmi/chips/rk616/rk616_hdmi.c | 43 +++-- .../rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c | 153 +++++++++--------- .../rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h | 2 +- 3 files changed, 110 insertions(+), 88 deletions(-) diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c index 7bed90d0d546..a46475ec7cb0 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c @@ -29,19 +29,15 @@ struct hdmi *hdmi = NULL; struct mfd_rk616 *g_rk616_hdmi = NULL; +struct delayed_work g_irq_work; -extern irqreturn_t hdmi_irq(int irq, void *priv); +extern void hdmi_irq(void); extern void hdmi_work(struct work_struct *work); extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name); extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent); extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi); -int set_hdmi_status(void) -{ - hdmi->hotplug = HDMI_HPD_ACTIVED; -} - #if defined(CONFIG_DEBUG_FS) static int rk616_hdmi_reg_show(struct seq_file *s, void *v) { @@ -54,10 +50,16 @@ static int rk616_hdmi_reg_show(struct seq_file *s, void *v) return 0; } + + seq_printf(s,"------>gpio = %d \n",gpio_get_value(rk616->pdata->hdmi_irq)); for(i=0;i<= (PHY_PRE_DIV_RATIO << 2);i+=4) { rk616->read_dev(rk616,RK616_HDMI_BASE + i,&val); - seq_printf(s,"reg%02x>>0x%08x\n",(i>>2),val); + //seq_printf(s,"reg%02x>>0x%08x\n",(i>>2),val); + if((i>>2)%16==0) + seq_printf(s,"\n>>>rk610_ctl %x:",i>>2); + seq_printf(s," %2x",val); + } return 0; @@ -140,7 +142,7 @@ static void hdmi_early_resume(struct early_suspend *h) mutex_lock(&hdmi->enable_mutex); hdmi->suspend = 0; - rk616_hdmi_initial(); +// rk616_hdmi_initial(); if(hdmi->enable) { enable_irq(hdmi->irq); } @@ -148,7 +150,23 @@ static void hdmi_early_resume(struct early_suspend *h) return; } #endif - +static void rk616_irq_work_func(struct work_struct *work) +{ + if(hdmi->suspend == 0) { + if(hdmi->enable == 1) { + hdmi_irq(); + } + queue_delayed_work(hdmi->workqueue, &g_irq_work, 100); + } +} +#if 0 +static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id) +{ + printk(KERN_INFO "rk616_hdmi_irq irq triggered.\n"); + schedule_work(&g_irq_work); + return IRQ_HANDLED; +} +#endif static int __devinit rk616_hdmi_probe (struct platform_device *pdev) { int ret; @@ -211,6 +229,7 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev) /* get the IRQ */ if(rk616->pdata->hdmi_irq != INVALID_GPIO) { + INIT_DELAYED_WORK(&g_irq_work, rk616_irq_work_func); ret = gpio_request(rk616->pdata->hdmi_irq,"rk616_hdmi_irq"); if(ret < 0) { @@ -224,13 +243,15 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev) goto err1; } +#if 0 /* request the IRQ */ - ret = request_threaded_irq(hdmi->irq,NULL,hdmi_irq,IRQF_TRIGGER_FALLING,dev_name(&pdev->dev), hdmi); + ret = request_irq(hdmi->irq,rk616_hdmi_irq,IRQF_TRIGGER_FALLING,dev_name(&pdev->dev), hdmi); if (ret) { dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret); goto err1; } +#endif } #if defined(CONFIG_DEBUG_FS) if(rk616->debugfs_dir) @@ -238,6 +259,8 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev) debugfs_create_file("rk616-hdmi", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_hdmi_reg_fops); } #endif + rk616_irq_work_func(NULL); + //queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); dev_info(hdmi->dev, "rk616 hdmi probe success.\n"); return 0; err1: diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c index 3fce867906da..cbe550488c22 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c @@ -44,11 +44,12 @@ static void rk616_hdmi_sys_power_down(void) static void rk616_hdmi_set_pwr_mode(int mode) { - hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__); if(hdmi->pwr_mode == mode) return; + hdmi_dbg(hdmi->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__,hdmi->pwr_mode,mode); switch(mode){ case NORMAL: + hdmi_dbg(hdmi->dev,"%s change pwr_mode NORMAL\n",__FUNCTION__,hdmi->pwr_mode,mode); rk616_hdmi_sys_power_down(); HDMIWrReg(PHY_DRIVER,0xaa); HDMIWrReg(PHY_PRE_EMPHASIS,0x0f); @@ -64,6 +65,7 @@ static void rk616_hdmi_set_pwr_mode(int mode) analog_sync = 1; break; case LOWER_PWR: + hdmi_dbg(hdmi->dev,"%s change pwr_mode LOWER_PWR\n",__FUNCTION__,hdmi->pwr_mode,mode); rk616_hdmi_av_mute(0); rk616_hdmi_sys_power_down(); HDMIWrReg(PHY_DRIVER,0x00); @@ -98,68 +100,51 @@ int rk616_hdmi_detect_hotplug(void) #define HDMI_DDC_CONFIG (HDMI_SYS_FREG_CLK>>2)/HDMI_SCL_RATE #define DDC_BUS_FREQ_L 0x4b #define DDC_BUS_FREQ_H 0x4c +#define EDID_BLOCK_SIZE 128 -int rk616_hdmi_read_edid(int block, unsigned char *buff) +int rk616_hdmi_read_edid(u8 block, u8 * buf) { - int value, ret = -1, ddc_bus_freq = 0; - char interrupt = 0, trytime = 2; - unsigned long flags; - - hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block); - spin_lock_irqsave(&hdmi->irq_lock, flags); - edid_result = 0; - spin_unlock_irqrestore(&hdmi->irq_lock, flags); - //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz. - //Set DDC I2C CLK which devided from DDC_CLK to 100KHz. - - ddc_bus_freq = HDMI_DDC_CONFIG; - HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF); - HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF); - - // Enable edid interrupt - HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG | m_INT_EDID_READY); - - while(trytime--) { - // Config EDID block and segment addr - HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80); - HDMIWrReg(EDID_SEGMENT_POINTER, block/2); - - value = 10; - while(value--) - { - spin_lock_irqsave(&hdmi->irq_lock, flags); - interrupt = edid_result; - edid_result = 0; - spin_unlock_irqrestore(&hdmi->irq_lock, flags); - if(interrupt & (m_INT_EDID_READY)) - break; - msleep(10); - } - hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value); - if(interrupt & m_INT_EDID_READY) - { - for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++) - HDMIRdReg(EDID_FIFO_ADDR,(buff+value)); - ret = 0; - - hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__); -#ifdef HDMI_DEBUG - for(value = 0; value < 128; value++) { - printk("%02x ,", buff[value]); - if( (value + 1) % 16 == 0) - printk("\n"); - } + u32 c = 0; + int ret = 0,i; + u8 Segment = 0; + u8 Offset = 0; + if(block%2) + Offset = EDID_BLOCK_SIZE; + if(block/2) + Segment = 1; + printk("EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int) Segment, (int) block, (int) Offset); + //set edid fifo first addr + c = 0x00; + HDMIWrReg(0x4f,0); + //set edid word address 00/80 + c = Offset; + HDMIWrReg(0x4e, c); + //set edid segment pointer + c = Segment; + HDMIWrReg(0x4d, c); + + //enable edid interrupt +// c=0xc6; +// HDMIWrReg(0xc0, c); + //wait edid interrupt +#if 0 + msleep(10); + printk("Interrupt generated\n"); + c=0x00; + ret = HDMIRdReg(0xc1, &c); + printk("Interrupt reg=%x \n",c); + //clear EDID interrupt reg + c=0x04; + HDMIWrReg(0xc1, c); #endif - break; - }else - hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__); - - hdmi_dbg(hdmi->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime); - msleep(100); + for(i=0; i >>%d:",i); + printk("%02x ",c); } - // Disable edid interrupt - HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG); -// msleep(100); return ret; } @@ -283,10 +268,12 @@ static int rk616_hdmi_config_video(struct hdmi_video_para *vpara) } if(hdmi->tmdsclk >= 148500000) { - HDMIWrReg(0xe3, 0x4f); + HDMIWrReg(0xed, 0xc); + HDMIWrReg(0xe7, 0x78); } else { - HDMIWrReg(0xe3, 0x0f); + HDMIWrReg(0xed, 0x3); + HDMIWrReg(0xe7, 0x1e); } return 0; } @@ -420,33 +407,40 @@ int rk616_hdmi_removed(void) } -irqreturn_t hdmi_irq(int irq, void *priv) +void hdmi_irq(void) { + static int hpd = 0; u32 interrupt1 = 0; unsigned long flags; - spin_lock_irqsave(&hdmi->irq_lock,flags); - HDMIRdReg(INTERRUPT_STATUS1,&interrupt1); - HDMIWrReg(INTERRUPT_STATUS1, interrupt1); + int i=0; + + int value = 0; + HDMIRdReg(HDMI_STATUS,&value); + //spin_lock(&hdmi->irq_lock,flags); +// HDMIRdReg(INTERRUPT_STATUS1,&interrupt1); +// HDMIWrReg(INTERRUPT_STATUS1, interrupt1); - if(interrupt1 & m_INT_HOTPLUG ){ + if((value & m_HOTPLUG)&& hpd == 0){ if(hdmi->state == HDMI_SLEEP) hdmi->state = WAIT_HOTPLUG; if(hdmi->pwr_mode == LOWER_PWR) rk616_hdmi_set_pwr_mode(NORMAL); queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); - }else if(interrupt1 & m_INT_EDID_READY) { - edid_result = interrupt1; - }else if(hdmi->state == HDMI_SLEEP) { - hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n"); + hpd = 1; + }else if ((value & m_HOTPLUG)== 0 && hpd == 1 ){ + queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); + hpd = 0; + } + + if(hdmi->state == HDMI_SLEEP) { +// hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n"); rk616_hdmi_set_pwr_mode(LOWER_PWR); } #if 0 if(hdmi->hdcp_irq_cb) hdmi->hdcp_irq_cb(interrupt2); #endif - spin_unlock_irqrestore(&hdmi->irq_lock,flags); - printk("int statu1:0x%08x\n",interrupt1); - return IRQ_HANDLED; + //spin_unlock(&hdmi->irq_lock,flags); } static void rk616_hdmi_reset(void) @@ -458,17 +452,22 @@ static void rk616_hdmi_reset(void) delay100us(); HDMIMskReg(SYS_CTRL,m_RST_ANALOG,v_NOT_RST_ANALOG); delay100us(); - msk = m_REG_CLK_INV | m_VCLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL; - val = v_REG_CLK_INV| v_VCLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON |v_INT_POL_HIGH; + msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL; + val = v_REG_CLK_INV | v_REG_CLK_SOURCE_TMDS | v_PWR_ON |v_INT_POL_HIGH; HDMIMskReg(SYS_CTRL,msk,val); - rk616_hdmi_set_pwr_mode(LOWER_PWR); + HDMIWrReg(INTERRUPT_MASK1,0x80);//m_INT_HOTPLUG); + val = 0; + HDMIRdReg(INTERRUPT_MASK1,&val); + //rk616_hdmi_set_pwr_mode(LOWER_PWR); + rk616_hdmi_set_pwr_mode(NORMAL); + printk(">>>%s mask = %x\n",__func__,val); } int rk616_hdmi_initial(void) { int rc = HDMI_ERROR_SUCESS; - hdmi->pwr_mode = NORMAL; + hdmi->pwr_mode = LOWER_PWR; hdmi->remove = rk616_hdmi_removed ; hdmi->control_output = rk616_hdmi_control_output; hdmi->config_video = rk616_hdmi_config_video; diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h index dc8d65a15db0..6b8d63b31d2a 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h @@ -217,7 +217,7 @@ enum { #define INTERRUPT_MASK1 0xc0 #define INTERRUPT_STATUS1 0xc1 #define m_INT_HOTPLUG (1 << 7) - #define m_INT_ACTIVE_VSYNC (1 << 6) + #define m_INT_ACTIVE_VSYNC (1 << 5) #define m_INT_EDID_READY (1 << 2) #define INTERRUPT_MASK2 0xc2 -- 2.34.1