rk3028a hdmi: add 3028a hdmi driver as compatible with rk616 hdmi
authorxuhuicong <xhc@rock-chips.com>
Wed, 24 Jul 2013 01:28:11 +0000 (09:28 +0800)
committerxuhuicong <xhc@rock-chips.com>
Wed, 24 Jul 2013 01:28:11 +0000 (09:28 +0800)
arch/arm/mach-rk2928/devices.c
drivers/video/rockchip/hdmi/chips/Kconfig
drivers/video/rockchip/hdmi/chips/rk616/Kconfig
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h

index ba673a7ac64f18301093461e2cd031eb45567ec0..e4cc759ecd00d9de7b5746969c26961bc348c44f 100644 (file)
@@ -567,7 +567,7 @@ static struct platform_device device_nand = {
        .num_resources  = ARRAY_SIZE(resources_nand),
 };
 #endif
-#ifdef CONFIG_HDMI_RK2928
+#if defined(CONFIG_HDMI_RK2928) || defined(CONFIG_HDMI_RK616)
 static struct resource resource_hdmi[] = {
        [0] = {
                .start = RK2928_HDMI_PHYS,
@@ -582,12 +582,17 @@ static struct resource resource_hdmi[] = {
 };
 
 static struct platform_device device_hdmi = {
+#ifdef CONFIG_HDMI_RK616
+        .name                           = "rk616-hdmi",
+#else
        .name                           = "rk2928-hdmi",
+#endif
        .id                                     = -1,
        .num_resources          = ARRAY_SIZE(resource_hdmi),
        .resource                       = resource_hdmi,
 };
 #endif
+
 #ifdef CONFIG_RGA_RK30
 static struct resource resource_rga[] = {
        [0] = {
@@ -797,7 +802,7 @@ static int __init rk2928_init_devices(void)
        rk_serial_debug_init(DEBUG_UART_BASE, IRQ_DEBUG_UART, IRQ_UART_SIGNAL, -1);
 #endif
        rk2928_init_i2s();
-#ifdef CONFIG_HDMI_RK2928
+#if defined(CONFIG_HDMI_RK2928) || defined(CONFIG_HDMI_RK616)
        platform_device_register(&device_hdmi);
 #endif
        platform_device_register(&device_arm_pmu);
index 69064120c15901e65b514753f78924b08bd0c92e..b8797ffdeab8f842346026dfeb6f312a6296385b 100755 (executable)
@@ -39,7 +39,8 @@ endif
 
 config  HDMI_RK616
         bool "RK616 HDMI support"
-        depends on MFD_RK616
+        depends on MFD_RK616 || ARCH_RK3026
+               default y
         help
            Support rk616 hdmi if you say y here
 
index dff44615ab976a18bb2abdc9026d0b55024be720..68cedb7eed0cc28435f53d06a793b68dc1ed9f18 100755 (executable)
@@ -1,6 +1,6 @@
 config HDCP_RK616
        bool "RK616 HDCP support"
-        depends on HDMI_RK616
+        depends on HDMI_RK616 || ARCH_RK3026
         default n
        help
          HDCP Interface. This adds the High Definition Content Protection Interface.
index a51139a1eb0076692a37717f080797da83d7bc60..df3ca6876b9b71d100476ca2e12a8947054c3c5f 100755 (executable)
@@ -38,29 +38,19 @@ static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
 {
        int i = 0;
        u32 val = 0;
-       struct mfd_rk616 *rk616 = s->private;
-       if(!rk616)
-       {
-               dev_err(rk616->dev,"no mfd rk616!\n");
-               return 0;
-       }
-
        seq_printf(s, "\n>>>rk616_ctl reg");
        for (i = 0; i < 16; i++) {
                seq_printf(s, " %2x", i);
        }
        seq_printf(s, "\n-----------------------------------------------------------------");
        
-       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);
-               if((i>>2)%16==0)
-                       seq_printf(s,"\n>>>rk616_ctl %2x:",i>>2);
+       for(i=0; i<= PHY_PRE_DIV_RATIO; i++) {
+                hdmi_readl(i, &val);
+               if(i%16==0)
+                       seq_printf(s,"\n>>>rk616_ctl %2x:", i);
                seq_printf(s," %02x",val);
 
        }
-       
        seq_printf(s, "\n-----------------------------------------------------------------\n");
        
        return 0;
@@ -68,24 +58,19 @@ static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
 
 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 { 
-       struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
        u32 reg;
        u32 val;
        char kbuf[25];
        if (copy_from_user(kbuf, buf, count))
                return -EFAULT;
        sscanf(kbuf, "%x%x", &reg, &val);
-        if ((reg < 0) || (reg > 0xed))
-        {
-                printk("it is no hdmi reg\n");
+        if ((reg < 0) || (reg > 0xed)) {
+                dev_info(hdmi->dev, "it is no hdmi reg\n");
                 return count;
         }
-       printk("/**********rk616 reg config******/");
-       printk("\n reg=%x val=%x\n", reg, val);
-
-       //sscanf(kbuf, "%x%x", &reg, &val);
-       dev_dbg(rk616->dev,"%s:reg:0x%04x val:0x%08x\n",__func__,reg, val);
-       rk616->write_dev(rk616, RK616_HDMI_BASE + (reg << 2), &val);
+       dev_info(hdmi->dev, "/**********rk616 reg config******/");
+       dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val);
+        hdmi_writel(reg, val);
 
        return count;
 }
@@ -166,10 +151,8 @@ static void hdmi_early_resume(struct early_suspend *h)
                // hdmi_irq();
                 rk616_hdmi_work();
        }
-
-        if (rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO) 
+        if (rk616_hdmi->rk616_drv && rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO) 
                 queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
-
        queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
        mutex_unlock(&hdmi->enable_mutex);
        return;
@@ -187,13 +170,13 @@ static void rk616_delay_work_func(struct work_struct *work)
                         rk616_hdmi_work();
                }
 
-                if (rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO) {
+                if (rk616_hdmi->rk616_drv && rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO) {
                         queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
                 }
        }
 }
 
-static void rk616_irq_work_func(struct work_struct *work)
+static void __maybe_unused rk616_irq_work_func(struct work_struct *work)
 {
        if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
                 rk616_hdmi_work();
@@ -202,29 +185,32 @@ static void rk616_irq_work_func(struct work_struct *work)
         enable_irq(hdmi->irq);
 }
 
-#if 1
 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
 {
         struct work_struct  *rk616_irq_work_struct;
+        struct rk616_hdmi *rk616_hdmi;
 
-        rk616_irq_work_struct  = dev_id;
-        disable_irq_nosync(hdmi->irq);
-       //printk(KERN_INFO "rk616_hdmi_irq irq triggered.\n");
-       queue_work(hdmi->workqueue, rk616_irq_work_struct);
+        rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
+        if(rk616_hdmi->rk616_drv) {
+                rk616_irq_work_struct  = dev_id;
+                disable_irq_nosync(hdmi->irq);
+                queue_work(hdmi->workqueue, rk616_irq_work_struct);
+        } else {
+                /* 3028a hdmi */
+                if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
+                        printk(KERN_INFO "line = %d, rk616_hdmi_irq irq triggered.\n", __LINE__);
+                        rk616_hdmi_work();
+                }
+        }
         return IRQ_HANDLED;
 }
-#endif
+
 static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
 {
        int ret;
         struct rk616_hdmi *rk616_hdmi;
-
-       struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent);
-       if(!rk616)
-       {
-               dev_err(&pdev->dev,"null mfd device rk616!\n");
-               return -ENODEV;
-       }
+        struct resource __maybe_unused *mem;
+        struct resource __maybe_unused *res;
 
         rk616_hdmi = devm_kzalloc(&pdev->dev, sizeof(*rk616_hdmi), GFP_KERNEL);
         if(!rk616_hdmi)
@@ -233,7 +219,18 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
                return -ENOMEM;
        }
         hdmi = &rk616_hdmi->g_hdmi;
-        rk616_hdmi->rk616_drv = rk616;
+
+#ifdef CONFIG_ARCH_RK3026
+       rk616_hdmi->rk616_drv = NULL;
+#else
+       rk616_hdmi->rk616_drv = dev_get_drvdata(pdev->dev.parent);
+       if(!(rk616_hdmi->rk616_drv))
+       {
+               dev_err(&pdev->dev,"null mfd device rk616!\n");
+               return -ENODEV;
+       }
+
+#endif
 
        hdmi->dev = &pdev->dev;
        platform_set_drvdata(pdev, hdmi);
@@ -251,7 +248,6 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
        hdmi->xscale = 100;
        hdmi->yscale = 100;
 
