blob: d4daa6dde308957bfb2561ae340211a9f942bd3c [file] [log] [blame]
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/of_device.h>
#include <linux/timer.h>
#include "jpeg_enc_core.h"
#include "jpeg_enc_soc.h"
#include "cam_hw.h"
#include "cam_hw_intf.h"
#include "cam_io_util.h"
#include "cam_jpeg_hw_intf.h"
#include "cam_jpeg_hw_mgr_intf.h"
#include "cam_cpas_api.h"
#include "cam_debug_util.h"
#include "cam_jpeg_enc_hw_info_ver_4_2_0.h"
static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info,
struct cam_jpeg_enc_device_core_info *core_info,
uint32_t hw_idx)
{
struct cam_cpas_register_params cpas_register_params;
int rc;
cpas_register_params.dev = soc_info->dev;
memcpy(cpas_register_params.identifier, "jpeg-enc",
sizeof("jpeg-enc"));
cpas_register_params.cam_cpas_client_cb = NULL;
cpas_register_params.cell_index = hw_idx;
cpas_register_params.userdata = NULL;
rc = cam_cpas_register_client(&cpas_register_params);
if (rc) {
CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc);
return rc;
}
core_info->cpas_handle = cpas_register_params.client_handle;
return rc;
}
static int cam_jpeg_enc_unregister_cpas(
struct cam_jpeg_enc_device_core_info *core_info)
{
int rc;
rc = cam_cpas_unregister_client(core_info->cpas_handle);
if (rc)
CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc);
core_info->cpas_handle = 0;
return rc;
}
static int cam_jpeg_enc_remove(struct platform_device *pdev)
{
struct cam_hw_info *jpeg_enc_dev = NULL;
struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
struct cam_jpeg_enc_device_core_info *core_info = NULL;
int rc;
jpeg_enc_dev_intf = platform_get_drvdata(pdev);
if (!jpeg_enc_dev_intf) {
CAM_ERR(CAM_JPEG, "error No data in pdev");
return -EINVAL;
}
jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv;
if (!jpeg_enc_dev) {
CAM_ERR(CAM_JPEG, "error HW data is NULL");
rc = -ENODEV;
goto free_jpeg_hw_intf;
}
core_info = (struct cam_jpeg_enc_device_core_info *)
jpeg_enc_dev->core_info;
if (!core_info) {
CAM_ERR(CAM_JPEG, "error core data NULL");
goto deinit_soc;
}
rc = cam_jpeg_enc_unregister_cpas(core_info);
if (rc)
CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc);
mutex_destroy(&core_info->core_mutex);
kfree(core_info);
deinit_soc:
rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
if (rc)
CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc);
mutex_destroy(&jpeg_enc_dev->hw_mutex);
kfree(jpeg_enc_dev);
free_jpeg_hw_intf:
kfree(jpeg_enc_dev_intf);
return rc;
}
static int cam_jpeg_enc_probe(struct platform_device *pdev)
{
struct cam_hw_info *jpeg_enc_dev = NULL;
struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
const struct of_device_id *match_dev = NULL;
struct cam_jpeg_enc_device_core_info *core_info = NULL;
struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
int rc;
jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
if (!jpeg_enc_dev_intf)
return -ENOMEM;
of_property_read_u32(pdev->dev.of_node,
"cell-index", &jpeg_enc_dev_intf->hw_idx);
jpeg_enc_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
if (!jpeg_enc_dev) {
rc = -ENOMEM;
goto error_alloc_dev;
}
jpeg_enc_dev->soc_info.pdev = pdev;
jpeg_enc_dev->soc_info.dev = &pdev->dev;
jpeg_enc_dev->soc_info.dev_name = pdev->name;
jpeg_enc_dev_intf->hw_priv = jpeg_enc_dev;
jpeg_enc_dev_intf->hw_ops.init = cam_jpeg_enc_init_hw;
jpeg_enc_dev_intf->hw_ops.deinit = cam_jpeg_enc_deinit_hw;
jpeg_enc_dev_intf->hw_ops.start = cam_jpeg_enc_start_hw;
jpeg_enc_dev_intf->hw_ops.stop = cam_jpeg_enc_stop_hw;
jpeg_enc_dev_intf->hw_ops.reset = cam_jpeg_enc_reset_hw;
jpeg_enc_dev_intf->hw_ops.process_cmd = cam_jpeg_enc_process_cmd;
jpeg_enc_dev_intf->hw_type = CAM_JPEG_DEV_ENC;
platform_set_drvdata(pdev, jpeg_enc_dev_intf);
jpeg_enc_dev->core_info =
kzalloc(sizeof(struct cam_jpeg_enc_device_core_info),
GFP_KERNEL);
if (!jpeg_enc_dev->core_info) {
rc = -ENOMEM;
goto error_alloc_core;
}
core_info = (struct cam_jpeg_enc_device_core_info *)
jpeg_enc_dev->core_info;
match_dev = of_match_device(pdev->dev.driver->of_match_table,
&pdev->dev);
if (!match_dev) {
CAM_ERR(CAM_JPEG, " No jpeg_enc hardware info");
rc = -EINVAL;
goto error_match_dev;
}
hw_info = (struct cam_jpeg_enc_device_hw_info *)match_dev->data;
core_info->jpeg_enc_hw_info = hw_info;
core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
mutex_init(&core_info->core_mutex);
rc = cam_jpeg_enc_init_soc_resources(&jpeg_enc_dev->soc_info,
cam_jpeg_enc_irq,
jpeg_enc_dev);
if (rc) {
CAM_ERR(CAM_JPEG, " failed to init_soc %d", rc);
goto error_init_soc;
}
rc = cam_jpeg_enc_register_cpas(&jpeg_enc_dev->soc_info,
core_info, jpeg_enc_dev_intf->hw_idx);
if (rc) {
CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc);
goto error_reg_cpas;
}
jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
mutex_init(&jpeg_enc_dev->hw_mutex);
spin_lock_init(&jpeg_enc_dev->hw_lock);
init_completion(&jpeg_enc_dev->hw_complete);
return rc;
error_reg_cpas:
cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
error_init_soc:
mutex_destroy(&core_info->core_mutex);
error_match_dev:
kfree(jpeg_enc_dev->core_info);
error_alloc_core:
kfree(jpeg_enc_dev);
error_alloc_dev:
kfree(jpeg_enc_dev_intf);
return rc;
}
static const struct of_device_id cam_jpeg_enc_dt_match[] = {
{
.compatible = "qcom,cam_jpeg_enc",
.data = &cam_jpeg_enc_hw_info,
},
{}
};
MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match);
static struct platform_driver cam_jpeg_enc_driver = {
.probe = cam_jpeg_enc_probe,
.remove = cam_jpeg_enc_remove,
.driver = {
.name = "cam-jpeg-enc",
.owner = THIS_MODULE,
.of_match_table = cam_jpeg_enc_dt_match,
.suppress_bind_attrs = true,
},
};
static int __init cam_jpeg_enc_init_module(void)
{
return platform_driver_register(&cam_jpeg_enc_driver);
}
static void __exit cam_jpeg_enc_exit_module(void)
{
platform_driver_unregister(&cam_jpeg_enc_driver);
}
module_init(cam_jpeg_enc_init_module);
module_exit(cam_jpeg_enc_exit_module);
MODULE_DESCRIPTION("CAM JPEG_ENC driver");
MODULE_LICENSE("GPL v2");