summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-imx8qm-device.dtsi26
-rw-r--r--drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.c378
-rw-r--r--drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.h2
3 files changed, 251 insertions, 155 deletions
diff --git a/arch/arm64/boot/dts/freescale/fsl-imx8qm-device.dtsi b/arch/arm64/boot/dts/freescale/fsl-imx8qm-device.dtsi
index 354cf104c03e..8cf06bcdf91a 100644
--- a/arch/arm64/boot/dts/freescale/fsl-imx8qm-device.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-imx8qm-device.dtsi
@@ -1170,17 +1170,33 @@
#address-cells = <1>;
#size-cells = <0>;
- pd_vpu_mu_enc: VPU_ENC_MU {
- reg = <SC_R_VPU_MU_1>;
+ pd_vpu_mu1_enc: VPU_ENC_MU1 {
+ reg = <SC_R_VPU_MU_2>;
#power-domain-cells = <0>;
power-domains =<&pd_vpu>;
#address-cells = <1>;
#size-cells = <0>;
- pd_vpu_enc: VPU_ENC {
- reg = <SC_R_VPU_ENC_0>;
+ pd_vpu_enc1: VPU_ENC1 {
+ reg = <SC_R_VPU_ENC_1>;
#power-domain-cells = <0>;
- power-domains =<&pd_vpu_mu_enc>;
+ power-domains =<&pd_vpu_mu1_enc>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pd_vpu_mu_enc: VPU_ENC_MU {
+ reg = <SC_R_VPU_MU_1>;
+ #power-domain-cells = <0>;
+ power-domains =<&pd_vpu_enc1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pd_vpu_enc: VPU_ENC {
+ reg = <SC_R_VPU_ENC_0>;
+ #power-domain-cells = <0>;
+ power-domains =<&pd_vpu_mu_enc>;
+ };
+ };
};
};
diff --git a/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.c b/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.c
index 5f15a4859913..da7695b9807a 100644
--- a/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.c
+++ b/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.c
@@ -1211,6 +1211,7 @@ static void report_stream_done(struct vpu_ctx *ctx, MEDIAIP_ENC_PIC_INFO *pEncP
p_data_req->vb2_buf->planes[0].bytesused = length;
else
p_data_req->vb2_buf->planes[0].bytesused = data_length;
+ length = p_data_req->vb2_buf->planes[0].bytesused;
vpu_dbg(LVL_INFO, "%s data_length %d, length %d\n", __func__, data_length, length);
/* Following calculations determine how much data we can transfer into p_vb2_buf
@@ -2138,7 +2139,7 @@ static struct video_device v4l2_videodevice_encoder = {
.ioctl_ops = &v4l2_encoder_ioctl_ops,
.vfl_dir = VFL_DIR_M2M,
};
-#if 1
+#if 0
static int set_vpu_pwr(sc_ipc_t ipcHndl,
sc_pm_power_mode_t pm,
u_int32 core_id
@@ -2269,192 +2270,281 @@ static void vpu_disable_hw(struct vpu_dev *This)
#endif
}
+static int get_platform_info_by_core_type(struct vpu_dev *dev, u32 core_type)
+{
+ int ret = 0;
+
+ if (!dev)
+ return -EINVAL;
+
+ switch (core_type) {
+ case 1:
+ dev->plat_type = IMX8QXP;
+ dev->core_num = 1;
+ break;
+ case 2:
+ dev->plat_type = IMX8QM;
+ dev->core_num = 2;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int parse_dt_info(struct vpu_dev *dev, struct device_node *np)
+{
+ int ret;
+ struct device_node *reserved_node = NULL;
+ struct resource reserved_res;
+ u_int32 core_type;
+
+ if (!dev || !np)
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, "core_type", &core_type);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "error: Cannot get core num %d\n", ret);
+ return -EINVAL;
+ }
+ ret = get_platform_info_by_core_type(dev, core_type);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "invalid core_type : %d\n", core_type);
+ return ret;
+ }
+ reserved_node = of_parse_phandle(np, "boot-region", 0);
+ if (!reserved_node) {
+ vpu_dbg(LVL_ERR, "error: boot-region of_parse_phandle error\n");
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
+ vpu_dbg(LVL_ERR,
+ "error: boot-region of_address_to_resource error\n");
+ return -EINVAL;
+ }
+ dev->core_dev[0].m0_p_fw_space_phy = reserved_res.start;
+ dev->core_dev[1].m0_p_fw_space_phy = reserved_res.start + M0_BOOT_SIZE;
+ reserved_node = of_parse_phandle(np, "rpc-region", 0);
+ if (!reserved_node) {
+ vpu_dbg(LVL_ERR,
+ "error: rpc-region of_parse_phandle error\n");
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
+ vpu_dbg(LVL_ERR,
+ "error: rpc-region of_address_to_resource error\n");
+ return -EINVAL;
+ }
+ dev->core_dev[0].m0_rpc_phy = reserved_res.start;
+ dev->core_dev[1].m0_rpc_phy = reserved_res.start + SHARED_SIZE;
+
+ return 0;
+}
+
+static int create_vpu_video_device(struct vpu_dev *dev)
+{
+ int ret;
+
+ dev->pvpu_encoder_dev = video_device_alloc();
+ if (!dev->pvpu_encoder_dev) {
+ vpu_dbg(LVL_ERR, "alloc vpu encoder video device fail\n");
+ return -ENOMEM;
+ }
+
+ strncpy(dev->pvpu_encoder_dev->name,
+ v4l2_videodevice_encoder.name,
+ sizeof(v4l2_videodevice_encoder.name));
+ dev->pvpu_encoder_dev->fops = v4l2_videodevice_encoder.fops;
+ dev->pvpu_encoder_dev->ioctl_ops = v4l2_videodevice_encoder.ioctl_ops;
+ dev->pvpu_encoder_dev->release = video_device_release;
+ dev->pvpu_encoder_dev->vfl_dir = v4l2_videodevice_encoder.vfl_dir;
+ dev->pvpu_encoder_dev->v4l2_dev = &dev->v4l2_dev;
+ video_set_drvdata(dev->pvpu_encoder_dev, dev);
+
+ ret = video_register_device(dev->pvpu_encoder_dev,
+ VFL_TYPE_GRABBER,
+ ENCODER_NODE_NUMBER);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "unable to register video encoder device\n");
+ video_device_release(dev->pvpu_encoder_dev);
+ dev->pvpu_encoder_dev = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int init_vpu_core_dev(struct vpu_dev *dev, u32 id)
+{
+ int ret;
+ struct core_device *core_dev = &dev->core_dev[id];
+
+ if (!dev)
+ return -EINVAL;
+
+ core_dev = &dev->core_dev[id];
+
+ mutex_init(&core_dev->core_mutex);
+ mutex_init(&core_dev->cmd_mutex);
+ init_completion(&core_dev->start_cmp);
+ init_completion(&core_dev->snap_done_cmp);
+ core_dev->firmware_started = false;
+
+ core_dev->fw_is_ready = false;
+ core_dev->workqueue = alloc_workqueue("vpu",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!core_dev->workqueue) {
+ vpu_dbg(LVL_ERR, "%s unable to alloc workqueue\n", __func__);
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ INIT_WORK(&core_dev->msg_work, vpu_msg_run_work);
+
+ ret = vpu_mu_init(dev, id);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "%s vpu mu init failed\n", __func__);
+ return ret;
+ }
+ //firmware space for M0
+ core_dev->m0_p_fw_space_vir =
+ ioremap_wc(core_dev->m0_p_fw_space_phy, M0_BOOT_SIZE);
+ if (!core_dev->m0_p_fw_space_vir)
+ vpu_dbg(LVL_ERR, "failed to remap space for M0 firmware\n");
+
+ memset_io(core_dev->m0_p_fw_space_vir, 0, M0_BOOT_SIZE);
+
+ core_dev->m0_rpc_virt = ioremap_wc(core_dev->m0_rpc_phy, SHARED_SIZE);
+ if (!core_dev->m0_rpc_virt)
+ vpu_dbg(LVL_ERR, "failed to remap space for shared memory\n");
+
+ memset_io(core_dev->m0_rpc_virt, 0, SHARED_SIZE);
+
+ rpc_init_shared_memory_encoder(&core_dev->shared_mem,
+ core_dev->m0_rpc_phy - core_dev->m0_p_fw_space_phy,
+ core_dev->m0_rpc_virt, SHARED_SIZE);
+ rpc_set_system_cfg_value_encoder(core_dev->shared_mem.pSharedInterface,
+ VPU_REG_BASE, id);
+
+ return 0;
+}
+
static int vpu_probe(struct platform_device *pdev)
{
struct vpu_dev *dev;
struct resource *res;
struct device_node *np = pdev->dev.of_node;
- struct device_node *reserved_node;
- struct resource reserved_res;
unsigned int mu_id;
- u_int32 core_type;
u_int32 i;
int ret;
+ if (!np) {
+ vpu_dbg(LVL_ERR, "error: %s of_node is NULL\n", __func__);
+ return -EINVAL;
+ }
+
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->plat_dev = pdev;
- dev->generic_dev = &pdev->dev;
+ dev->generic_dev = get_device(&pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->regs_base = ioremap(ENC_REG_BASE, 0x1000000);
if (!dev->regs_base) {
vpu_dbg(LVL_ERR, "%s could not map regs_base\n", __func__);
- return PTR_ERR(dev->regs_base);
+ ret = PTR_ERR(dev->regs_base);
+ goto error_put_dev;
}
- if (np) {
- ret = of_property_read_u32(np, "core_type", &core_type);
- if (ret) {
- vpu_dbg(LVL_ERR, "error: Cannot get core num %d\n", ret);
- return -EINVAL;
- }
- if (core_type == 2)
- dev->plat_type = IMX8QM;
- else
- dev->plat_type = IMX8QXP;
- reserved_node = of_parse_phandle(np, "boot-region", 0);
- if (!reserved_node) {
- vpu_dbg(LVL_ERR, "error: boot-region of_parse_phandle error\n");
- return -ENODEV;
- }
-
- if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
- vpu_dbg(LVL_ERR, "error: boot-region of_address_to_resource error\n");
- return -EINVAL;
- }
- dev->core_dev[0].m0_p_fw_space_phy = reserved_res.start;
- dev->core_dev[1].m0_p_fw_space_phy = reserved_res.start + M0_BOOT_SIZE;
- reserved_node = of_parse_phandle(np, "rpc-region", 0);
- if (!reserved_node) {
- vpu_dbg(LVL_ERR, "error: rpc-region of_parse_phandle error\n");
- return -ENODEV;
- }
-
- if (of_address_to_resource(reserved_node, 0, &reserved_res)) {
- vpu_dbg(LVL_ERR, "error: rpc-region of_address_to_resource error\n");
- return -EINVAL;
- }
- dev->core_dev[0].m0_rpc_phy = reserved_res.start;
- dev->core_dev[1].m0_rpc_phy = reserved_res.start + SHARED_SIZE;
- } else
- vpu_dbg(LVL_ERR, "error: %s of_node is NULL\n", __func__);
+ ret = parse_dt_info(dev, np);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "parse device tree fail\n");
+ goto error_iounmap;
+ }
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
vpu_dbg(LVL_ERR, "%s unable to register v4l2 dev\n", __func__);
- return ret;
+ goto error_iounmap;
}
platform_set_drvdata(pdev, dev);
- dev->pvpu_encoder_dev = video_device_alloc();
- if (dev->pvpu_encoder_dev) {
- strncpy(dev->pvpu_encoder_dev->name, v4l2_videodevice_encoder.name, sizeof(v4l2_videodevice_encoder.name));
- dev->pvpu_encoder_dev->fops = v4l2_videodevice_encoder.fops;
- dev->pvpu_encoder_dev->ioctl_ops = v4l2_videodevice_encoder.ioctl_ops;
- dev->pvpu_encoder_dev->release = video_device_release;
- dev->pvpu_encoder_dev->vfl_dir = v4l2_videodevice_encoder.vfl_dir;
- dev->pvpu_encoder_dev->v4l2_dev = &dev->v4l2_dev;
-
- video_set_drvdata(dev->pvpu_encoder_dev, dev);
-
- if (video_register_device(dev->pvpu_encoder_dev,
- VFL_TYPE_GRABBER,
- ENCODER_NODE_NUMBER)) {
- vpu_dbg(LVL_ERR, "%s unable to register video encoder device\n",
- __func__
- );
- video_device_release(dev->pvpu_encoder_dev);
- dev->pvpu_encoder_dev = NULL;
- } else {
- vpu_dbg(LVL_INFO, "%s register video encoder device\n",
- __func__
- );
- }
+ ret = create_vpu_video_device(dev);
+ if (ret) {
+ vpu_dbg(LVL_ERR, "create vpu video device fail\n");
+ goto error_unreg_v4l2;
}
if (!dev->mu_ipcHandle) {
ret = sc_ipc_getMuID(&mu_id);
if (ret) {
- vpu_dbg(LVL_ERR, "--- sc_ipc_getMuID() cannot obtain mu id SCI error! (%d)\n", ret);
- return ret;
+ vpu_dbg(LVL_ERR,
+ "-- cannot obtain mu id SCI error!(%d)\n",
+ ret);
+ goto error_rm_vdev;
}
ret = sc_ipc_open(&dev->mu_ipcHandle, mu_id);
if (ret) {
- vpu_dbg(LVL_ERR, "--- sc_ipc_getMuID() cannot open MU channel to SCU error! (%d)\n", ret);
- return ret;
+ vpu_dbg(LVL_ERR,
+ "-- cannot open MU channel to SCU error!(%d)\n",
+ ret);
+ goto error_rm_vdev;
}
}
- if (core_type == 2) {
- vpu_set_power(dev, true, 0);
- vpu_set_power(dev, true, 1);
- }
-
vpu_enable_hw(dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
mutex_init(&dev->dev_mutex);
- for (i = 0; i < core_type; i++) {
- struct core_device *core_dev;
-
- core_dev = &dev->core_dev[i];
- mutex_init(&core_dev->core_mutex);
- mutex_init(&core_dev->cmd_mutex);
- init_completion(&core_dev->start_cmp);
- init_completion(&core_dev->snap_done_cmp);
- core_dev->firmware_started = false;
-
- core_dev->fw_is_ready = false;
- core_dev->workqueue = alloc_workqueue("vpu", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
- if (!core_dev->workqueue) {
- vpu_dbg(LVL_ERR, "%s unable to alloc workqueue\n", __func__);
- ret = -ENOMEM;
- return ret;
- }
-
- INIT_WORK(&core_dev->msg_work, vpu_msg_run_work);
-
- ret = vpu_mu_init(dev, i);
- if (ret) {
- vpu_dbg(LVL_ERR, "%s vpu mu init failed\n", __func__);
- return ret;
- }
- //firmware space for M0
- core_dev->m0_p_fw_space_vir = ioremap_wc(core_dev->m0_p_fw_space_phy,
- M0_BOOT_SIZE
- );
- if (!core_dev->m0_p_fw_space_vir)
- vpu_dbg(LVL_ERR, "failed to remap space for M0 firmware\n");
-
- memset_io(core_dev->m0_p_fw_space_vir, 0, M0_BOOT_SIZE);
+ for (i = 0; i < dev->core_num; i++) {
+ ret = init_vpu_core_dev(dev, i);
+ if (ret)
+ goto error_pwoff;
+ }
+ pm_runtime_put_sync(&pdev->dev);
- core_dev->m0_rpc_virt = ioremap_wc(core_dev->m0_rpc_phy,
- SHARED_SIZE
- );
- if (!core_dev->m0_rpc_virt)
- vpu_dbg(LVL_ERR, "failed to remap space for shared memory\n");
+ return 0;
- memset_io(core_dev->m0_rpc_virt, 0, SHARED_SIZE);
+error_pwoff:
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ vpu_disable_hw(dev);
- rpc_init_shared_memory_encoder(&core_dev->shared_mem, core_dev->m0_rpc_phy - core_dev->m0_p_fw_space_phy, core_dev->m0_rpc_virt, SHARED_SIZE);
- rpc_set_system_cfg_value_encoder(core_dev->shared_mem.pSharedInterface, VPU_REG_BASE, i);
+error_rm_vdev:
+ if (dev->pvpu_encoder_dev) {
+ video_unregister_device(dev->pvpu_encoder_dev);
+ dev->pvpu_encoder_dev = NULL;
}
- pm_runtime_put_sync(&pdev->dev);
- return 0;
+error_unreg_v4l2:
+ v4l2_device_unregister(&dev->v4l2_dev);
+error_iounmap:
+ if (dev->regs_base)
+ iounmap(dev->regs_base);
+error_put_dev:
+ if (dev->generic_dev) {
+ put_device(dev->generic_dev);
+ dev->generic_dev = NULL;
+ }
+ return ret;
}
static int vpu_remove(struct platform_device *pdev)
{
struct vpu_dev *dev = platform_get_drvdata(pdev);
- u_int32 core_num;
u_int32 i;
- if (dev->plat_type == IMX8QM) {
- destroy_workqueue(dev->core_dev[0].workqueue);
- destroy_workqueue(dev->core_dev[1].workqueue);
- core_num = 2;
- } else {
- destroy_workqueue(dev->core_dev[0].workqueue);
- core_num = 1;
- }
+ for (i = 0; i < dev->core_num; i++) {
+ destroy_workqueue(dev->core_dev[i].workqueue);
- for (i = 0; i < core_num; i++) {
if (dev->core_dev[i].m0_p_fw_space_vir)
iounmap(dev->core_dev[i].m0_p_fw_space_vir);
dev->core_dev[i].m0_p_fw_space_vir = NULL;
@@ -2475,6 +2565,11 @@ static int vpu_remove(struct platform_device *pdev)
video_unregister_device(dev->pvpu_encoder_dev);
v4l2_device_unregister(&dev->v4l2_dev);
+ if (dev->generic_dev) {
+ put_device(dev->generic_dev);
+ dev->generic_dev = NULL;
+ }
+
return 0;
}
@@ -2518,14 +2613,9 @@ static int vpu_suspend(struct device *dev)
{
struct vpu_dev *vpudev = (struct vpu_dev *)dev_get_drvdata(dev);
struct core_device *core_dev;
- u_int32 core_num, i;
-
- if (vpudev->plat_type == IMX8QM)
- core_num = 2;
- else
- core_num = 1;
+ u_int32 i;
- for (i = 0; i < core_num; i++) {
+ for (i = 0; i < vpudev->core_num; i++) {
core_dev = &vpudev->core_dev[i];
if (core_dev->hang_mask != core_dev->instance_mask) {
@@ -2537,7 +2627,6 @@ static int vpu_suspend(struct device *dev)
return -1;
}
}
- vpu_set_power(vpudev, false, i);
}
return 0;
@@ -2548,20 +2637,11 @@ static int vpu_resume(struct device *dev)
struct vpu_dev *vpudev = (struct vpu_dev *)dev_get_drvdata(dev);
void *csr_offset, *csr_cpuwait;
struct core_device *core_dev;
- u_int32 core_num;
u_int32 i;
- if (vpudev->plat_type == IMX8QM) {
- core_num = 2;
- vpu_set_power(vpudev, true, 0);
- vpu_set_power(vpudev, true, 1);
- vpu_enable_hw(vpudev);
- } else {
- core_num = 1;
- vpu_set_power(vpudev, true, 0);
- vpu_enable_hw(vpudev);
- }
- for (i = 0; i < core_num; i++) {
+ vpu_enable_hw(vpudev);
+
+ for (i = 0; i < vpudev->core_num; i++) {
core_dev = &vpudev->core_dev[i];
MU_Init(core_dev->mu_base_virtaddr);
MU_EnableRxFullInt(core_dev->mu_base_virtaddr, 0);
diff --git a/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.h b/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.h
index 128e2a0304bc..35952e73aeb3 100644
--- a/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.h
+++ b/drivers/mxc/vpu-encoder-b0/vpu_encoder_b0.h
@@ -217,6 +217,7 @@ struct vpu_dev {
struct mutex dev_mutex;
struct core_device core_dev[2];
u_int32 plat_type;
+ u_int32 core_num;
// struct vpu_ctx *ctx[VPU_MAX_NUM_STREAMS];
};
@@ -249,7 +250,6 @@ struct vpu_ctx {
bool forceStop;
wait_queue_head_t buffer_wq_output;
wait_queue_head_t buffer_wq_input;
- struct buffer_addr encoder_buffer;
struct buffer_addr encoder_stream;
struct buffer_addr encoder_mem;
struct buffer_addr encFrame[MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES];