RK3168/RK3188:add DDR_CHANGE_FREQ_IN_LCDC_VSYNC
authorcym <cym@rock-chips.com>
Mon, 5 Aug 2013 09:20:35 +0000 (17:20 +0800)
committercym <cym@rock-chips.com>
Mon, 5 Aug 2013 09:22:43 +0000 (17:22 +0800)
arch/arm/mach-rk30/ddr.c
arch/arm/plat-rk/ddr_freq.c
arch/arm/plat-rk/ddr_test.c [changed mode: 0644->0755]
arch/arm/plat-rk/include/plat/board.h
arch/arm/plat-rk/include/plat/ddr.h

index f8196e38b9a976c56ae43086f9f6c7cd124e77c4..5cc6960f372f15e01f21b9ef7c4e11641b790797 100755 (executable)
 #include <mach/ddr.h>
 #include <mach/cpu.h>
 #include <plat/efuse.h>
+#include <linux/rk_fb.h>
 
 typedef uint32_t uint32;
 
-#define ENABLE_DDR_CLCOK_GPLL_PATH  //for RK3188
+//#define ENABLE_DDR_CLCOK_GPLL_PATH  //for RK3188
 
 #define DDR3_DDR2_DLL_DISABLE_FREQ    (125)
 #define DDR3_DDR2_ODT_DISABLE_FREQ    (333)
@@ -3525,7 +3526,7 @@ int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t mi
     data8_dqstr[dqstr_value][3]=pPHY_Reg->DATX8[0].DXDQSTR;
 
     ddr_print("training %luMhz[%d]:0x%x-0x%x-0x%x-0x%x\n",
-        clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000,dqstr_value,data8_dqstr[dqstr_value][0],data8_dqstr[dqstr_value][1],
+        clk_get_rate(clk_get(NULL, "ddr"))/1000000,dqstr_value,data8_dqstr[dqstr_value][0],data8_dqstr[dqstr_value][1],
         data8_dqstr[dqstr_value][2],data8_dqstr[dqstr_value][3]);
     return 0;
 }
@@ -3594,7 +3595,7 @@ void __sramlocalfunc ddr_set_pll_exit_3168(uint32 freq_slew,uint32_t dqstr_value
 }
 #endif 
 
-uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
+uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz , struct ddr_freq_t ddr_freq_t)
 {
     uint32_t ret;
     u32 i;
@@ -3608,7 +3609,7 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
     uint32_t freq_slew=0,dqstr_value=0;
     if(dqstr_flag==true)
     {
-        dqstr_value=(nMHz-min_ddr_freq+1)/50;
+        dqstr_value=((nMHz-min_ddr_freq+1)/25 + 1) /2;
         freq_slew = (nMHz>ddr_freq)? 1 : 0;
     }
 #endif
@@ -3653,6 +3654,26 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
 #endif
     dsb();
 
+#if defined (DDR_CHANGE_FREQ_IN_LCDC_VSYNC)
+    if(ddr_freq_t.screen_ft_us > 0)
+    {
+        ddr_freq_t.t1 = cpu_clock(0);
+        ddr_freq_t.t2 = (u32)(ddr_freq_t.t1 - ddr_freq_t.t0)/1000;
+
+        if(ddr_freq_t.t2 > ddr_freq_t.screen_ft_us)
+        {
+            DDR_RESTORE_SP(save_sp);
+            local_fiq_enable();
+            local_irq_restore(flags);
+            return 0;
+        }
+        else
+        {
+            rk_fb_poll_wait_frame_complete();
+        }
+    }
+#endif
+
     /** 2. ddr enter self-refresh mode or precharge power-down mode */
    idle_port();
 #if defined(CONFIG_ARCH_RK3066B)
@@ -3682,6 +3703,8 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
 uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
 {
     uint32_t gpll_freq,gpll_div;
+    struct ddr_freq_t ddr_freq_t;
+    ddr_freq_t.screen_ft_us = 0;
 
     gpllvaluel = ddr_get_pll_freq(GPLL);
 
@@ -3704,7 +3727,7 @@ uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
         }
 
         ddr_select_gpll_div=gpll_div;    //select GPLL
-        ddr_change_freq_sram(gpll_freq);
+        ddr_change_freq_sram(gpll_freq,ddr_freq_t);
         ddr_select_gpll_div=0;
 
         ddr_set_pll(nMHz,0); //count DPLL
@@ -3715,7 +3738,7 @@ uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz)
         ddr_print("GPLL frequency = %dMHz,Not suitable for ddr_clock \n",gpllvaluel);
     }
 