-       ret = rk616_hdmi_initial();
 
        hdmi_sys_init();
 
@@ -265,7 +261,6 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
        register_early_suspend(&hdmi->early_suspend);
 #endif
 
-       hdmi_register_display_sysfs(hdmi, NULL);
 #ifdef CONFIG_SWITCH
        hdmi->switch_hdmi.name="hdmi";
        switch_dev_register(&(hdmi->switch_hdmi));
@@ -277,39 +272,102 @@ static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
        INIT_DELAYED_WORK(&rk616_hdmi->rk616_delay_work, rk616_delay_work_func);
 
        /* get the IRQ */
-       if(rk616->pdata->hdmi_irq != INVALID_GPIO)
-       {
-               INIT_WORK(&rk616_hdmi->rk616_irq_work_struct, rk616_irq_work_func);
-               ret = gpio_request(rk616->pdata->hdmi_irq,"rk616_hdmi_irq");
-               if(ret < 0)
-               {
-                       dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
-               }
-               gpio_direction_input(rk616->pdata->hdmi_irq);
-               hdmi->irq = gpio_to_irq(rk616->pdata->hdmi_irq);
-               if(hdmi->irq <= 0) {
-                       dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
-                       ret = -ENXIO;
-                       goto err1;
-               }
-
-               /* request the IRQ */
+       // if(rk616->pdata->hdmi_irq != INVALID_GPIO)
+        
+#ifdef CONFIG_ARCH_RK3026
+        hdmi->hclk = clk_get(NULL,"pclk_hdmi");
+        if(IS_ERR(hdmi->hclk)) {
+                dev_err(hdmi->dev, "Unable to get hdmi hclk\n");
+                ret = -ENXIO;
+                goto err0;
+        }
+        clk_enable(hdmi->hclk);
+        
+        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+        if (!res) {
+                dev_err(hdmi->dev, "Unable to get register resource\n");
+                ret = -ENXIO;
+                goto err0;
+        }
+        hdmi->regbase_phy = res->start;
+        hdmi->regsize_phy = (res->end - res->start) + 1;
+        mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
+        if (!mem) {
+                dev_err(hdmi->dev, "failed to request mem region for hdmi\n");
+                ret = -ENOENT;
+                goto err0;
+        }
+        
+        printk("res->start = 0x%x\n, xhc-------res->end = 0x%x\n", res->start, res->end);
+        hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);
+        if (!hdmi->regbase) {
+                dev_err(hdmi->dev, "cannot ioremap registers\n");
+                ret = -ENXIO;
+                goto err1;
+        }
+        
+        // rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);
+        // rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);
+        // rk30_mux_api_set(GPIO0B7_HDMI_HOTPLUGIN_NAME, GPIO0B_HDMI_HOTPLUGIN);
+        iomux_set(HDMI_DDCSDA);
+        iomux_set(HDMI_DDCSCL);
+        iomux_set(HDMI_HOTPLUGIN);
+        
+        ret = rk616_hdmi_initial();
+        /* get the IRQ */
+        hdmi->irq = platform_get_irq(pdev, 0);
+        if(hdmi->irq <= 0) {
+                dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
+                hdmi->irq = 0;
+        } else {               
+                /* request the IRQ */
+                ret = request_irq(hdmi->irq, rk616_hdmi_irq, 0, dev_name(&pdev->dev), hdmi);
+                if (ret) {
+                        dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
+                        goto err1;
+                }
+        }
+#else
+        ret = rk616_hdmi_initial();
+        if(rk616_hdmi->rk616_drv->pdata->hdmi_irq != INVALID_GPIO) {               
+                INIT_WORK(&rk616_hdmi->rk616_irq_work_struct, rk616_irq_work_func);
+                ret = gpio_request(rk616_hdmi->rk616_drv->pdata->hdmi_irq,"rk616_hdmi_irq");
+                if(ret < 0) {
+                        dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
+                }
+                gpio_direction_input(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
+                hdmi->irq = gpio_to_irq(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
+                if(hdmi->irq <= 0) {
+                        dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
+                        ret = -ENXIO;
+                        goto err1;
+                }
+                
+                /* request the IRQ */
                 ret = request_irq(hdmi->irq, rk616_hdmi_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), &rk616_hdmi->rk616_irq_work_struct);
-               if (ret)
-               {
-                       dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
-                       goto err1;
-               }
-       } else {
-
+                if (ret) {
+                        dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
+                        goto err1;
+                }
+        } else {                
                 /* use roll polling method */
-               hdmi->irq = 0;
+                hdmi->irq = 0;
         }
+
+#endif
+       hdmi_register_display_sysfs(hdmi, NULL);
+
 #if defined(CONFIG_DEBUG_FS)
-       if(rk616->debugfs_dir)
-       {
-               debugfs_create_file("hdmi", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_hdmi_reg_fops);
-       }
+       if(rk616_hdmi->rk616_drv && rk616_hdmi->rk616_drv->debugfs_dir) {
+               debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->rk616_drv->debugfs_dir, rk616_hdmi->rk616_drv, &rk616_hdmi_reg_fops);
+       } else {
+                rk616_hdmi->debugfs_dir = debugfs_create_dir("rk616", NULL);
+                if (IS_ERR(rk616_hdmi->debugfs_dir)) {
+                        dev_err(hdmi->dev,"failed to create debugfs dir for rk616!\n");
+                } else {
+                        debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->debugfs_dir, rk616_hdmi, &rk616_hdmi_reg_fops);
+                }
+        }
 #endif
        // rk616_delay_work_func(NULL);
        queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, msecs_to_jiffies(0));
