#include "vcodec_service.h"\r
\r
#define HEVC_TEST_ENABLE 0\r
-#define HEVC_SIM_ENABLE 1\r
+#define HEVC_SIM_ENABLE 0\r
\r
typedef enum {\r
VPU_DEC_ID_9190 = 0x6731,\r
\r
#define MHZ (1000*1000)\r
\r
-#if 0\r
-#if defined(CONFIG_ARCH_RK319X)\r
-#define VCODEC_PHYS RK319X_VCODEC_PHYS\r
-#else\r
-#define VCODEC_PHYS (0x10104000)\r
-#endif\r
-#endif\r
-\r
#define REG_NUM_9190_DEC (60)\r
#define REG_NUM_9190_PP (41)\r
#define REG_NUM_9190_DEC_PP (REG_NUM_9190_DEC+REG_NUM_9190_PP)\r
volatile u32 *hwregs;\r
} vpu_device;\r
\r
+enum vcodec_device_id {\r
+ VCODEC_DEVICE_ID_VPU,\r
+ VCODEC_DEVICE_ID_HEVC\r
+};\r
+\r
typedef struct vpu_service_info {\r
struct wake_lock wake_lock;\r
struct delayed_work power_off_work;\r
\r
struct clk *aclk_vcodec;\r
struct clk *hclk_vcodec;\r
+ struct clk *clk_core;\r
+ struct clk *clk_cabac;\r
\r
int irq_dec;\r
int irq_enc;\r
struct dentry *debugfs_file_regs;\r
\r
u32 irq_status;\r
+#if defined(CONFIG_ION_ROCKCHIP) \r
struct ion_client * ion_client;\r
+#endif \r
+\r
+ enum vcodec_device_id dev_id;\r
\r
struct delayed_work simulate_work;\r
} vpu_service_info;\r
#define VPU_POWER_OFF_DELAY 4*HZ /* 4s */\r
#define VPU_TIMEOUT_DELAY 2*HZ /* 2s */\r
\r
-#define VPU_SIMULATE_DELAY msecs_to_jiffies(5)\r
+#define VPU_SIMULATE_DELAY msecs_to_jiffies(15)\r
\r
static void vpu_get_clk(struct vpu_service_info *pservice)\r
{\r
if (IS_ERR(pd_video)) {\r
pr_err("failed on clk_get pd_video\n");\r
}*/\r
+\r
pservice->aclk_vcodec = devm_clk_get(pservice->dev, "aclk_vcodec");\r
if (IS_ERR(pservice->aclk_vcodec)) {\r
dev_err(pservice->dev, "failed on clk_get aclk_vcodec\n");\r
}\r
+\r
pservice->hclk_vcodec = devm_clk_get(pservice->dev, "hclk_vcodec");\r
if (IS_ERR(pservice->hclk_vcodec)) {\r
dev_err(pservice->dev, "failed on clk_get hclk_vcodec\n");\r
}\r
+\r
+ if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+ pservice->clk_core = devm_clk_get(pservice->dev, "clk_core");\r
+ if (IS_ERR(pservice->clk_core)) {\r
+ dev_err(pservice->dev, "failed on clk_get clk_core\n");\r
+ }\r
+\r
+ pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");\r
+ if (IS_ERR(pservice->clk_cabac)) {\r
+ dev_err(pservice->dev, "failed on clk_get clk_cabac\n");\r
+ }\r
+ }\r
}\r
\r
static void vpu_put_clk(struct vpu_service_info *pservice)\r
if (pservice->hclk_vcodec) {\r
devm_clk_put(pservice->dev, pservice->hclk_vcodec);\r
}\r
+\r
+ if (pservice->hw_info->hw_id == HEVC_ID) {\r
+ if (pservice->clk_core) {\r
+ devm_clk_put(pservice->dev, pservice->clk_core);\r
+ }\r
+ \r
+ if (pservice->clk_cabac) {\r
+ devm_clk_put(pservice->dev, pservice->clk_cabac);\r
+ }\r
+ }\r
}\r
\r
static void vpu_reset(struct vpu_service_info *pservice)\r
//clk_disable(pd_video);\r
#endif\r
udelay(10);\r
- //clk_disable(hclk_cpu_vcodec);\r
- //clk_disable(aclk_ddr_vepu);\r
#if 0\r
clk_disable_unprepare(pservice->hclk_vcodec);\r
clk_disable_unprepare(pservice->aclk_vcodec);\r
+ if (pservice->hw_info->hw_id == HEVC_ID) {\r
+ clk_disable_unprepare(pservice->clk_core);\r
+ clk_disable_unprepare(pservice->clk_cabac);\r
+ }\r
#endif\r
wake_unlock(&pservice->wake_lock);\r
printk("done\n");\r
#if 0\r
clk_prepare_enable(pservice->aclk_vcodec);\r
clk_prepare_enable(pservice->hclk_vcodec);\r
+ if (pservice->hw_info->hw_id == HEVC_ID) {\r
+ clk_prepare_enable(pservice->clk_core);\r
+ clk_prepare_enable(pservice->clk_cabac);\r
+ }\r
#endif\r
- //clk_prepare_enable(hclk_cpu_vcodec);\r
+\r
#if defined(CONFIG_ARCH_RK319X)\r
/// select aclk_vepu as vcodec clock source. \r
#define BIT_VCODEC_SEL (1<<7)\r
//clk_enable(pd_video);\r
#endif\r
udelay(10);\r
- //clk_enable(aclk_ddr_vepu);\r
wake_lock(&pservice->wake_lock);\r
}\r
\r
} break;\r
case VPU_DEC : {\r
u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
+\r
pservice->reg_codec = reg;\r
\r
- for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
- dst[i] = src[i];\r
+ if (pservice->hw_info->hw_id != HEVC_ID) {\r
+ for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
+ dst[i] = src[i];\r
+ } else {\r
+ for (i = REG_NUM_HEVC_DEC - 1; i > VPU_REG_EN_DEC; i--) {\r
+ dst[i] = src[i];\r
+ }\r
+ }\r
\r
dsb();\r
\r
- dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
- dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
+ if (pservice->hw_info->hw_id != HEVC_ID) {\r
+ dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
+ dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
+ } else {\r
+ dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
+ }\r
+ dsb();\r
+ dmb();\r
\r
#if VPU_SERVICE_SHOW_TIME\r
do_gettimeofday(&dec_start);\r
of_property_read_string(np, "name", (const char**)&prop);\r
dev_set_name(dev, prop);\r
\r
+ if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
+ pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
+ } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
+ pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
+ } else {\r
+ dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
+ return -1;\r
+ }\r
+\r
wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
INIT_LIST_HEAD(&pservice->waiting);\r
INIT_LIST_HEAD(&pservice->running);\r
struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
vpu_device *dev = &pservice->dec_dev;\r
u32 irq_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
+ int i;\r
\r
pr_debug("dec_irq\n");\r
\r
\r
#endif\r
\r
-#if HEVC_TEST_ENABLE\r
+#if HEVC_TEST_ENABLE & defined(CONFIG_ION_ROCKCHIP)\r
#include "hevc_test_inc/pps_00.h"\r
#include "hevc_test_inc/register_00.h"\r
#include "hevc_test_inc/rps_00.h"\r
\r
#include "hevc_test_inc/cabac.h"\r
\r
+extern struct ion_client *rockchip_ion_client_create(const char * name);\r
+\r
+static struct ion_client *ion_client = NULL;\r
+u8* get_align_ptr(u8* tbl, int len, u32 *phy)\r
+{\r
+ int size = (len+15) & (~15);\r
+ struct ion_handle *handle;\r
+ u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
+\r
+ if (ion_client == NULL) {\r
+ ion_client = rockchip_ion_client_create("vcodec");\r
+ }\r
+\r
+ handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+\r
+ ptr = ion_map_kernel(ion_client, handle);\r
+\r
+ ion_phys(ion_client, handle, phy, &size);\r
+\r
+ memcpy(ptr, tbl, len);\r
+\r
+ return ptr;\r
+}\r
+\r
+u8* get_align_ptr_no_copy(int len, u32 *phy)\r
+{\r
+ int size = (len+15) & (~15);\r
+ struct ion_handle *handle;\r
+ u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
+\r
+ if (ion_client == NULL) {\r
+ ion_client = rockchip_ion_client_create("vcodec");\r
+ }\r
+\r
+ handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+\r
+ ptr = ion_map_kernel(ion_client, handle);\r
+\r
+ ion_phys(ion_client, handle, phy, &size);\r
+\r
+ return ptr;\r
+}\r
+\r
#define TEST_CNT 2\r
static int hevc_test_case0(vpu_service_info *pservice)\r
{\r
vpu_session session;\r
vpu_reg *reg; \r
- unsigned long size = sizeof(register_00); // registers array length\r
+ unsigned long size = 272;//sizeof(register_00); // registers array length\r
int testidx = 0;\r
int ret = 0;\r
\r
u8 *scaling_list_tbl[TEST_CNT];\r
u8 *stream_tbl[TEST_CNT];\r
\r
- int stream_size[2];\r
-\r
+ int stream_size[2];\r
+ int pps_size[2];\r
+ int rps_size[2];\r
+ int scl_size[2];\r
+ int cabac_size[2];\r
+ \r
u32 phy_pps;\r
u32 phy_rps;\r
u32 phy_scl;\r
u32 phy_str;\r
u32 phy_yuv;\r
+ u32 phy_ref;\r
u32 phy_cabac;\r
\r
+ volatile u8 *stream_buf;\r
+ volatile u8 *pps_buf;\r
+ volatile u8 *rps_buf;\r
+ volatile u8 *scl_buf;\r
+ volatile u8 *yuv_buf;\r
+ volatile u8 *cabac_buf;\r
+ volatile u8 *ref_buf;\r
+\r
u8 *pps;\r
- u8 *yuv;\r
+ u8 *yuv[2];\r
int i;\r
\r
pps_tbl[0] = pps_00;\r
stream_size[0] = sizeof(stream_00);\r
stream_size[1] = sizeof(stream_01);\r
\r
+ pps_size[0] = sizeof(pps_00);\r
+ pps_size[1] = sizeof(pps_01);\r
+\r
+ rps_size[0] = sizeof(rps_00);\r
+ rps_size[1] = sizeof(rps_01);\r
+\r
+ scl_size[0] = sizeof(scaling_list_00);\r
+ scl_size[1] = sizeof(scaling_list_01);\r
+ \r
+ cabac_size[0] = sizeof(Cabac_table);\r
+ cabac_size[1] = sizeof(Cabac_table);\r
+\r
// create session\r
session.pid = current->pid;\r
session.type = VPU_DEC;\r
atomic_set(&session.task_running, 0);\r
list_add_tail(&session.list_session, &pservice->session);\r
\r
- while (testidx < TEST_CNT) {\r
+ yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
+ yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
+\r
+ while (testidx < TEST_CNT) {\r
+ \r
// create registers\r
reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
if (NULL == reg) {\r
return -1;\r
}\r
\r
+\r
if (size > pservice->reg_size) {\r
printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
size = pservice->reg_size;\r
INIT_LIST_HEAD(®->session_link);\r
INIT_LIST_HEAD(®->status_link);\r
\r
- pps = kmalloc(sizeof(pps_00), GFP_KERNEL);\r
- yuv = kzalloc(256*256*3/2, GFP_KERNEL);\r
- memcpy(pps, pps_tbl[testidx], sizeof(pps_00));\r
-\r
// TODO: stuff registers\r
- memcpy(®->reg[0], register_tbl[testidx], sizeof(register_00));\r
+ memcpy(®->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
+\r
+ stream_buf = get_align_ptr(stream_tbl[testidx], stream_size[testidx], &phy_str);\r
+ pps_buf = get_align_ptr(pps_tbl[0], pps_size[0], &phy_pps);\r
+ rps_buf = get_align_ptr(rps_tbl[testidx], rps_size[testidx], &phy_rps);\r
+ scl_buf = get_align_ptr(scaling_list_tbl[testidx], scl_size[testidx], &phy_scl);\r
+ cabac_buf = get_align_ptr(Cabac_table, cabac_size[testidx], &phy_cabac);\r
+\r
+ pps = pps_buf;\r
\r
// TODO: replace reigster address\r
- phy_pps = virt_to_phys(pps);\r
- phy_rps = virt_to_phys(rps_tbl[testidx]);\r
- phy_scl = virt_to_phys(scaling_list_tbl[testidx]);\r
- phy_str = virt_to_phys(stream_tbl[testidx]);\r
- phy_yuv = virt_to_phys(yuv);\r
- phy_cabac = virt_to_phys(Cabac_table);\r
\r
for (i=0; i<64; i++) {\r
u32 scaling_offset;\r
pps[i*80+77] = (tmp >> 24) & 0xff;\r
}\r
\r
- dmac_flush_range(&pps[0], &pps[sizeof(pps_00) - 1]);\r
- outer_flush_range(phy_pps, phy_pps + sizeof(pps_00) - 1);\r
-\r
printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n", __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
\r
+ reg->reg[1] = 0x21;\r
reg->reg[4] = phy_str;\r
reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
reg->reg[6] = phy_cabac;\r
- reg->reg[7] = phy_yuv;\r
+ reg->reg[7] = testidx?phy_ref:phy_yuv;\r
reg->reg[42] = phy_pps;\r
reg->reg[43] = phy_rps;\r
+ for (i = 10; i <= 24; i++) {\r
+ reg->reg[i] = phy_yuv;\r
+ }\r
\r
mutex_lock(&pservice->lock);\r
list_add_tail(®->status_link, &pservice->waiting);\r
}\r
\r
pr_err("test index %d failed\n", testidx);\r
- kfree(pps);\r
- kfree(yuv);\r
break;\r
} else {\r
pr_info("test index %d success\n", testidx);\r
}\r
\r
reg_deinit(pservice, reg);\r
- kfree(pps);\r
- kfree(yuv);\r
}\r
\r
return 0;\r