-    return ddr_change_freq_sram(nMHz);
+    return ddr_change_freq_sram(nMHz,ddr_freq_t);
 
 }
 
@@ -3729,19 +3752,14 @@ if rk3188 DPLL is bad,use GPLL
 ******************************************/
 uint32_t ddr_change_freq(uint32_t nMHz)
 {
+    struct ddr_freq_t ddr_freq_t;
+    ddr_freq_t.screen_ft_us = 0;
 
-    if(ddr_rk3188_dpll_is_good == false)    //if rk3188 DPLL is bad,use GPLL
-    {
-        return ddr_change_freq_sram(nMHz);
-    }
-    else
-    {
 #if defined(ENABLE_DDR_CLCOK_GPLL_PATH) && defined(CONFIG_ARCH_RK3188)
-        return ddr_change_freq_gpll_dpll(nMHz);
+    return ddr_change_freq_gpll_dpll(nMHz);
 #else
-        return ddr_change_freq_sram(nMHz);
+    return ddr_change_freq_sram(nMHz,ddr_freq_t);
 #endif
-    }
 }
 EXPORT_SYMBOL(ddr_change_freq);
 
@@ -3982,7 +4000,7 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
     uint32_t die=1;
     uint32_t gsr,dqstr;
 
-    ddr_print("version 1.00 20130712 \n");
+    ddr_print("version 1.00 20130805 0 \n");
 
     mem_type = pPHY_Reg->DCR.b.DDRMD;
     ddr_speed_bin = dram_speed_bin;
index 0d23a171629009536ac0f5a8d39789535ee6dd73..5e88981842561a9772976ecbec35f8e0ec68095b 100755 (executable)
 #include <mach/ddr.h>
 #include <mach/dvfs.h>
 
+#include <linux/rk_fb.h>
+//#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <linux/vmalloc.h>
+
 enum {
        DEBUG_DDR = 1U << 0,
        DEBUG_VIDEO_STATE = 1U << 1,
@@ -34,13 +41,15 @@ module_param(debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
 enum SYS_STATUS {
        SYS_STATUS_SUSPEND = 0, // 0x01
        SYS_STATUS_VIDEO,       // 0x02
-       SYS_STATUS_GPU,         // 0x04
-       SYS_STATUS_RGA,         // 0x08
-       SYS_STATUS_CIF0,        // 0x10
-       SYS_STATUS_CIF1,        // 0x20
-       SYS_STATUS_REBOOT,      // 0x40
-       SYS_STATUS_LCDC0,       // 0x80
-       SYS_STATUS_LCDC1,       // 0x100
+       SYS_STATUS_VIDEO_720P,       // 0x04
+       SYS_STATUS_VIDEO_1080P,       // 0x08
+       SYS_STATUS_GPU,         // 0x10
+       SYS_STATUS_RGA,         // 0x20
+       SYS_STATUS_CIF0,        // 0x40
+       SYS_STATUS_CIF1,        // 0x80
+       SYS_STATUS_REBOOT,      // 0x100
+       SYS_STATUS_LCDC0,       // 0x200
+       SYS_STATUS_LCDC1,       // 0x400
 };
 
 struct ddr {
@@ -51,6 +60,7 @@ struct ddr {
        struct clk *clk;
        unsigned long normal_rate;
        unsigned long video_rate;
+       unsigned long video_low_rate;
        unsigned long dualview_rate;
        unsigned long idle_rate;
        unsigned long suspend_rate;
@@ -117,8 +127,13 @@ static noinline void ddrfreq_work(unsigned long sys_status)
              && (s & (1 << SYS_STATUS_LCDC1))
              ) {
                ddrfreq_mode(false, &ddr.dualview_rate, "dual-view");
-       } else if (ddr.video_rate && (s & (1 << SYS_STATUS_VIDEO))) {
-               ddrfreq_mode(false, &ddr.video_rate, "video");
+       } else if ((ddr.video_rate || ddr.video_low_rate) && (s & (1 << SYS_STATUS_VIDEO))) {
+               if(ddr.video_low_rate && (s & (1 << SYS_STATUS_VIDEO_720P)))
+                       ddrfreq_mode(false, &ddr.video_low_rate, "video low");
+               else if(ddr.video_rate && (s & (1 << SYS_STATUS_VIDEO_1080P)))
+                       ddrfreq_mode(false, &ddr.video_rate, "video");
+               else
+                       ddrfreq_mode(false, &ddr.normal_rate, "video normal");
        } else if (ddr.idle_rate
                && !(s & (1 << SYS_STATUS_GPU))
                && !(s & (1 << SYS_STATUS_RGA))
@@ -174,11 +189,12 @@ static void __sramfunc pause_cpu(void *info)
        local_irq_restore(flags);
 }
 
-static void _ddr_change_freq(uint32_t nMHz)
+static int _ddr_change_freq_(uint32_t nMHz,struct ddr_freq_t ddr_freq_t)
 {
        u32 timeout = MAX_TIMEOUT;
        unsigned int cpu;
        unsigned int this_cpu = smp_processor_id();
+       int ret;
 
        cpu_maps_update_begin();
 
@@ -195,12 +211,45 @@ static void _ddr_change_freq(uint32_t nMHz)
                }
        }
 
-       ddr_change_freq(nMHz);
+       ret = ddr_change_freq_sram(nMHz,ddr_freq_t);
 
        set_other_cpus_pause(false);
 
 out:
        cpu_maps_update_done();
+
+       return ret;
+}
+
+static void _ddr_change_freq(uint32_t nMHz)
+{
+       struct ddr_freq_t ddr_freq_t;
+       int test_count=0;
+
+       ddr_freq_t.screen_ft_us = 0;
+       ddr_freq_t.t0 = 0;
+       ddr_freq_t.t1 = 0;
+
+#if defined (DDR_CHANGE_FREQ_IN_LCDC_VSYNC)
+       do
+       {
+               if(rk_fb_poll_wait_frame_complete() == true)
+               {
+                       ddr_freq_t.t0 = cpu_clock(0);
+                       ddr_freq_t.screen_ft_us = rk_fb_get_prmry_screen_ft();
+
+                       test_count++;
+                       //dprintk(DEBUG_VERBOSE,"test_count=%d\n",test_count);
+                       usleep_range(ddr_freq_t.screen_ft_us-test_count*1000,ddr_freq_t.screen_ft_us-test_count*1000);
+
+                       flush_cache_all();
+                       outer_flush_all();
+                       flush_tlb_all();
+               }
+       }while(_ddr_change_freq_(nMHz,ddr_freq_t)==0);
+#else
+       _ddr_change_freq_(nMHz,ddr_freq_t);
+#endif
 }
 #else
 static void _ddr_change_freq(uint32_t nMHz)
@@ -237,27 +286,67 @@ static int video_state_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+#define VIDEO_LOW_RESOLUTION       (1080*720)
 static ssize_t video_state_write(struct file *file, const char __user *buffer,
                                 size_t count, loff_t *ppos)
 {
        char state;
+       char *cookie_pot;
+       char *p;
+       char *buf = vzalloc(count);
+       uint32_t v_width=0,v_height=0,v_sync=0;
+       cookie_pot = buf;
 
        if (count < 1)
                return count;
-       if (copy_from_user(&state, buffer, 1)) {
+       if (copy_from_user(cookie_pot, buffer, count)) {
                return -EFAULT;
        }
 
-       dprintk(DEBUG_VIDEO_STATE, "video_state write %c\n", state);
+       dprintk(DEBUG_VIDEO_STATE, "video_state write %s,len %d\n", cookie_pot,count);
+
+       state=cookie_pot[0];
+       if( (count>=3) && (cookie_pot[2]=='w') )
+       {
+               strsep(&cookie_pot,",");
+               strsep(&cookie_pot,"=");
+               p=strsep(&cookie_pot,",");
+               v_width = simple_strtol(p,NULL,10);
+               strsep(&cookie_pot,"=");
+               p=strsep(&cookie_pot,",");
+               v_height= simple_strtol(p,NULL,10);
+               strsep(&cookie_pot,"=");
+               p=strsep(&cookie_pot,",");
+               v_sync= simple_strtol(p,NULL,10);
+               dprintk(DEBUG_VIDEO_STATE, "video_state %c,width=%d,height=%d,sync=%d\n", state,v_width,v_height,v_sync);
+       }
+
        switch (state) {
        case '0':
                ddrfreq_clear_sys_status(SYS_STATUS_VIDEO);
+               ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_720P);
+               ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_1080P);
                break;
        case '1':
                ddrfreq_set_sys_status(SYS_STATUS_VIDEO);
+
+               if( (v_width == 0) && (v_height == 0)){
+                       ddrfreq_set_sys_status(SYS_STATUS_VIDEO_1080P);
+               }
+               else if(v_sync==1){
+                       if(ddr.video_low_rate && ((v_width*v_height) <= VIDEO_LOW_RESOLUTION) )
+                               ddrfreq_set_sys_status(SYS_STATUS_VIDEO_720P);
+                       else
+                               ddrfreq_set_sys_status(SYS_STATUS_VIDEO_1080P);
+               }
+               else{
+                       ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_720P);
+                       ddrfreq_clear_sys_status(SYS_STATUS_VIDEO_1080P);
+               }
                break;
        default:
                return -EINVAL;
+
        }
        ddr.video_state = state;
        return count;
@@ -383,7 +472,7 @@ static int ddrfreq_init(void)
 {
        int i, ret;
        struct cpufreq_frequency_table *table;
-       bool new_version = false;
+       int ddrfreq_version = 0;
 
        init_waitqueue_head(&ddr.wait);
        ddr.video_state = '0';
@@ -409,16 +498,22 @@ static int ddrfreq_init(void)
 
        for (i = 0; table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
                if (table[i].frequency % 1000) {
-                       new_version = true;
+                       ddrfreq_version = 1;
+               }
+
+               if (table[i].frequency % 1000 > 100) {
+                       ddrfreq_version = 2;
                        break;
                }
        }
-       if (!new_version) {
+        
+       if (ddrfreq_version==0) {
                ddr.video_rate = 300 * MHZ;
                ddr.dualview_rate = ddr.normal_rate;
                ddr.suspend_rate = 200 * MHZ;
        }
-       for (i = 0; new_version && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
+
+       for (i = 0; ddrfreq_version == 1 && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
                unsigned int mode = table[i].frequency % 1000;
                unsigned long rate;
 
@@ -429,6 +524,9 @@ static int ddrfreq_init(void)
                case DDR_FREQ_NORMAL:
                        ddr.normal_rate = rate;
                        break;
+               case DDR_FREQ_VIDEO_LOW:
+                       ddr.video_low_rate = rate;
+                       break;
                case DDR_FREQ_VIDEO:
                        ddr.video_rate = rate;
                        break;
@@ -444,6 +542,32 @@ static int ddrfreq_init(void)
                }
        }
 
+       for (i = 0; ddrfreq_version == 2 && table && table[i].frequency != CPUFREQ_TABLE_END; i++) {
+               unsigned int mode = table[i].frequency % 1000;
+               unsigned long rate;
+
+               table[i].frequency -= mode;
+               rate = table[i].frequency * 1000;
+
+               if( (mode&DDR_FREQ_NORMAL) == DDR_FREQ_NORMAL)
+                       ddr.normal_rate = rate;
+
+               if( (mode&DDR_FREQ_VIDEO_LOW) == DDR_FREQ_VIDEO_LOW)
+                       ddr.video_low_rate = rate;
+
+               if( (mode&DDR_FREQ_VIDEO) == DDR_FREQ_VIDEO)
+                       ddr.video_rate = rate;
+
+               if( (mode&DDR_FREQ_DUALVIEW) == DDR_FREQ_DUALVIEW)
+                       ddr.dualview_rate= rate;
+
+               if( (mode&DDR_FREQ_IDLE) == DDR_FREQ_IDLE)
+                       ddr.idle_rate = rate;
+
+               if( (mode&DDR_FREQ_SUSPEND) == DDR_FREQ_SUSPEND)
+                       ddr.suspend_rate = rate;
+       }
+
        if (ddr.idle_rate) {
                REGISTER_CLK_NOTIFIER(pd_gpu);
                REGISTER_CLK_NOTIFIER(pd_rga);
@@ -501,9 +625,9 @@ static int ddrfreq_late_init(void)
 
        register_reboot_notifier(&ddrfreq_reboot_notifier);
 
-       pr_info("verion 2.4 20130427\n");
-       dprintk(DEBUG_DDR, "normal %luMHz video %luMHz dualview %luMHz idle %luMHz suspend %luMHz reboot %luMHz\n",
-               ddr.normal_rate / MHZ, ddr.video_rate / MHZ, ddr.dualview_rate / MHZ,ddr.idle_rate / MHZ, ddr.suspend_rate / MHZ, ddr.reboot_rate / MHZ);
+       pr_info("verion 3.1 20130805\n");
+       dprintk(DEBUG_DDR, "normal %luMHz video %luMHz video_low %luMHz dualview %luMHz idle %luMHz suspend %luMHz reboot %luMHz\n",
+               ddr.normal_rate / MHZ, ddr.video_rate / MHZ, ddr.video_low_rate / MHZ, ddr.dualview_rate / MHZ, ddr.idle_rate / MHZ, ddr.suspend_rate / MHZ, ddr.reboot_rate / MHZ);
 
        return 0;
 
old mode 100644 (file)
new mode 100755 (executable)
index ad2906a..6a99680
@@ -8,6 +8,21 @@
 #include <linux/uaccess.h>
 #include <linux/clk.h>
 
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+
+#include <mach/ddr.h>
+
+struct ddrtest {
+    struct clk *pll;
+    struct clk *clk;
+    volatile unsigned int freq;
+    volatile bool change_end;
+    struct task_struct *task;
+    wait_queue_head_t wait;
+};
+static struct ddrtest ddrtest;
+
 static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                           unsigned long len, void *data)
 {
@@ -52,10 +67,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                 p=strsep(&cookie_pot,"M");
                 value = simple_strtol(p,NULL,10);
                 printk("change!!! freq=%dMHz\n", value);
-                clk_set_rate(clk_ddr, value * 1000000);
+                //clk_set_rate(clk_ddr, value * 1000000);
+                ddrtest.freq = value;
+                ddrtest.change_end = false;
+                wake_up(&ddrtest.wait);
+                while(ddrtest.change_end != true);  //wait change freq end
                 value = clk_get_rate(clk_ddr) / 1000000;
                 printk("success!!! freq=%dMHz\n", value);
-                msleep(32);
+                msleep(64);
                 printk("\n");
             }
             else
@@ -92,10 +111,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                     }while(value < value1);
 
                     printk("change!!! freq=%dMHz\n", value);
-                    clk_set_rate(clk_ddr, value * 1000000);
+                    //clk_set_rate(clk_ddr, value * 1000000);
+                    ddrtest.freq = value;
+                    ddrtest.change_end = false;
+                    wake_up(&ddrtest.wait);
+                    while(ddrtest.change_end != true);  //wait change freq end
                     value = clk_get_rate(clk_ddr) / 1000000;
                     printk("success!!! freq=%dMHz\n", value);
-                    msleep(32);
+                    msleep(64);
                     count++;
                 }
 
