blob: 91604b98f53f494bed5c36fc947a5e3bd59912da [file] [log] [blame]
/*
* Samsung Exynos SoC series VPU driver
*
* Copyright (c) 2015 Samsung Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/pm_qos.h>
#include "vpu-config.h"
#include "vpu-device.h"
#include "vpu-system.h"
#include "vpu-interface.h"
#define CAM_L0 690000
#define CAM_L1 680000
#define CAM_L2 670000
#define CAM_L3 660000
#define CAM_L4 650000
#define CAM_L5 640000
#define MIF_L0 2093000
#define MIF_L1 2002000
#define MIF_L2 1794000
#define MIF_L3 1539000
#define MIF_L4 1352000
#define MIF_L5 1014000
#define MIF_L6 845000
#define MIF_L7 676000
struct pm_qos_request exynos_vpu_qos_cam;
struct pm_qos_request exynos_vpu_qos_mem;
int vpu_system_probe(struct vpu_system *system, struct platform_device *pdev)
{
int ret = 0;
struct device *dev;
struct resource *res;
void __iomem *iomem;
int irq;
BUG_ON(!system);
BUG_ON(!pdev);
dev = &pdev->dev;
system->cam_qos = 0;
system->mif_qos = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
probe_err("platform_get_resource(0) is fail(%p)", res);
ret = PTR_ERR(res);
goto p_err;
}
iomem = devm_ioremap_resource(dev, res);
if (IS_ERR_OR_NULL(iomem)) {
probe_err("devm_ioremap_resource(0) is fail(%p)", iomem);
ret = PTR_ERR(iomem);
goto p_err;
}
system->ram0 = iomem;
system->ram0_size = resource_size(res);
probe_info("resource0 : %p\n", iomem);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
probe_err("platform_get_resource(1) is fail(%p)", res);
ret = PTR_ERR(res);
goto p_err;
}
iomem = devm_ioremap_resource(dev, res);
if (IS_ERR_OR_NULL(iomem)) {
probe_err("devm_ioremap_resource(1) is fail(%p)", iomem);
ret = PTR_ERR(iomem);
goto p_err;
}
system->ram1 = iomem;
system->ram1_size = resource_size(res);
probe_info("resource1 : %p\n", iomem);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (!res) {
probe_err("platform_get_resource(2) is fail(%p)", res);
ret = PTR_ERR(res);
goto p_err;
}
iomem = devm_ioremap_resource(dev, res);
if (IS_ERR_OR_NULL(iomem)) {
probe_err("devm_ioremap_resource(2) is fail(%p)", iomem);
ret = PTR_ERR(iomem);
goto p_err;
}
system->code = iomem;
system->code_size = resource_size(res);
probe_info("resource2 : %p\n", iomem);
res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
if (!res) {
probe_err("platform_get_resource(3) is fail(%p)", res);
ret = PTR_ERR(res);
goto p_err;
}
iomem = devm_ioremap_resource(dev, res);
if (IS_ERR_OR_NULL(iomem)) {
probe_err("devm_ioremap_resource(3) is fail(%p)", iomem);
ret = PTR_ERR(iomem);
goto p_err;
}
system->regs = iomem;
system->regs_size = resource_size(res);
probe_info("resource3 : %p\n", iomem);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
probe_err("platform_get_irq(0) is fail(%d)", irq);
ret = -EINVAL;
goto p_err;
}
system->irq0 = irq;
irq = platform_get_irq(pdev, 1);
if (irq < 0) {
probe_err("platform_get_irq(1) is fail(%d)", irq);
ret = -EINVAL;
goto p_err;
}
system->irq1 = irq;
ret = vpu_exynos_probe(&system->exynos, dev, system->regs, system->ram0, system->ram1);
if (ret) {
probe_err("vpu_exynos_probe is fail(%d)\n", ret);
ret = -EINVAL;
goto p_err;
}
ret = vpu_memory_probe(&system->memory, dev);
if (ret) {
vpu_err("vpu_memory_probe is fail(%d)\n", ret);
goto p_err;
}
ret = vpu_interface_probe(&system->interface, dev,
system->code, system->code_size,
system->regs, system->regs_size,
system->irq0, system->irq1);
if (ret) {
vpu_err("vpu_interface_probe is fail(%d)\n", ret);
goto p_err;
}
ret = vpu_binary_init(&system->binary,
dev,
VPU_FW_PATH1,
VPU_FW_PATH2,
VPU_FW_NAME);
if (ret) {
vpu_err("vpu_binary_init is fail(%d)\n", ret);
goto p_err;
}
ret = vpu_tv_probe(&system->tvset, dev, &system->exynos, &system->memory);
if (ret) {
vpu_err("vpu_tv_probe is fail(%d)\n", ret);
goto p_err;
}
p_err:
return ret;
}
int vpu_system_open(struct vpu_system *system)
{
int ret = 0;
ret = vpu_memory_open(&system->memory);
if (ret) {
vpu_err("vpu_memory_open is fail(%d)\n", ret);
goto p_err;
}
ret = vpu_interface_open(&system->interface);
if (ret) {
vpu_err("vpu_interface_open is fail(%d)\n", ret);
vpu_memory_close(&system->memory);
goto p_err;
}
p_err:
return ret;
}
int vpu_system_close(struct vpu_system *system)
{
int ret = 0;
ret = vpu_interface_close(&system->interface);
if (ret)
vpu_err("vpu_interface_close is fail(%d)\n", ret);
ret = vpu_memory_close(&system->memory);
if (ret)
vpu_err("vpu_memory_close is fail(%d)\n", ret);
return ret;
}
int vpu_system_resume(struct vpu_system *system, u32 mode)
{
int ret = 0;
struct vpu_exynos *exynos;
struct vpu_memory *memory;
struct vpu_binary *binary;
BUG_ON(!system);
exynos = &system->exynos;
memory = &system->memory;
binary = &system->binary;
ret = CLK_OP(exynos, clk_cfg);
if (ret) {
vpu_err("CLK_OP(clk_cfg) is fail(%d)\n", ret);
goto p_err;
}
#if defined(CONFIG_PM_DEVFREQ)
pm_qos_add_request(&exynos_vpu_qos_cam, PM_QOS_CAM_THROUGHPUT, CAM_L5);
pm_qos_add_request(&exynos_vpu_qos_mem, PM_QOS_BUS_THROUGHPUT, MIF_L6);
#endif
ret = CLK_OP(exynos, clk_on);
if (ret) {
vpu_err("CLK_OP(clk_on) is fail(%d)\n", ret);
goto p_err;
}
#if defined(CONFIG_VIDEOBUF2_ION)
vb2_ion_attach_iommu(system->memory.alloc_ctx);
#endif
if (mode == VPU_DEVICE_MODE_TEST)
goto p_err;
ret = vpu_binary_read(binary, system->code, system->code_size);
if (ret) {
vpu_err("vpu_binary_load is fail(%d)\n", ret);
goto p_err;
}
ret = CTL_OP(exynos, ctl_reset, false);
if (ret) {
vpu_err("CTL_OP(ctl_reset) is fail(%d)\n", ret);
goto p_err;
}
p_err:
return ret;
}
int vpu_system_suspend(struct vpu_system *system)
{
int ret = 0;
struct vpu_exynos *exynos;
struct vpu_memory *memory;
BUG_ON(!system);
exynos = &system->exynos;
memory = &system->memory;
#if defined(CONFIG_VIDEOBUF2_ION)
vb2_ion_detach_iommu(memory->alloc_ctx);
#endif
ret = CTL_OP(exynos, ctl_reset, true);
if (ret)
vpu_err("CTL_OP(ctl_reset) is fail(%d)\n", ret);
ret = CLK_OP(exynos, clk_off);
if (ret)
vpu_err("CLK_OP(clk_off) is fail(%d)\n", ret);
#if defined(CONFIG_PM_DEVFREQ)
pm_qos_remove_request(&exynos_vpu_qos_cam);
pm_qos_remove_request(&exynos_vpu_qos_mem);
#endif
return ret;
}
int vpu_system_start(struct vpu_system *system)
{
int ret = 0;
ret = vpu_interface_start(&system->interface);
if (ret) {
vpu_err("vpu_interface_start is fail(%d)\n", ret);
goto p_err;
}
p_err:
return ret;
}
int vpu_system_stop(struct vpu_system *system)
{
int ret = 0;
ret = vpu_interface_stop(&system->interface);
if (ret)
vpu_err("vpu_interface_stop is fail(%d)\n", ret);
return ret;
}