From 7df9c83c10a8bd6aedb931d5993d4514f06dd5f8 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 3 Aug 2010 11:28:11 +0800 Subject: [PATCH] Simplified power management --- .../staging/rk2818/rk2818_dsp/rk2818_dsp.c | 124 ++++++++++-------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/drivers/staging/rk2818/rk2818_dsp/rk2818_dsp.c b/drivers/staging/rk2818/rk2818_dsp/rk2818_dsp.c index 92c7287cd11f..06143994e805 100755 --- a/drivers/staging/rk2818/rk2818_dsp/rk2818_dsp.c +++ b/drivers/staging/rk2818/rk2818_dsp/rk2818_dsp.c @@ -51,10 +51,9 @@ #endif #define USE_PLL_REG 0 //ÊÇ·ñÖ±½Ó¿ØÖÆPLL¼Ä´æÆ÷ - -#define CLOSE_CLK_GATE 1 //ÊÍ·ÅDSPʱÊÇ·ñÁ¬clock gateÒ»Æð¹Øµô - -#define CONFIG_CHIP_RK2818 +#define ENTER_SLOW 0 //ÊÇ·ñ²»Ê¹ÓÃDSPµÄʱºòÁ¢¼´½øÈëSLOW MODE(DSP PLL BYPASS) +#define FIXED_REQ 560 //ʹÓù̶¨ÆµÂÊÖµ, 0Ϊ½ûÓà +#define CLOSE_CLK_GATE 0 //ÊÍ·ÅDSPʱÊÇ·ñÁ¬clock gateÒ»Æð¹Øµô struct rk28dsp_inf { struct miscdevice miscdev; @@ -64,6 +63,8 @@ struct rk28dsp_inf { void *pmu_base; void *l1_dbase; void *l2_idbase; + void *scu_base; + void *regfile_base; int irq0; int irq1; @@ -164,17 +165,14 @@ static DECLARE_MUTEX(sem); static int rcv_quit = 0; -static int video_type = 0;//h264:1 ,rv40:2 , other: 0. void dsp_powerctl(int ctl, int arg); + //need reset reg value when finishing the video play static void resetRegValueForVideo() { #ifdef CONFIG_CHIP_RK2818 - void * r1 = (void *)ioremap(APB_SCU_BASE, 0x60); - void * r3 = (void *)ioremap(APB_REG_FILE_BASE, 0x60); - struct rk28dsp_inf *inf = g_inf; if(!inf) return; //disable the AXI bus @@ -183,31 +181,23 @@ static void resetRegValueForVideo() //__raw_writel((__raw_readl(r3+0x14) & (~0x20002000)) , r3+0x14); if(video_type) { - dsp_powerctl(DPC_SLEEP, 0); - inf->dsp_status = DS_SLEEP; - - - __raw_writel((__raw_readl(r1+0x20) | (1<<25)) , r1+0x20); + __raw_writel((__raw_readl(inf->scu_base+0x20) | (1<<25)) , inf->scu_base+0x20); if(video_type == 2) { //mdelay(10); - __raw_writel((__raw_readl(r1+0x1c) | (0x400)) , r1+0x1c); - printk("close rv40 hardware advice\n"); + __raw_writel((__raw_readl(inf->scu_base+0x1c) | (0x400)) , inf->scu_base+0x1c); + dspprintk("close rv40 hardware advice\n"); } else { - __raw_writel((__raw_readl(r1+0x20) | (1<<20)) , r1+0x20); - printk("close h264 hardware advice\n"); + __raw_writel((__raw_readl(inf->scu_base+0x20) | (1<<20)) , inf->scu_base+0x20); + dspprintk("close h264 hardware advice\n"); } video_type = 0; } - - //mdelay(1); - iounmap((void __iomem *)(r1)); - iounmap((void __iomem *)(r3)); #endif - return; + return; } //add by Charles Chen for test 281x play RMVB static void setRegValueForVideo(unsigned long type) @@ -219,46 +209,42 @@ static void setRegValueForVideo(unsigned long type) µÈ´ýһЩʱ¼äÔÙÓëÉÏ ¡«0x00000110 0x18019018 »òÉÏ 0x00200000 */ - void * r1 = (void *)ioremap(APB_SCU_BASE, 0x60); - //void * r2 = (void *)ioremap(APB_SCU_BASE, 0x28); - void * r3 = (void *)ioremap(APB_REG_FILE_BASE, 0x60); + struct rk28dsp_inf *inf = g_inf; + if(!inf) return; video_type = 1; //axi bus - __raw_writel((__raw_readl(r1+0x20) | (0x08000000)) , r1+0x20); + __raw_writel((__raw_readl(inf->scu_base+0x20) | (0x08000000)) , inf->scu_base+0x20); //mc dma - __raw_writel((__raw_readl(r1+0x20) & ~(1<<25)) , r1+0x20); + __raw_writel((__raw_readl(inf->scu_base+0x20) & ~(1<<25)) , inf->scu_base+0x20); //printk("------->0x18018020 value 0x%08x\n",__raw_readl(r1+0x20)); if(!type) { video_type ++; //rv deblocking clock - __raw_writel((__raw_readl(r1+0x1c) & (~0x400)) , r1+0x1c); + __raw_writel((__raw_readl(inf->scu_base+0x1c) & (~0x400)) , inf->scu_base+0x1c); mdelay(1); - __raw_writel((__raw_readl(r1+0x28) | (0x00000100)) , r1+0x28); + __raw_writel((__raw_readl(inf->scu_base+0x28) | (0x00000100)) , inf->scu_base+0x28); mdelay(5); - __raw_writel((__raw_readl(r1+0x28) & (~0x00000100)) , r1+0x28); + __raw_writel((__raw_readl(inf->scu_base+0x28) & (~0x00000100)) , inf->scu_base+0x28); //rv deblocking bridge select - __raw_writel((__raw_readl(r3+0x14) | (0x20002000)) , r3+0x14); + __raw_writel((__raw_readl(inf->regfile_base+0x14) | (0x20002000)) , inf->regfile_base+0x14); - printk("%s this is rm 9 video\n",__func__); + dspprintk("%s this is rm 9 video\n",__func__); } else { //h264 hardware - __raw_writel((__raw_readl(r1+0x20) & ~(1<<20)) , r1+0x20); - printk("%s this is h264 video\n",__func__); + __raw_writel((__raw_readl(inf->scu_base+0x20) & ~(1<<20)) , inf->scu_base+0x20); + dspprintk("%s this is h264 video\n",__func__); } - iounmap((void __iomem *)(r1)); - iounmap((void __iomem *)(r3)); - #endif return; } @@ -290,7 +276,7 @@ void dsp_set_clk(int clkrate) unsigned int freqreg = 0; int cnt = 0; - if(24==clkrate || 0==clkrate) { + if(0==clkrate) { /* pll set 300M */ freqreg = ( __raw_readl(SCU_BASE_ADDR_VA+0x04)&(~0x003FFFFE) ) | 0x00030310; __raw_writel(freqreg, SCU_BASE_ADDR_VA+0x04); @@ -302,6 +288,10 @@ void dsp_set_clk(int clkrate) return; } + if(clkrate) { + clkrate = FIXED_REQ ? FIXED_REQ : clkrate; + } + /* dsp pll enable */ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x04) & (~(0x01u<<22))) , SCU_BASE_ADDR_VA+0x04); udelay(300); //0.3ms @@ -335,6 +325,9 @@ void dsp_set_clk(int clkrate) } #else struct rk28dsp_inf *inf = g_inf; + if(clkrate) { + clkrate = FIXED_REQ ? FIXED_REQ : clkrate; + } if(inf) { if(inf->clk) clk_set_rate(inf->clk, clkrate*1000000); } @@ -351,10 +344,20 @@ void dsp_powerctl(int ctl, int arg) { case DPC_NORMAL: { +#if 0 //def CONFIG_CHIP_RK2818 //coreµçѹ²»ÎÈʱ,dspÉϵç»áµ¼ÖÂAHBÈ¡Ö¸´íÎó,ËùÒÔdspÉϵçºóµ½Îȶ¨Æڼ䲻²Ù×÷AHB + unsigned long flags; + local_irq_save(flags); + /* dsp subsys power on 0x21*/ + ddr_pll_delay(6000); //¿ªÖ®Ç°Ò²µÃ¼Ó,±ÜÃâ×ÜÏß»¹ÔÚ·ÃÎÊ + __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x10) & (~0x21)) , SCU_BASE_ADDR_VA+0x10); + ddr_pll_delay(6000); //¹ØÖжÏʱ¼ä²»ÄÜÌ«³¤ (6000´ó¸ÅΪ1us) + local_irq_restore(flags); + mdelay(10); +#else /* dsp subsys power on 0x21*/ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x10) & (~0x21)) , SCU_BASE_ADDR_VA+0x10); mdelay(15); - +#endif /* dsp clock enable 0x12*/ DSP_CLOCK_ENABLE(); @@ -363,6 +366,7 @@ void dsp_powerctl(int ctl, int arg) /* dsp set clk */ dsp_set_clk(arg); + mdelay(5); /* dsp peripheral urst */ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x28) & (~0x02000020)) , SCU_BASE_ADDR_VA+0x28); @@ -387,11 +391,12 @@ void dsp_powerctl(int ctl, int arg) /* set CXCLK, XHCLK, XPCLK */ __raw_writel(0, inf->pmu_base+0x08); //CXCLK_DIV (clki:ceva) - __raw_writel(1, inf->pmu_base+0x0c); //XHCLK_DIV (ceva:hclk) + __raw_writel(2, inf->pmu_base+0x0c); //XHCLK_DIV (ceva:hclk) __raw_writel(1, inf->pmu_base+0x10); //XPCLK_DIV (hclk:pclk) } break; + case DPC_SLEEP: { /* dsp work mode :slow mode*/ @@ -419,10 +424,14 @@ void dsp_powerctl(int ctl, int arg) DSP_CLOCK_DISABLE(); /* dsp pll close */ - dsp_set_clk(24); + dsp_set_clk(0); /* dsp subsys power off 0x21*/ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x10) | (0x21)) , SCU_BASE_ADDR_VA+0x10); + + /* close rv/h264 hardware advice after dsp has closed */ + udelay(10); + resetRegValueForVideo(); } break; default: @@ -461,8 +470,8 @@ static int _down_firmware(char *fwname, struct rk28dsp_inf *inf) inf->dsp_status = DS_NORMAL; dspprintk("down firmware (%s) ... \n", fwname); - { - if(0==strcmp(fwname,"rk28_rv40.rkl")) + { + if(0==strcmp(fwname,"rk28_rv40.rkl")) { setRegValueForVideo(0); } @@ -470,7 +479,7 @@ static int _down_firmware(char *fwname, struct rk28dsp_inf *inf) { setRegValueForVideo(1); } - } + } { const struct firmware *fw; char *buf,*code_buf; @@ -484,7 +493,7 @@ static int _down_firmware(char *fwname, struct rk28dsp_inf *inf) dsp_powerctl(DPC_NORMAL, inf->cur_freq); /* down dsp boot */ - dspprintk("\nrequest_firmware ... \n"); + dspprintk("request_firmware ... \n"); ret = request_firmware(&fw, "DspBoot.rkl", &inf->dev); if (ret) { printk(KERN_ERR "Failed to load boot image \"DspBoot.rkl\" err %d\n",ret); @@ -585,12 +594,15 @@ static int _down_firmware(char *fwname, struct rk28dsp_inf *inf) DSP_BOOT_CTRL(); mdelay(10); +#if ENTER_SLOW /* dsp work mode :slow mode*/ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x0c) & (~0x03)) , SCU_BASE_ADDR_VA+0x0c); mdelay(1); +#endif /* dsp core urst*/ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x28) & (~0x00000010)) , SCU_BASE_ADDR_VA+0x28); + mdelay(1); /* change dsp & arm to normal mode */ __raw_writel(0x5, SCU_BASE_ADDR_VA+0x0c); @@ -682,7 +694,7 @@ static long dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) down(&sem); if(inf->cur_pid!=current->tgid || inf->cur_file!=file) { dspprintk("res is obtain by pid %d(cur_file=0x%08x), refuse this req(pid=%d file=0x%08x cmd=0x%08x) \n", - inf->cur_pid, inf->cur_file, current->tgid, file, cmd); + inf->cur_pid, (u32)inf->cur_file, current->tgid, (u32)file, cmd); up(&sem); return -EBUSY; } @@ -729,6 +741,7 @@ static long dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if(0==ret) { + del_timer(&inf->dsp_timer); _down_firmware(req.fwname, inf); queue_flush(inf->rcvmsg_q); rcv_quit = 0; @@ -747,18 +760,18 @@ static long dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) wake_up(&wq); } else { if(strcmp(inf->req1fwname, "")) { - _down_firmware(inf->req1fwname, inf); + //_down_firmware(inf->req1fwname, inf); } } - if(inf->cur_req == 2) - resetRegValueForVideo();//when finishing the video ,must reset some reg value; inf->cur_req = 0; inf->cur_pid = 0; inf->cur_file = NULL; +#if ENTER_SLOW /* dsp work mode :slow mode*/ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x0c) & (~0x03)) , SCU_BASE_ADDR_VA+0x0c); +#endif #if CLOSE_CLK_GATE /* dsp clock disable */ @@ -768,9 +781,10 @@ static long dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* sram dsp clock disable */ __raw_writel((__raw_readl(SCU_BASE_ADDR_VA+0x1c) | (0x10)) , SCU_BASE_ADDR_VA+0x1c); #endif + if(DS_SLEEP!=inf->dsp_status) { - inf->dsp_status = DS_TOSLEEP; - mod_timer(&inf->dsp_timer, jiffies + 5*HZ); + mod_timer(&inf->dsp_timer, jiffies + 5*HZ); + inf->dsp_status = DS_TOSLEEP; } } @@ -780,6 +794,7 @@ static long dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) wake_up(&wq2); up(&sem); + dspprintk("\n"); break; case DSP_IOCTL_SEND_MSG: @@ -1005,6 +1020,8 @@ static int __init dsp_drv_probe(struct platform_device *pdev) inf->pmu_base = (void*)ioremap(PMU_BASE_ADDR, 0x3000); inf->l1_dbase = (void*)ioremap(DSP_BASE_ADDR, 0x10000); inf->l2_idbase = (void*)ioremap(DSP_L2_IMEM_BASE, 0x400000); + inf->scu_base = (void *)ioremap(APB_SCU_BASE, 0x60); + inf->regfile_base = (void *)ioremap(APB_REG_FILE_BASE, 0x60); inf->irq0 = pdev->resource[1].start; inf->irq1 = pdev->resource[2].start; @@ -1086,6 +1103,8 @@ static int dsp_drv_remove(struct platform_device *pdev) iounmap((void __iomem *)(inf->pmu_base)); iounmap((void __iomem *)(inf->l1_dbase)); iounmap((void __iomem *)(inf->l2_idbase)); + iounmap((void __iomem *)(inf->scu_base)); + iounmap((void __iomem *)(inf->regfile_base)); if(inf->clk) { DSP_CLOCK_DISABLE(); @@ -1109,13 +1128,14 @@ static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state) return -EINVAL; } - if(DS_NORMAL==inf->dsp_status) return -EPERM; + if(DS_NORMAL==inf->dsp_status) return -EPERM; //DSPÕýÔÚʹÓÃÖÐ if(DS_SLEEP != inf->dsp_status ) { inf->dsp_status = DS_SLEEP; dsp_powerctl(DPC_SLEEP, 0); dspprintk("dsp : normal -> sleep \n"); } + return 0; } -- 2.34.1