index c2a807abfe98f4c38286693d75dfed1c8164bff7..2d033fa6f33019f4c76bb62230737a7a40c53de0 100755 (executable)
@@ -32,6 +32,7 @@ struct rk616_hdmi {
         struct delayed_work     rk616_delay_work;
         struct work_struct      rk616_irq_work_struct;
         struct mfd_rk616        *rk616_drv;
+        struct dentry           *debugfs_dir;
 };
 
 #endif /* __RK30_HDMI_H__ */
index ad0c16f3516957eeb29de5d957927801abe5d88c..76db26bcd074c58f50a6dafdbd1b2738c8faea1c 100755 (executable)
@@ -7,14 +7,13 @@
 
 // static char edid_result = 0;
 
-
+#ifndef CONFIG_ARCH_RK3026
 static int rk616_set_polarity(struct mfd_rk616 * rk616, int vic)
 {
         u32 val;
         int ret;
         u32 hdmi_polarity_mask = (3<<14);
 
-        // printk("----------xhc---------vic = %d\n", vic);
         switch(vic)
         {
                 
@@ -48,7 +47,6 @@ static int rk616_hdmi_set_vif(rk_screen * screen,bool connect)
         struct rk616_hdmi *rk616_hdmi;
         rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
 
-
         if (connect) 
                 rk616_set_polarity(rk616_hdmi->rk616_drv, hdmi->vic); 
 
@@ -60,15 +58,18 @@ static int rk616_hdmi_init_pol_set(struct mfd_rk616 * rk616,int pol)
 {
        u32 val;
        int ret;
-       ret = rk616->read_dev(rk616,CRU_CFGMISC_CON,&val);
-       if(pol)
-               val &= 0xffffffdf;
-       else
-               val |= 0x20;
-       ret = rk616->write_dev(rk616,CRU_CFGMISC_CON,&val);
+        int int_pol_mask = (1 << 5);
+
+        if (pol) 
+                val = 0x0;
+        else
+                val = 0x20;
+        ret = rk616->write_dev_bits(rk616, CRU_CFGMISC_CON, int_pol_mask, &val);
 
        return 0;
 }
+#endif
+
 static inline void delay100us(void)
 {
        msleep(1);
@@ -358,7 +359,6 @@ static int rk616_hdmi_config_video(struct hdmi_video_para *vpara)
        value = mode->vsync_len;
        hdmi_writel(VIDEO_EXT_VDURATION, value & 0xFF);
 #endif
-        //rk616_set_polarity(rk616_hdmi->rk616_drv, vpara->vic); 
 
         if(vpara->output_mode == OUTPUT_HDMI) {
                rk616_hdmi_config_avi(vpara->vic, vpara->output_color);
@@ -368,19 +368,15 @@ static int rk616_hdmi_config_video(struct hdmi_video_para *vpara)
                hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); 
        }
        
-#if 1
-        hdmi_writel(0xed, 0x0f);
-        hdmi_writel(0xe7, 0x96);
-#else
-       if(hdmi->tmdsclk >= 148500000) {
-               hdmi_writel(0xed, 0xc);
-               hdmi_writel(0xe7, 0x78);
-       }
-       else {
-               hdmi_writel(0xed, 0x3);
-               hdmi_writel(0xe7, 0x1e);
-       }
-#endif
+        // if(rk616_hdmi->rk616_drv) {     
+        if (hdmi->set_vif) {
+                hdmi_writel(0xed, 0x0f);
+                hdmi_writel(0xe7, 0x96);
+        } else {        // rk3028a
+                hdmi_writel(0xed, 0x1e);
+                hdmi_writel(0xe7, 0x2c);
+                hdmi_writel(0xe8, 0x01);
+        }
        return 0;
 }
 
@@ -520,6 +516,7 @@ void rk616_hdmi_work(void)
        u32 interrupt = 0;
         // int value = 0;
 
+        
         hdmi_readl(INTERRUPT_STATUS1,&interrupt);
         if(interrupt){
                 hdmi_writel(INTERRUPT_STATUS1, interrupt);
@@ -576,11 +573,16 @@ int rk616_hdmi_initial(void)
        hdmi->config_audio = rk616_hdmi_config_audio;
        hdmi->detect_hotplug = rk616_hdmi_detect_hotplug;
        hdmi->read_edid = rk616_hdmi_read_edid;
-       hdmi->set_vif = rk616_hdmi_set_vif;
-       
-       rk616_hdmi_reset();
 
+#ifdef CONFIG_ARCH_RK3026
+        rk3028_hdmi_reset_pclk();
+        rk616_hdmi_reset();
+#else
+        hdmi->set_vif = rk616_hdmi_set_vif;
+        rk616_hdmi_reset();
        rk616_hdmi_init_pol_set(rk616_hdmi->rk616_drv, 0);
+#endif
+        
        if(hdmi->hdcp_power_on_cb)
                rc = hdmi->hdcp_power_on_cb();
 
index c3b98ebd3e121aae3ec90d4337507f5e8bb4e894..c998933c0bb3ff8f53f33970a3fe8a24d62bc246 100755 (executable)
@@ -285,6 +285,7 @@ enum {
 #define PHY_PRE_DIV_RATIO              0xed
        #define v_PRE_DIV_RATIO(n)      (n&1f)
 
+#ifndef CONFIG_ARCH_RK3026
 static inline int hdmi_readl(u16 offset, u32 *val)
 {
         int ret;
@@ -314,6 +315,37 @@ static inline int hdmi_msk_reg(u16 offset, u32 msk, u32 val)
         ret = rk616_hdmi->rk616_drv->write_dev_bits(rk616_hdmi->rk616_drv, (RK616_HDMI_BASE + ((offset)<<2)), msk, &val);
         return ret;
 }
+#else
+
+static inline int hdmi_readl(u16 offset, u32 *val)
+{
+        int ret = 0;
+       *val = readl_relaxed(hdmi->regbase + (offset) * 0x04);
+        return ret;
+}
+
+static inline int hdmi_writel(u16 offset, u32 val)
+{
+        int ret = 0;
+        writel_relaxed(val, hdmi->regbase + (offset) * 0x04);
+        return ret;
+}
+
+static inline int hdmi_msk_reg(u16 offset, u32 msk, u32 val)
+{
+        int ret = 0;
+        u32 temp;
+        temp = readl_relaxed(hdmi->regbase + (offset) * 0x04) & (0xFF - (msk));
+        writel_relaxed(temp | ( (val) & (msk) ),  hdmi->regbase + (offset) * 0x04);
+        return ret;
+}
+static inline void rk3028_hdmi_reset_pclk(void)
+{
+        writel_relaxed(0x00010001,RK2928_CRU_BASE+ 0x128);
+        msleep(100);
+        writel_relaxed(0x00010000, RK2928_CRU_BASE + 0x128);
+}
+#endif
 
 extern int rk616_hdmi_initial(void);
 extern void rk616_hdmi_work(void);