@@ -140,10 +163,14 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                     }
 
                     printk("change!!! freq=%dMHz\n", value);
-                    clk_set_rate(clk_ddr, value * 1000000);
+                    //clk_set_rate(clk_ddr, value * 1000000);
+                    ddrtest.freq = value;
+                    ddrtest.change_end = false;
+                    wake_up(&ddrtest.wait);
+                    while(ddrtest.change_end != true);  //wait change freq end
                     value = clk_get_rate(clk_ddr) / 1000000;
                     printk("success!!! freq=%dMHz\n", value);
-                    msleep(32);
+                    msleep(64);
                     count++;
                 }
 
@@ -176,19 +203,65 @@ static const struct file_operations ddr_proc_fops = {
     .owner             = THIS_MODULE,
 };
 
+static void ddrtest_work(unsigned int value)
+{
+
+    clk_set_rate(ddrtest.clk, value * 1000000);
+    ddrtest.change_end = true;
+}
+
+static int ddrtest_task(void *data)
+{
+    set_freezable();
+
+    do {
+        //unsigned long status = ddr.sys_status;
+        ddrtest_work(ddrtest.freq);
+        wait_event_freezable(ddrtest.wait, (ddrtest.change_end == false ) || kthread_should_stop());
+    } while (!kthread_should_stop());
+
+    return 0;
+}
+
 static int ddr_proc_init(void)
 {
     struct proc_dir_entry *ddr_proc_entry;
+    int ret;
+    struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+    init_waitqueue_head(&ddrtest.wait);
+
+    ddrtest.pll = clk_get(NULL, "ddr_pll");
+    ddrtest.clk = clk_get(NULL, "ddr");
+    if (IS_ERR(ddrtest.clk)) {
+        ret = PTR_ERR(ddrtest.clk);
+        ddrtest.clk = NULL;
+        pr_err("failed to get ddr clk, error %d\n", ret);
+        return ret;
+    }
+
     ddr_proc_entry = create_proc_entry("driver/ddr_ts", 0777, NULL);
     if(ddr_proc_entry != NULL)
     {
         ddr_proc_entry->write_proc = ddr_proc_write;
-        return -1;
+        //return -1;
     }
     else
     {
         printk("create proc error !\n");
     }
+
+    ddrtest.task = kthread_create(ddrtest_task, NULL, "ddrtestd");
+    if (IS_ERR(ddrtest.task)) {
+        ret = PTR_ERR(ddrtest.task);
+        pr_err("failed to create kthread! error %d\n", ret);
+        goto err;
+    }
+    sched_setscheduler_nocheck(ddrtest.task,SCHED_FIFO, &param);
+    get_task_struct(ddrtest.task);
+    kthread_bind(ddrtest.task, 0);
+    wake_up_process(ddrtest.task);
+
+err:
     return 0;
 }
 
