rk3036, rk312x: add iommu switch in dts for vcodec and iep

This commit is contained in:
ljf
2014-08-08 09:46:48 +08:00
parent d0d6b8b1e3
commit b2076f04e8
5 changed files with 83 additions and 65 deletions

View File

@@ -643,8 +643,9 @@
};
};
vpu: vpu_service@10108000 {
vpu: vpu_service@10108000 {
compatible = "vpu_service";
iommu_enabled = <1>;
reg = <0x10108000 0x800>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq_dec";
@@ -656,6 +657,7 @@
hevc: hevc_service@1010c000 {
compatible = "rockchip,hevc_service";
iommu_enabled = <1>;
reg = <0x1010c000 0x400>;
interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq_dec";
@@ -663,7 +665,7 @@
clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core";
name = "hevc_service";
status = "okay";
};
};
vop_mmu {
dbgname = "vop";

View File

@@ -657,6 +657,7 @@
vpu: vpu_service@10106000 {
compatible = "vpu_service";
iommu_enabled = <1>;
reg = <0x10106000 0x800>;
interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq_enc", "irq_dec";
@@ -668,6 +669,7 @@
hevc: hevc_service@10104000 {
compatible = "rockchip,hevc_service";
iommu_enabled = <1>;
reg = <0x10104000 0x400>;
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq_dec";
@@ -679,6 +681,7 @@
iep: iep@10108000 {
compatible = "rockchip,iep";
iommu_enabled = <1>;
reg = <0x10108000 0x800>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates9 8>, <&clk_gates9 7>;

View File

@@ -405,9 +405,9 @@ static const struct file_operations debug_vcodec_fops = {
#define BIT_VCODEC_SEL_RK312X (1<<15)
static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mode)
{
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128()) {
int bits = soc_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
void __iomem *addr = soc_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
if (cpu_is_rk3036() || cpu_is_rk312x()) {
int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
if (reserved_mode)
*reserved_mode = readl_relaxed(addr);
if (id == VCODEC_DEVICE_ID_HEVC)
@@ -419,23 +419,23 @@ static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mod
static void vcodec_exit_mode_nolock(enum vcodec_device_id id, u32 reserved_mode)
{
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128()) {
int bits = soc_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
void __iomem *addr = soc_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
if (cpu_is_rk3036() || cpu_is_rk312x()) {
int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
writel_relaxed(reserved_mode | (bits << 16), addr);
}
}
static void vcodec_enter_mode(enum vcodec_device_id id)
{
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
if (cpu_is_rk3036() || cpu_is_rk312x())
mutex_lock(&g_mode_mutex);
vcodec_enter_mode_nolock(id, NULL);
}
static void vcodec_exit_mode(void)
{
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
if (cpu_is_rk3036() || cpu_is_rk312x())
mutex_unlock(&g_mode_mutex);
}
@@ -462,7 +462,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
break;
}
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");
if (IS_ERR(pservice->clk_cabac)) {
dev_err(pservice->dev, "failed on clk_get clk_cabac\n");
@@ -472,7 +472,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
pservice->clk_cabac = NULL;
}
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
pservice->pd_video = devm_clk_get(pservice->dev, "pd_hevc");
if (IS_ERR(pservice->pd_video)) {
dev_err(pservice->dev, "failed on clk_get pd_hevc\n");
@@ -482,7 +482,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
pservice->pd_video = NULL;
}
} else {
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");
if (IS_ERR(pservice->pd_video)) {
dev_err(pservice->dev, "failed on clk_get pd_video\n");
@@ -493,7 +493,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
}
}
if (soc_is_rk3126() || soc_is_rk3128()) {
if (cpu_is_rk312x()) {
pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");
if (IS_ERR(pservice->pd_video)) {
dev_err(pservice->dev, "failed on clk_get pd_video\n");
@@ -1415,7 +1415,7 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long
return 0;
}
#if 1
static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
{
int ret = -EINVAL, i = 0;
@@ -1442,7 +1442,6 @@ static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
iounmap((void *)tmp);
return ret;
}
#endif
static int vpu_service_open(struct inode *inode, struct file *filp)
{
@@ -1554,7 +1553,9 @@ static int vcodec_probe(struct platform_device *pdev)
struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);
char *prop = (char*)dev_name(dev);
#if defined(CONFIG_VCODEC_MMU)
u32 iommu_en = 0;
char mmu_dev_dts_name[40];
of_property_read_u32(np, "iommu_enabled", &iommu_en);
#endif
pr_info("probe device %s\n", dev_name(dev));
@@ -1584,7 +1585,7 @@ static int vcodec_probe(struct platform_device *pdev)
pservice->reg_pproc = NULL;
atomic_set(&pservice->total_running, 0);
pservice->enabled = false;
#if defined(CONFIG_VCODEC_MMU)
#if defined(CONFIG_VCODEC_MMU)
pservice->mmu_dev = NULL;
#endif
pservice->dev = dev;
@@ -1610,7 +1611,7 @@ static int vcodec_probe(struct platform_device *pdev)
{
u32 offset = res->start;
if (soc_is_rk3036()) {
if (cpu_is_rk3036()) {
if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)
offset += 0x400;
}
@@ -1629,7 +1630,7 @@ static int vcodec_probe(struct platform_device *pdev)
pservice->reg_size = pservice->dec_dev.iosize;
if (pservice->hw_info->hw_id != HEVC_ID && !soc_is_rk3036()) {
if (pservice->hw_info->hw_id != HEVC_ID && !cpu_is_rk3036()) {
pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;
pservice->enc_dev.iosize = pservice->hw_info->enc_io_size;
@@ -1716,23 +1717,26 @@ static int vcodec_probe(struct platform_device *pdev)
#endif
#if defined(CONFIG_VCODEC_MMU)
pservice->ion_client = rockchip_ion_client_create("vpu");
if (IS_ERR(pservice->ion_client)) {
dev_err(&pdev->dev, "failed to create ion client for vcodec");
return PTR_ERR(pservice->ion_client);
} else {
dev_info(&pdev->dev, "vcodec ion client create success!\n");
}
if (iommu_en) {
pservice->ion_client = rockchip_ion_client_create("vpu");
if (IS_ERR(pservice->ion_client)) {
dev_err(&pdev->dev, "failed to create ion client for vcodec");
return PTR_ERR(pservice->ion_client);
} else {
dev_info(&pdev->dev, "vcodec ion client create success!\n");
}
if (pservice->hw_info->hw_id == HEVC_ID)
sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");
else
sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");
pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);
if (pservice->hw_info->hw_id == HEVC_ID)
sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");
else
sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");
if (pservice->mmu_dev) {
platform_set_sysmmu(pservice->mmu_dev, pservice->dev);
iovmm_activate(pservice->dev);
pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);
if (pservice->mmu_dev) {
platform_set_sysmmu(pservice->mmu_dev, pservice->dev);
iovmm_activate(pservice->dev);
}
}
#endif
@@ -1844,7 +1848,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
if (soc_is_rk3190() || soc_is_rk3288())
dec->maxDecPicWidth = 4096;
else if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
else if (cpu_is_rk3036() || cpu_is_rk312x())
dec->maxDecPicWidth = 1920;
else
dec->maxDecPicWidth = configReg & 0x07FFU;
@@ -1878,7 +1882,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
dec->refBufSupport |= 8; /* enable HW support for offset */
/// invalidate fuse register value in rk319x vpu and following.
if (!soc_is_rk3190() && !soc_is_rk3288() && !soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
if (!soc_is_rk3190() && !soc_is_rk3288() && !cpu_is_rk3036() && !cpu_is_rk312x()) {
VPUHwFuseStatus_t hwFuseSts;
/* Decoder fuse configuration */
u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
@@ -1995,7 +1999,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
}
}
if (!soc_is_rk3036()) {
if (!cpu_is_rk3036()) {
configReg = pservice->enc_dev.hwregs[63];
enc->maxEncodedWidth = configReg & ((1 << 11) - 1);
enc->h264Enabled = (configReg >> 27) & 1;
@@ -2018,7 +2022,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
pservice->bug_dec_addr = cpu_is_rk30xx();
} else {
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
if (cpu_is_rk3036() || cpu_is_rk312x())
dec->maxDecPicWidth = 1920;
else
dec->maxDecPicWidth = 4096;

View File

@@ -1195,7 +1195,7 @@ void iep_config(iep_session *session, IEP_MSG *iep_msg)
#if defined(CONFIG_IEP_IOMMU)
INIT_LIST_HEAD(&reg->mem_region_list);
#endif
#endif
//write config
iep_config_src_size(iep_msg);
@@ -1249,10 +1249,12 @@ void iep_config(iep_session *session, IEP_MSG *iep_msg)
#endif
#if defined(CONFIG_IEP_IOMMU)
if (0 > iep_reg_address_translate(&iep_service, reg)) {
IEP_ERR("error: translate reg address failed\n");
kfree(reg);
return;
if (iep_service.iommu_dev) {
if (0 > iep_reg_address_translate(&iep_service, reg)) {
IEP_ERR("error: translate reg address failed\n");
kfree(reg);
return;
}
}
#endif

View File

@@ -79,11 +79,13 @@ static void iep_reg_deinit(struct iep_reg *reg)
#if defined(CONFIG_IEP_IOMMU)
struct iep_mem_region *mem_region = NULL, *n;
// release memory region attach to this registers table.
list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {
ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);
ion_free(iep_service.ion_client, mem_region->hdl);
list_del_init(&mem_region->reg_lnk);
kfree(mem_region);
if (iep_service.iommu_dev) {
list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {
ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);
ion_free(iep_service.ion_client, mem_region->hdl);
list_del_init(&mem_region->reg_lnk);
kfree(mem_region);
}
}
#endif
list_del_init(&reg->session_link);
@@ -797,7 +799,10 @@ static int iep_drv_probe(struct platform_device *pdev)
int ret = 0;
struct resource *res = NULL;
#if defined(CONFIG_IEP_IOMMU)
u32 iommu_en = 0;
struct device *mmu_dev = NULL;
struct device_node *np = pdev->dev.of_node;
of_property_read_u32(np, "iommu_enabled", &iommu_en);
#endif
data = (struct iep_drvdata*)devm_kzalloc(&pdev->dev, sizeof(struct iep_drvdata), GFP_KERNEL);
@@ -884,24 +889,26 @@ static int iep_drv_probe(struct platform_device *pdev)
#if defined(CONFIG_IEP_IOMMU)
iep_service.iommu_dev = NULL;
iep_power_on();
iep_service.ion_client = rockchip_ion_client_create("iep");
if (IS_ERR(iep_service.ion_client)) {
IEP_ERR("failed to create ion client for vcodec");
return PTR_ERR(iep_service.ion_client);
} else {
IEP_INFO("iep ion client create success!\n");
if (iommu_en) {
iep_power_on();
iep_service.ion_client = rockchip_ion_client_create("iep");
if (IS_ERR(iep_service.ion_client)) {
IEP_ERR("failed to create ion client for vcodec");
return PTR_ERR(iep_service.ion_client);
} else {
IEP_INFO("iep ion client create success!\n");
}
mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,iep_mmu");
if (mmu_dev) {
platform_set_sysmmu(mmu_dev, &pdev->dev);
iovmm_activate(&pdev->dev);
}
iep_service.iommu_dev = &pdev->dev;
iep_power_off();
}
mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,iep_mmu");
if (mmu_dev) {
platform_set_sysmmu(mmu_dev, &pdev->dev);
iovmm_activate(&pdev->dev);
}
iep_service.iommu_dev = &pdev->dev;
iep_power_off();
#endif
IEP_INFO("IEP Driver loaded succesfully\n");