diff --git a/arch/arm/mach-rk30/common.c b/arch/arm/mach-rk30/common.c index 9e47f426d484..48ccd49c4ff5 100755 --- a/arch/arm/mach-rk30/common.c +++ b/arch/arm/mach-rk30/common.c @@ -133,8 +133,8 @@ void __init rk30_map_io(void) rk29_sram_init(); board_clock_init(); rk30_l2_cache_init(); -#if !defined(CONFIG_ARCH_RK3066B) ddr_init(DDR_TYPE, DDR_FREQ); +#if !defined(CONFIG_ARCH_RK3066B) clk_disable_unused(); #endif rk30_iomux_init(); diff --git a/arch/arm/mach-rk30/ddr.c b/arch/arm/mach-rk30/ddr.c index db644378fc36..4a4d8f1cd6f5 100755 --- a/arch/arm/mach-rk30/ddr.c +++ b/arch/arm/mach-rk30/ddr.c @@ -38,6 +38,7 @@ typedef uint32_t uint32; #define SysSrv_DdrTiming (RK30_CPU_AXI_BUS_BASE+0x0c) #define SysSrv_DdrMode (RK30_CPU_AXI_BUS_BASE+0x10) #define SysSrv_ReadLatency (RK30_CPU_AXI_BUS_BASE+0x14) +#define ROM_CHIP_ID_ADDR (RK30_ROM_BASE+0x27f0) #define ddr_print(x...) printk( "DDR DEBUG: " x ) @@ -228,6 +229,14 @@ typedef volatile struct tagPMU_FILE #define NO(n) ((0xF<<16) | ((n)-1)) #define NF(n) ((0x1FFF<<16) | ((n)-1)) #define NB(n) ((0xFFF<<16) | ((n)-1)) + +//RK3066B +#define PLL_RESET_RK3066B (((0x1<<1)<<16) | (0x1<<1)) +#define PLL_DE_RESET_RK3066B (((0x1<<1)<<16) | (0x0<<1)) +#define NR_RK3066B(n) ((0x3F<<(8+16)) | (((n)-1)<<8)) +#define NO_RK3066B(n) ((0x3F<<16) | ((n)-1)) +#define NF_RK3066B(n) ((0xFFFF<<16) | ((n)-1)) + //CRU Registers typedef volatile struct tagCRU_STRUCT { @@ -288,6 +297,33 @@ typedef volatile struct tagREG_FILE #define pGRF_Reg ((pREG_FILE)REG_FILE_BASE_ADDR) +//REG FILE registers +typedef volatile struct tagREG_FILE_RK3066B +{ + GPIO_LH_T GRF_GPIO_DIR[4]; + GPIO_LH_T GRF_GPIO_DO[4]; + GPIO_LH_T GRF_GPIO_EN[4]; + GPIO_IOMUX_T GRF_GPIO_IOMUX[4]; + uint32 GRF_SOC_CON[3]; + uint32 GRF_SOC_STATUS0; + uint32 GRF_DMAC0_CON[3]; + uint32 GRF_DMAC1_CON[4]; + uint32 reserved0[(0xec-0xcc)/4]; + uint32 GRF_DDRC_CON0; + uint32 GRF_DDRC_STAT; + uint32 GRF_IO_CON[5]; + uint32 reserved1; + uint32 GRF_UOC0_CON[4]; + uint32 GRF_UOC1_CON[4]; + uint32 GRF_UOC2_CON[2]; + uint32 reserved2; + uint32 GRF_UOC3_CON[2]; + uint32 GRF_HSIC_STAT; + uint32 GRF_OS_REG[8]; +} REG_FILE_RK3066B, *pREG_FILE_RK3066B; + +#define pGRF_Reg_RK3066B ((pREG_FILE_RK3066B)REG_FILE_BASE_ADDR) + //SCTL #define INIT_STATE (0) #define CFG_STATE (1) @@ -981,7 +1017,9 @@ uint32_t __sramdata ddr3_tRC_tFAW[22]={ ((53<<16)|50) //DDR3_DEFAULT }; + __sramdata uint32_t mem_type; // 0:LPDDR, 1:DDR, 2:DDR2, 3:DDR3, 4:LPDDR2 +__sramdata bool chip_rk3066b_flag=false; static __sramdata uint32_t ddr_speed_bin; // used for ddr3 only static __sramdata uint32_t ddr_capability_per_die; // one chip cs capability static __sramdata uint32_t ddr_freq; @@ -1023,9 +1061,19 @@ uint32 ddr_get_row(void) i = *(volatile uint32*)SysSrv_DdrConf; row = ddr_cfg_2_rbc[i].row; - if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1)) + if(chip_rk3066b_flag == true) { - row += 1; + if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (1<<1)) + { + row += 1; + } + } + else + { + if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1)) + { + row += 1; + } } return row; } @@ -1360,18 +1408,101 @@ uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) ddr_delayus(1); pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET; dsb(); - while (delay > 0) + while (delay > 0) { ddr_delayus(1); - if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) - break; - delay--; - } - + if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) + break; + delay--; + } pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x0<<8) //clk_ddr_src = DDR PLL | 0; //clk_ddr_src:clk_ddrphy = 1:1 - + + pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal + dsb(); + } +out: + return ret; +} + + +/***************************************** +RK3066B +NR NO NF Fout freq Step finally use +1 14 46 - 91 78MHz - 157MHz 1.7MHz 78MHz<= 150MHz +1 8 46 - 91 137MHz - 275MHz 3MHz 150MHz<= 200MHz +1 6 46 - 91 183MHz - 366MHz 4MHz 200MHz<= 300MHz +1 4 46 - 91 275MHz - 550MHz 6MHz 300MHz<= 550MHz +1 2 46 - 91 550MHz - 1100MHz 12MHz 550MHz<= 1100MHz +1 1 46 - 91 1100MHz - 2200MHz 24MHz 1100MHz<= 2200MHz +******************************************/ +uint32_t __sramlocalfunc ddr_set_pll_rk3600b(uint32_t nMHz, uint32_t set) +{ + uint32_t ret = 0; + int delay = 1000; + uint32_t pll_id=1; //DPLL + + if(nMHz == 24) + { + ret = 24; + goto out; + } + + if(!set) + { + if(nMHz <= 150) + { + clkod = 14; + } + else if(nMHz <= 200) + { + clkod = 8; + } + else if(nMHz <= 300) + { + clkod = 6; + } + else if(nMHz <= 550) + { + clkod = 4; + } + else if(nMHz <= 1100) + { + clkod = 2; + } + else + { + clkod = 1; + } + clkr = 1; + clkf=(nMHz*clkr*clkod)/24; + ret = (24*clkf)/(clkr*clkod); + } + else + { + pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x0<<(pll_id*4)); //PLL slow-mode + dsb(); + + pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B; + pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod); + pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf); +// pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1); + ddr_delayus(1); + pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B; + dsb(); + while (delay > 0) + { + ddr_delayus(1); + if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5)) + break; + delay--; + } + + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x0<<8) //clk_ddr_src = DDR PLL + | 0; //clk_ddr_src:clk_ddrphy = 1:1 + pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal dsb(); } @@ -2798,9 +2929,19 @@ __sramfunc void ddr_adjust_config(uint32_t dram_type) ddr_move_to_Config_state(); //extend capability for debug - if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1)) + if(chip_rk3066b_flag == true) { - pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en; + if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (0x1<<1)) + { + pGRF_Reg_RK3066B->GRF_SOC_CON[2] = rank_to_row15_en; + } + } + else + { + if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1)) + { + pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en; + } } //set data training address @@ -2985,15 +3126,18 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz) // freq = (Fin/NR)*NF/OD if((pCRU_Reg->CRU_MODE_CON&3) == 1) // CPLL Normal mode - freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0x1fff)+1) // NF = 2*(CLKF+1) + freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0xffff)+1) // NF = 2*(CLKF+1) /((((regvalue>>8)&0x3f)+1) // NR = CLKR+1 - *((regvalue&0xF)+1)); // OD = 2^CLKOD + *((regvalue&0x3F)+1)); // OD = 2^CLKOD else freq = 24; loops_per_us = LPJ_100MHZ*freq / 1000000; - - ret=ddr_set_pll(nMHz,0); + + if(chip_rk3066b_flag == true) + ret=ddr_set_pll_rk3600b(nMHz,0); + else + ret=ddr_set_pll(nMHz,0); ddr_get_parameter(ret); /** 1. Make sure there is no host access */ @@ -3014,7 +3158,14 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz) n= pCRU_Reg->CRU_PLL_CON[0][0]; n= pPMU_Reg->PMU_WAKEUP_CFG[0]; n= *(volatile uint32_t *)SysSrv_DdrConf; - n= pGRF_Reg->GRF_SOC_STATUS0; + if(chip_rk3066b_flag == true) + { + n= pGRF_Reg_RK3066B->GRF_SOC_STATUS0; + } + else + { + n= pGRF_Reg->GRF_SOC_STATUS0; + } dsb(); /** 2. ddr enter self-refresh mode or precharge power-down mode */ @@ -3022,7 +3173,10 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz) ddr_selfrefresh_enter(ret); /** 3. change frequence */ - ddr_set_pll(ret,1); + if(chip_rk3066b_flag == true) + ddr_set_pll_rk3600b(ret,1); + else + ddr_set_pll(ret,1); ddr_freq = ret; /** 5. Issues a Mode Exit command */ @@ -3092,9 +3246,17 @@ void __sramfunc ddr_resume(void) while (delay > 0) { ddr_delayus(1); - if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) - break; - delay--; + if(chip_rk3066b_flag == true) + { + if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5)) + break; + } + else + { + if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) + break; + } + delay--; } pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal @@ -3127,9 +3289,19 @@ uint32 ddr_get_cap(void) break; } row = ddr_cfg_2_rbc[i].row; - if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1)) + if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c) == 0x56313030) { - row += 1; + if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (1<<1)) + { + row += 1; + } + } + else + { + if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1)) + { + row += 1; + } } return (1 << (row+(ddr_cfg_2_rbc[i].col)+(ddr_cfg_2_rbc[i].bank)+2))*cs; @@ -3225,7 +3397,15 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq) uint32_t cs,die=1; uint32_t gsr,dqstr; - ddr_print("version 1.00 20120822 \n"); + ddr_print("version 1.00 20120903 \n"); + + if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c) == 0x56313030) + { + chip_rk3066b_flag=true; + ddr_print("RK3066B \n"); + } + else + chip_rk3066b_flag=false; mem_type = pPHY_Reg->DCR.b.DDRMD; ddr_speed_bin = dram_speed_bin; diff --git a/arch/arm/mach-rk30/ddr_freq.c b/arch/arm/mach-rk30/ddr_freq.c index 5a3eef8f02b1..bf87a3db0f9d 100644 --- a/arch/arm/mach-rk30/ddr_freq.c +++ b/arch/arm/mach-rk30/ddr_freq.c @@ -88,21 +88,22 @@ out: uint32_t ddr_set_rate(uint32_t nMHz) { - _ddr_change_freq(nMHz); - return 0; + nMHz = _ddr_change_freq(nMHz); + return nMHz; } - #ifdef CONFIG_HAS_EARLYSUSPEND +static uint32_t ddr_resume_freq=DDR_FREQ; +static uint32_t ddr_suspend_freq=120; static void ddr_early_suspend(struct early_suspend *h) { uint32_t value; //Enable auto self refresh 0x01*32 DDR clk cycle ddr_set_auto_self_refresh(true); - - value = _ddr_change_freq(120); - + + ddr_resume_freq=clk_get_rate(ddr.ddr_pll)/1000000; + value = ddr_set_rate(ddr_suspend_freq); ddr_print("init success!!! freq=%dMHz\n", value); return; @@ -115,8 +116,7 @@ static void ddr_late_resume(struct early_suspend *h) //Disable auto self refresh ddr_set_auto_self_refresh(false); - value = _ddr_change_freq(DDR_FREQ); - + value = ddr_set_rate(ddr_resume_freq); ddr_print("init success!!! freq=%dMHz\n", value); return; @@ -173,13 +173,9 @@ 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); - cpu1_online=cpu_online(1); - if(cpu1_online) - cpu_down(1); - value=ddr_change_freq(value); - if(cpu1_online) - cpu_up(1); + value=ddr_set_rate(value); printk("success!!! freq=%dMHz\n", value); + msleep(32); printk("\n"); } else @@ -216,16 +212,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer, }while(value < value1); printk("change!!! freq=%dMHz\n", value); - - cpu1_online=cpu_online(1); - if(cpu1_online) - cpu_down(1); - msleep(32); - value=ddr_change_freq(value); - if(cpu1_online) - cpu_up(1); + value=ddr_set_rate(value); printk("success!!! freq=%dMHz\n", value); - + msleep(32); count++; } @@ -269,14 +258,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer, } printk("change!!! freq=%dMHz\n", value); - cpu1_online=cpu_online(1); - if(cpu1_online) - cpu_down(1); - msleep(32); - value=ddr_change_freq(value); - if(cpu1_online) - cpu_up(1); + value=ddr_set_rate(value); printk("success!!! freq=%dMHz\n", value); + msleep(32); count++; } @@ -287,7 +271,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer, printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'a:200M-400M-1000T' > ddr_test\n"); } break; - + + case 'h': + case 'H': default: printk("Help for ddr_ts .\n-->The Cmd list: \n"); printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-100T' > ddr_test\n"); diff --git a/arch/arm/plat-rk/include/plat/vpu_service.h b/arch/arm/plat-rk/include/plat/vpu_service.h index 1ec121559670..21b02b9dccc1 100644 --- a/arch/arm/plat-rk/include/plat/vpu_service.h +++ b/arch/arm/plat-rk/include/plat/vpu_service.h @@ -32,21 +32,6 @@ #define VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, unsigned long) #define VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, unsigned long) - -// client type: decoder only£º60 registers, size 240B -#define VPU_REG_NUM_DEC (60) -// client type: post-process only£º41 registers, size 164B -#define VPU_REG_NUM_PP (41) -// client type: decoder plus post-process£º101 registers, size 404B -#define VPU_REG_NUM_DEC_PP (VPU_REG_NUM_DEC+VPU_REG_NUM_PP) -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK2928) -// client type: encoder only: 96 registers, size 384B for rk29 -#define VPU_REG_NUM_ENC (96) -#elif defined(CONFIG_ARCH_RK30) -// client type: encoder only: 164 registers, size 384B for rk30 -#define VPU_REG_NUM_ENC (164) -#endif - typedef enum VPU_CLIENT_TYPE { VPU_ENC = 0x0, VPU_DEC = 0x1, @@ -90,9 +75,8 @@ typedef struct VPUHwEndConfig unsigned long mpeg4Enabled; /* HW supports MPEG-4 */ unsigned long vsEnabled; /* HW supports video stabilization */ unsigned long rgbEnabled; /* HW supports RGB input */ - unsigned long busType; /* HW bus type in use */ - unsigned long busWidth; - unsigned long synthesisLanguage; + unsigned long reg_size; + unsigned long reserv[2]; /* reverved */ } VPUHwEncConfig_t; typedef struct VPUHwCfgReq diff --git a/arch/arm/plat-rk/vpu_service.c b/arch/arm/plat-rk/vpu_service.c index 9782c76cef48..b0eaeafc25da 100644 --- a/arch/arm/plat-rk/vpu_service.c +++ b/arch/arm/plat-rk/vpu_service.c @@ -46,6 +46,67 @@ #include #include +typedef enum { + VPU_DEC_ID_9190 = 0x6731, + VPU_ID_8270 = 0x8270, + VPU_ID_4831 = 0x4831, +} VPU_HW_ID; + +typedef enum { + VPU_DEC_TYPE_9190 = 0, + VPU_ENC_TYPE_8270 = 0x100, + VPU_ENC_TYPE_4831 , +} VPU_HW_TYPE_E; + +typedef struct { + VPU_HW_ID hw_id; + unsigned long hw_addr; + unsigned long enc_offset; + unsigned long enc_reg_num; + unsigned long enc_io_size; + unsigned long dec_offset; + unsigned long dec_reg_num; + unsigned long dec_io_size; +} VPU_HW_INFO_E; + +#define VCODEC_PHYS (0x10104000) + +#define REG_NUM_9190_DEC (60) +#define REG_NUM_9190_PP (41) +#define REG_NUM_9190_DEC_PP (REG_NUM_9190_DEC+REG_NUM_9190_PP) + +#define REG_NUM_DEC_PP (REG_NUM_9190_DEC+REG_NUM_9190_PP) + +#define REG_NUM_ENC_8270 (96) +#define REG_SIZE_ENC_8270 (0x200) +#define REG_NUM_ENC_4831 (164) +#define REG_SIZE_ENC_4831 (0x400) + +#define SIZE_REG(reg) ((reg)*4) + +VPU_HW_INFO_E vpu_hw_set[] = { + [0] = { + .hw_id = VPU_ID_8270, + .hw_addr = VCODEC_PHYS, + .enc_offset = 0x0, + .enc_reg_num = REG_NUM_ENC_8270, + .enc_io_size = REG_NUM_ENC_8270 * 4, + .dec_offset = REG_SIZE_ENC_8270, + .dec_reg_num = REG_NUM_9190_DEC_PP, + .dec_io_size = REG_NUM_9190_DEC_PP * 4, + }, + [1] = { + .hw_id = VPU_ID_4831, + .hw_addr = VCODEC_PHYS, + .enc_offset = 0x0, + .enc_reg_num = REG_NUM_ENC_4831, + .enc_io_size = REG_NUM_ENC_4831 * 4, + .dec_offset = REG_SIZE_ENC_4831, + .dec_reg_num = REG_NUM_9190_DEC_PP, + .dec_io_size = REG_NUM_9190_DEC_PP * 4, + }, +}; + #define DEC_INTERRUPT_REGISTER 1 #define PP_INTERRUPT_REGISTER 60 @@ -55,36 +116,6 @@ #define PP_INTERRUPT_BIT 0x100 #define ENC_INTERRUPT_BIT 0x1 -#define REG_NUM_DEC (60) -#define REG_NUM_PP (41) -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK2928) -#define REG_NUM_ENC (96) -#elif defined(CONFIG_ARCH_RK30) -#define REG_NUM_ENC (164) -#endif -#define REG_NUM_DEC_PP (REG_NUM_DEC+REG_NUM_PP) -#define SIZE_REG(reg) ((reg)*4) - -#define DEC_IO_SIZE ((100 + 1) * 4) /* bytes */ -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK2928) -#define ENC_IO_SIZE (96 * 4) /* bytes */ -#elif defined(CONFIG_ARCH_RK30) -#define ENC_IO_SIZE (164 * 4) /* bytes */ -#endif -#define REG_NUM_DEC_PP (REG_NUM_DEC+REG_NUM_PP) -static const u16 dec_hw_ids[] = { 0x8190, 0x8170, 0x9170, 0x9190, 0x6731 }; -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK2928) -static const u16 enc_hw_ids[] = { 0x6280, 0x7280, 0x8270 }; -#define DEC_PHY_OFFSET 0x200 -#if defined(CONFIG_ARCH_RK2928) -#define RK29_VCODEC_PHYS RK2928_VCODEC_PHYS -#endif -#elif defined(CONFIG_ARCH_RK30) -static const u16 enc_hw_ids[] = { 0x6280, 0x7280, 0x8270, 0x8290, 0x4831 }; -#define DEC_PHY_OFFSET 0x400 -#define RK29_VCODEC_PHYS RK30_VCODEC_PHYS -#endif - #define VPU_REG_EN_ENC 14 #define VPU_REG_ENC_GATE 2 #define VPU_REG_ENC_GATE_BIT (1<<4) @@ -125,14 +156,13 @@ typedef struct vpu_session { * * @author ChenHengming (2011-5-4) */ -#define VPU_REG_NUM_MAX (((VPU_REG_NUM_ENC)>(VPU_REG_NUM_DEC_PP))?(VPU_REG_NUM_ENC):(VPU_REG_NUM_DEC_PP)) typedef struct vpu_reg { VPU_CLIENT_TYPE type; vpu_session *session; struct list_head session_link; /* link to vpu service session */ struct list_head status_link; /* link to register set list */ unsigned long size; - unsigned long reg[VPU_REG_NUM_MAX]; + unsigned long *reg; } vpu_reg; typedef struct vpu_device { @@ -156,6 +186,8 @@ typedef struct vpu_service_info { vpu_reg *reg_resev; VPUHwDecConfig_t dec_config; VPUHwEncConfig_t enc_config; + VPU_HW_INFO_E *hw_info; + unsigned long reg_size; } vpu_service_info; typedef struct vpu_request @@ -211,7 +243,7 @@ static void vpu_reset(void) cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, false); cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, false); clk_enable(aclk_ddr_vepu); -#elif defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928) +#elif defined(CONFIG_ARCH_RK30) pmu_set_idle_request(IDLE_REQ_VIDEO, true); cru_set_soft_reset(SOFT_RST_CPU_VCODEC, true); cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, true); @@ -293,7 +325,7 @@ static void vpu_service_power_off(void) } printk("vpu: power off..."); -#if defined(CONFIG_ARCH_RK29) +#ifdef CONFIG_ARCH_RK29 pmu_set_power_domain(PD_VCODEC, false); #else clk_disable(pd_video); @@ -337,7 +369,7 @@ static void vpu_service_power_on(void) clk_enable(hclk_vepu); clk_enable(hclk_cpu_vcodec); udelay(10); -#if defined(CONFIG_ARCH_RK29) +#ifdef CONFIG_ARCH_RK29 pmu_set_power_domain(PD_VCODEC, true); #else clk_enable(pd_video); @@ -357,7 +389,7 @@ static void vpu_service_power_on(void) static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long size) { unsigned long flag; - vpu_reg *reg = kmalloc(sizeof(vpu_reg), GFP_KERNEL); + vpu_reg *reg = kmalloc(sizeof(vpu_reg)+service.reg_size, GFP_KERNEL); if (NULL == reg) { pr_err("error: kmalloc fail in reg_init\n"); return NULL; @@ -366,6 +398,7 @@ static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long s reg->session = session; reg->type = session->type; reg->size = size; + reg->reg = (unsigned long *)®[1]; INIT_LIST_HEAD(®->session_link); INIT_LIST_HEAD(®->status_link); @@ -420,24 +453,24 @@ static void reg_from_run_to_done(vpu_reg *reg) switch (reg->type) { case VPU_ENC : { service.reg_codec = NULL; - reg_copy_from_hw(reg, enc_dev.hwregs, REG_NUM_ENC); + reg_copy_from_hw(reg, enc_dev.hwregs, service.hw_info->enc_reg_num); break; } case VPU_DEC : { service.reg_codec = NULL; - reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_DEC); + reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_9190_DEC); break; } case VPU_PP : { service.reg_pproc = NULL; - reg_copy_from_hw(reg, dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_PP); + reg_copy_from_hw(reg, dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP); dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0; break; } case VPU_DEC_PP : { service.reg_codec = NULL; service.reg_pproc = NULL; - reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_DEC_PP); + reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_9190_DEC_PP); dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0; break; } @@ -459,6 +492,7 @@ void reg_copy_to_hw(vpu_reg *reg) atomic_add(1, ®->session->task_running); switch (reg->type) { case VPU_ENC : { + int enc_count = service.hw_info->enc_reg_num; u32 *dst = (u32 *)enc_dev.hwregs; #if defined(CONFIG_ARCH_RK30) cru_set_soft_reset(SOFT_RST_CPU_VCODEC, true); @@ -473,7 +507,7 @@ void reg_copy_to_hw(vpu_reg *reg) for (i = 0; i < VPU_REG_EN_ENC; i++) dst[i] = src[i]; - for (i = VPU_REG_EN_ENC + 1; i < REG_NUM_ENC; i++) + for (i = VPU_REG_EN_ENC + 1; i < enc_count; i++) dst[i] = src[i]; dsb(); @@ -485,7 +519,7 @@ void reg_copy_to_hw(vpu_reg *reg) u32 *dst = (u32 *)dec_dev.hwregs; service.reg_codec = reg; - for (i = REG_NUM_DEC - 1; i > VPU_REG_DEC_GATE; i--) + for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--) dst[i] = src[i]; dsb(); @@ -499,7 +533,7 @@ void reg_copy_to_hw(vpu_reg *reg) dst[VPU_REG_PP_GATE] = src[VPU_REG_PP_GATE] | VPU_REG_PP_GATE_BIT; - for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_PP; i++) + for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_9190_PP; i++) dst[i] = src[i]; dsb(); @@ -511,7 +545,7 @@ void reg_copy_to_hw(vpu_reg *reg) service.reg_codec = reg; service.reg_pproc = reg; - for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_DEC_PP; i++) + for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_9190_DEC_PP; i++) dst[i] = src[i]; dst[VPU_REG_EN_DEC_PP] = src[VPU_REG_EN_DEC_PP] | 0x2; @@ -579,22 +613,22 @@ static int return_reg(vpu_reg *reg, u32 __user *dst) int ret = 0; switch (reg->type) { case VPU_ENC : { - if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_ENC))) + if (copy_to_user(dst, ®->reg[0], service.hw_info->enc_io_size)) ret = -EFAULT; break; } case VPU_DEC : { - if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_DEC))) + if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_9190_DEC))) ret = -EFAULT; break; } case VPU_PP : { - if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_PP))) + if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_9190_PP))) ret = -EFAULT; break; } case VPU_DEC_PP : { - if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_DEC_PP))) + if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_9190_DEC_PP))) ret = -EFAULT; break; } @@ -713,33 +747,46 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long return 0; } -static int vpu_service_check_hw_id(struct vpu_device * dev, const u16 *hwids, size_t num) +static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr) { - u32 hwid = readl(dev->hwregs); - pr_info("HW ID = 0x%08x\n", hwid); - - hwid = (hwid >> 16) & 0xFFFF; /* product version only */ - - while (num--) { - if (hwid == hwids[num]) { - pr_info("Compatible HW found at 0x%08lx\n", dev->iobaseaddr); - return 1; + int ret = -EINVAL, i = 0; + volatile u32 *tmp = (volatile u32 *)ioremap_nocache(hw_addr, 0x4); + u32 enc_id = *tmp; + enc_id = (enc_id >> 16) & 0xFFFF; + pr_info("checking hw id %x\n", enc_id); + p->hw_info = NULL; + for (i = 0; i < ARRAY_SIZE(vpu_hw_set); i++) { + if (enc_id == vpu_hw_set[i].hw_id) { + p->hw_info = &vpu_hw_set[i]; + ret = 0; + break; } } - - pr_info("No Compatible HW found at 0x%08lx\n", dev->iobaseaddr); - return 0; + iounmap((void *)tmp); + return ret; } static void vpu_service_release_io(void) { - if (dec_dev.hwregs) + if (dec_dev.hwregs) { iounmap((void *)dec_dev.hwregs); - release_mem_region(dec_dev.iobaseaddr, dec_dev.iosize); + dec_dev.hwregs = NULL; + } + if (dec_dev.iobaseaddr) { + release_mem_region(dec_dev.iobaseaddr, dec_dev.iosize); + dec_dev.iobaseaddr = 0; + dec_dev.iosize = 0; + } - if (enc_dev.hwregs) + if (enc_dev.hwregs) { iounmap((void *)enc_dev.hwregs); - release_mem_region(enc_dev.iobaseaddr, enc_dev.iosize); + enc_dev.hwregs = NULL; + } + if (enc_dev.iobaseaddr) { + release_mem_region(enc_dev.iobaseaddr, enc_dev.iosize); + enc_dev.iobaseaddr = 0; + enc_dev.iosize = 0; + } } static int vpu_service_reserve_io(void) @@ -762,15 +809,10 @@ static int vpu_service_reserve_io(void) goto err; } - /* check for correct HW */ - if (!vpu_service_check_hw_id(&dec_dev, dec_hw_ids, ARRAY_SIZE(dec_hw_ids))) { - goto err; - } - iobaseaddr = enc_dev.iobaseaddr; iosize = enc_dev.iosize; - if (!request_mem_region(iobaseaddr, iosize, "hx280enc")) { + if (!request_mem_region(iobaseaddr, iosize, "vepu_io")) { pr_info("failed to reserve enc HW regs\n"); goto err; } @@ -782,14 +824,9 @@ static int vpu_service_reserve_io(void) goto err; } - /* check for correct HW */ - if (!vpu_service_check_hw_id(&enc_dev, enc_hw_ids, ARRAY_SIZE(enc_hw_ids))) { - goto err; - } return 0; err: - vpu_service_release_io(); return -EBUSY; } @@ -1075,9 +1112,11 @@ static void get_hw_info(void) enc->jpegEnabled = (configReg >> 25) & 1; enc->vsEnabled = (configReg >> 24) & 1; enc->rgbEnabled = (configReg >> 28) & 1; - enc->busType = (configReg >> 20) & 15; - enc->synthesisLanguage = (configReg >> 16) & 15; - enc->busWidth = (configReg >> 12) & 15; + //enc->busType = (configReg >> 20) & 15; + //enc->synthesisLanguage = (configReg >> 16) & 15; + //enc->busWidth = (configReg >> 12) & 15; + enc->reg_size = service.reg_size; + enc->reserv[0] = enc->reserv[1] = 0; } static irqreturn_t vdpu_isr(int irq, void *dev_id) @@ -1152,12 +1191,7 @@ static int __init vpu_service_init(void) { int ret; - pr_debug("baseaddr = 0x%08x vdpu irq = %d vepu irq = %d\n", RK29_VCODEC_PHYS, IRQ_VDPU, IRQ_VEPU); - - dec_dev.iobaseaddr = RK29_VCODEC_PHYS + DEC_PHY_OFFSET; - dec_dev.iosize = DEC_IO_SIZE; - enc_dev.iobaseaddr = RK29_VCODEC_PHYS; - enc_dev.iosize = ENC_IO_SIZE; + pr_debug("baseaddr = 0x%08x vdpu irq = %d vepu irq = %d\n", VCODEC_PHYS, IRQ_VDPU, IRQ_VEPU); INIT_LIST_HEAD(&service.waiting); INIT_LIST_HEAD(&service.running); @@ -1175,6 +1209,17 @@ static int __init vpu_service_init(void) service.timer.expires = jiffies + POWER_OFF_DELAY; service.timer.function = vpu_service_power_off_work_func; vpu_service_power_on(); + ret = vpu_service_check_hw(&service, VCODEC_PHYS); + if (ret < 0) { + pr_err("error: hw info check faild\n"); + goto err_hw_id_check; + } + + dec_dev.iobaseaddr = service.hw_info->hw_addr + service.hw_info->dec_offset; + dec_dev.iosize = service.hw_info->dec_io_size; + enc_dev.iobaseaddr = service.hw_info->hw_addr + service.hw_info->enc_offset; + enc_dev.iosize = service.hw_info->enc_io_size;; + service.reg_size = max(dec_dev.iosize, enc_dev.iosize); ret = vpu_service_reserve_io(); if (ret < 0) { @@ -1204,6 +1249,7 @@ static int __init vpu_service_init(void) platform_device_register(&vpu_service_device); platform_driver_probe(&vpu_service_driver, NULL); get_hw_info(); + del_timer(&service.timer); vpu_service_power_off(); pr_info("init success\n"); @@ -1217,15 +1263,18 @@ err_req_vepu_irq: err_req_vdpu_irq: pr_info("init failed\n"); err_reserve_io: - vpu_service_power_off(); vpu_service_release_io(); +err_hw_id_check: + vpu_service_power_off(); vpu_put_clk(); pr_info("init failed\n"); return ret; } +static void __exit vpu_service_proc_release(void); static void __exit vpu_service_exit(void) { + vpu_service_proc_release(); del_timer(&service.timer); vpu_service_power_off(); platform_device_unregister(&vpu_service_device); @@ -1233,6 +1282,7 @@ static void __exit vpu_service_exit(void) misc_deregister(&vpu_service_misc_device); free_irq(IRQ_VEPU, (void *)&enc_dev); free_irq(IRQ_VDPU, (void *)&dec_dev); + vpu_service_release_io(); vpu_put_clk(); } @@ -1300,5 +1350,9 @@ static int __init vpu_service_proc_init(void) return 0; } +static void __exit vpu_service_proc_release(void) +{ + remove_proc_entry("vpu_service", NULL); +} #endif /* CONFIG_PROC_FS */ diff --git a/drivers/video/rockchip/chips/rk31_lcdc.c b/drivers/video/rockchip/chips/rk31_lcdc.c index 29dff742a256..20d0362f3b37 100644 --- a/drivers/video/rockchip/chips/rk31_lcdc.c +++ b/drivers/video/rockchip/chips/rk31_lcdc.c @@ -76,6 +76,9 @@ static int init_rk31_lcdc(struct rk_lcdc_device_driver *dev_drv) LcdMskReg(lcdc_dev,SYS_CFG, m_LCDC_AXICLK_AUTO_ENABLE | m_W0_AXI_OUTSTANDING2 | m_W1_AXI_OUTSTANDING2,v_LCDC_AXICLK_AUTO_ENABLE(1) | v_W0_AXI_OUTSTANDING2(1) | v_W1_AXI_OUTSTANDING2(1));//eanble axi-clk auto gating for low power + LcdWrReg(lcdc_dev,AXI_MS_ID,v_HWC_CHANNEL_ID(5) | v_WIN2_CHANNEL_ID(4) | + v_WIN1_YRGB_CHANNEL_ID(3) | v_WIN0_CBR_CHANNEL_ID(2) | + v_WIN0_YRGB_CHANNEL_ID(1)); LcdMskReg(lcdc_dev, INT_STATUS,m_HOR_STARTMASK| m_FRM_STARTMASK | m_SCANNING_MASK, v_HOR_STARTMASK(1) | v_FRM_STARTMASK(1) | v_SCANNING_MASK(1)); //mask all interrupt in init @@ -385,6 +388,7 @@ static int win0_set_par(struct rk31_lcdc_device *lcdc_dev,rk_screen *screen, u32 ScaleYrgbY = 0x1000; u32 ScaleCbrX = 0x1000; u32 ScaleCbrY = 0x1000; + u8 fmt_cfg =0 ; //data format register config value xact = par->xact; //active (origin) picture window width/height yact = par->yact; @@ -399,17 +403,23 @@ static int win0_set_par(struct rk31_lcdc_device *lcdc_dev,rk_screen *screen, switch (par->format) { case ARGB888: - par->format = RGB888; + fmt_cfg = 0; + break; + case RGB565: + fmt_cfg = 1; break; case YUV422:// yuv422 + fmt_cfg = 2; ScaleCbrX = CalScale((xact/2), par->xsize); ScaleCbrY = CalScale(yact, par->ysize); break; case YUV420: // yuv420 + fmt_cfg = 3; ScaleCbrX = CalScale(xact/2, par->xsize); ScaleCbrY = CalScale(yact/2, par->ysize); break; case YUV444:// yuv444 + fmt_cfg = 4; ScaleCbrX = CalScale(xact, par->xsize); ScaleCbrY = CalScale(yact, par->ysize); break; @@ -425,7 +435,7 @@ static int win0_set_par(struct rk31_lcdc_device *lcdc_dev,rk_screen *screen, { LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY)); LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_CBR,v_X_SCL_FACTOR(ScaleCbrX)| v_Y_SCL_FACTOR(ScaleCbrY)); - LcdMskReg(lcdc_dev,SYS_CFG, m_W0_FORMAT, v_W0_FORMAT(par->format - 1)); //(inf->video_mode==0) + LcdMskReg(lcdc_dev,SYS_CFG, m_W0_FORMAT, v_W0_FORMAT(fmt_cfg)); //(inf->video_mode==0) LcdWrReg(lcdc_dev, WIN0_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact)); LcdWrReg(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(xpos) | v_DSP_STY(ypos)); LcdWrReg(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(par->xsize)| v_DSP_HEIGHT(par->ysize)); @@ -448,6 +458,7 @@ static int win1_set_par(struct rk31_lcdc_device *lcdc_dev,rk_screen *screen, u32 ScaleYrgbY = 0x1000; u32 ScaleCbrX = 0x1000; u32 ScaleCbrY = 0x1000; + u8 fmt_cfg; xact = par->xact; yact = par->yact; @@ -468,25 +479,16 @@ static int win1_set_par(struct rk31_lcdc_device *lcdc_dev,rk_screen *screen, switch (par->format) { case ARGB888: - par->format = RGB888; + fmt_cfg = 0; break; - case YUV422:// yuv422 - ScaleCbrX = CalScale((xact/2), par->xsize); - ScaleCbrY = CalScale(yact, par->ysize); - break; - case YUV420: // yuv420 - ScaleCbrX = CalScale(xact/2, par->xsize); - ScaleCbrY = CalScale(yact/2, par->ysize); - break; - case YUV444:// yuv444 - ScaleCbrX = CalScale(xact, par->xsize); - ScaleCbrY = CalScale(yact, par->ysize); + case RGB565: + fmt_cfg = 1; break; default: break; } - LcdMskReg(lcdc_dev,SYS_CFG, m_W1_FORMAT, v_W1_FORMAT(par->format - 1)); + LcdMskReg(lcdc_dev,SYS_CFG, m_W1_FORMAT, v_W1_FORMAT(fmt_cfg)); LcdWrReg(lcdc_dev, WIN1_DSP_ST,v_DSP_STX(xpos) | v_DSP_STY(ypos)); LcdWrReg(lcdc_dev, WIN1_DSP_INFO,v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize)); // enable win1 color key and set the color to black(rgb=0) diff --git a/drivers/video/rockchip/chips/rk31_lcdc.h b/drivers/video/rockchip/chips/rk31_lcdc.h index 25c6044d8688..c3abd092b04b 100644 --- a/drivers/video/rockchip/chips/rk31_lcdc.h +++ b/drivers/video/rockchip/chips/rk31_lcdc.h @@ -376,6 +376,17 @@ #define v_WIN2_FIFO_FULL_LEVEL(x) (((x)&0x1f) << 7) +#define m_WIN0_YRGB_CHANNEL_ID ((0x0f)<<0) +#define m_WIN0_CBR_CHANNEL_ID ((0x0f)<<4) +#define m_WIN1_YRGB_CHANNEL_ID ((0x0f)<<8) +#define m_WIN2_CHANNEL_ID ((0x0f)<<12) +#define m_HWC_CHANNEL_ID ((0x0f)<<16) +#define v_WIN0_YRGB_CHANNEL_ID(x) (((x)&0x0f)<<0) +#define v_WIN0_CBR_CHANNEL_ID(x) (((x)&0x0f)<<4) +#define v_WIN1_YRGB_CHANNEL_ID(x) (((x)&0x0f)<<8) +#define v_WIN2_CHANNEL_ID(x) (((x)&0x0f)<<12) +#define v_HWC_CHANNEL_ID(x) (((x)&0x0f)<<16) + //LCDC_WINx_SCL_FACTOR_Y/CBCR #define v_X_SCL_FACTOR(x) ((x)<<0) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index b6197e690606..f25d6a115422 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -176,7 +176,7 @@ static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) par->y_offset = (yoffset*xvir + xoffset)*4; break; case RGB888: - par->y_offset = (yoffset*xvir + xoffset)*4; + par->y_offset = (yoffset*xvir + xoffset)*3; break; case RGB565: par->y_offset = (yoffset*xvir + xoffset)*2;