index 52dd95a18623cc6c21111ea88dc305c1e817fcb1..04b1689dc45e3b4c617d985c36d452ef197f629c 100755 (executable)
@@ -555,8 +555,7 @@ void __sramfunc board_pmu_resume(void);
  * For DDR frequency scaling setup. Board code something like this:
  *
  * This array _must_ be sorted in ascending frequency (without DDR_FREQ_*) order.
- * 必须按频率(不必考虑DDR_FREQ_*)递增。
- *static struct cpufreq_frequency_table dvfs_ddr_table[] = {
+ * å¿\85é¡»æ\8c\89é¢\91ç\8e\87ï¼\88ä¸\8då¿\85è\80\83è\99\91DDR_FREQ_*ï¼\89é\80\92å¢\9eã\80? *static struct cpufreq_frequency_table dvfs_ddr_table[] = {
  *     {.frequency = 200 * 1000 + DDR_FREQ_SUSPEND,    .index = xxxx * 1000},
  *     {.frequency = 200 * 1000 + DDR_FREQ_IDLE,       .index = xxxx * 1000},
  *     {.frequency = 300 * 1000 + DDR_FREQ_VIDEO,      .index = xxxx * 1000},
@@ -565,11 +564,12 @@ void __sramfunc board_pmu_resume(void);
  *};
  */
 enum ddr_freq_mode {
-       DDR_FREQ_NORMAL = 1,    // default
-       DDR_FREQ_VIDEO,         // when video is playing
-       DDR_FREQ_DUALVIEW,     // when dual view,lcdc0 and lcdc1 open at the same time
-       DDR_FREQ_IDLE,          // when screen is idle
-       DDR_FREQ_SUSPEND,       // when early suspend
+       DDR_FREQ_SUSPEND=(0x1<<0),      // when early suspend
+       DDR_FREQ_VIDEO=(0x1<<1),                // when video is playing
+       DDR_FREQ_VIDEO_LOW=(0x1<<2),                // when video is playing low
+       DDR_FREQ_DUALVIEW=(0x1<<3),     // when dual view,lcdc0 and lcdc1 open at the same time
+       DDR_FREQ_IDLE=(0x1<<4),         // when screen is idle
+       DDR_FREQ_NORMAL=(0x1<<8),      // default
 };
 
 #endif
index 87f31f7d56b8768d6f8fd8c19d94d4866b7d4211..219674c023aa3a4b3633f4f7b31f2c54f419a722 100755 (executable)
@@ -149,7 +149,14 @@ void __sramfunc ddr_resume(void);
 #if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026)
 uint32_t __sramfunc ddr_change_freq(uint32_t nMHz);
 #else
+struct ddr_freq_t {
+    unsigned long screen_ft_us;
+    unsigned long long t0;
+    unsigned long long t1;
+    unsigned long t2;
+};
 uint32_t ddr_change_freq(uint32_t nMHz);
+uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz , struct ddr_freq_t ddr_freq_t);
 #endif
 uint32_t ddr_get_cap(void);
 int ddr_init(uint32_t dram_type, uint32_t freq);
@@ -160,4 +167,8 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set);
 int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t min_freq);
 #endif
 
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
+#define DDR_CHANGE_FREQ_IN_LCDC_VSYNC
+#endif
+
 #endif