Camera: Bring over camera driver changes
Bring over camera driver changes as of msm-4.19 commit 5a5551a7 (Merge "msm: camera: reqmgr: Fix CRM shift one req issue"). Change-Id: Ic0c2b2d74d1b3470c1c51d98228e312fb13c501a Signed-off-by: Jigarkumar Zala <jzala@codeaurora.org>
This commit is contained in:
16
drivers/cam_lrme/Makefile
Normal file
16
drivers/cam_lrme/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/include/uapi/media
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include/
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw_mgr/
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_dev.o cam_lrme_context.o
|
251
drivers/cam_lrme/cam_lrme_context.c
Normal file
251
drivers/cam_lrme/cam_lrme_context.c
Normal file
@@ -0,0 +1,251 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_lrme_context.h"
|
||||
|
||||
static const char lrme_dev_name[] = "lrme";
|
||||
|
||||
static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx,
|
||||
struct cam_acquire_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
uintptr_t ctxt_to_hw_map = (uintptr_t)ctx->ctxt_to_hw_map;
|
||||
struct cam_lrme_context *lrme_ctx = ctx->ctx_priv;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_acquire_dev_to_hw(ctx, cmd);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to acquire");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctxt_to_hw_map |= (lrme_ctx->index << CAM_LRME_CTX_INDEX_SHIFT);
|
||||
ctx->ctxt_to_hw_map = (void *)ctxt_to_hw_map;
|
||||
|
||||
ctx->state = CAM_CTX_ACQUIRED;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_release_dev_in_acquired(struct cam_context *ctx,
|
||||
struct cam_release_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_release_dev_to_hw(ctx, cmd);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to release");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->state = CAM_CTX_AVAILABLE;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_start_dev_in_acquired(struct cam_context *ctx,
|
||||
struct cam_start_stop_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_start_dev_to_hw(ctx, cmd);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to start");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->state = CAM_CTX_ACTIVATED;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_config_dev_in_activated(struct cam_context *ctx,
|
||||
struct cam_config_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_prepare_dev_to_hw(ctx, cmd);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to config");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_flush_dev_in_activated(struct cam_context *ctx,
|
||||
struct cam_flush_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_flush_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Failed to flush device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
static int __cam_lrme_ctx_stop_dev_in_activated(struct cam_context *ctx,
|
||||
struct cam_start_stop_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_stop_dev_to_hw(ctx);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to stop dev");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->state = CAM_CTX_ACQUIRED;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_release_dev_in_activated(struct cam_context *ctx,
|
||||
struct cam_release_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = __cam_lrme_ctx_stop_dev_in_activated(ctx, NULL);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to stop");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_context_release_dev_to_hw(ctx, cmd);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to release");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->state = CAM_CTX_AVAILABLE;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_handle_irq_in_activated(void *context,
|
||||
uint32_t evt_id, void *evt_data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter");
|
||||
|
||||
rc = cam_context_buf_done_from_hw(context, evt_data, evt_id);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed in buf done, rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* top state machine */
|
||||
static struct cam_ctx_ops
|
||||
cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = {
|
||||
/* Uninit */
|
||||
{
|
||||
.ioctl_ops = {},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Available */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.acquire_dev = __cam_lrme_ctx_acquire_dev_in_available,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Acquired */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.config_dev = __cam_lrme_ctx_config_dev_in_activated,
|
||||
.release_dev = __cam_lrme_ctx_release_dev_in_acquired,
|
||||
.start_dev = __cam_lrme_ctx_start_dev_in_acquired,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
.ioctl_ops = {},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Activate */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.config_dev = __cam_lrme_ctx_config_dev_in_activated,
|
||||
.release_dev = __cam_lrme_ctx_release_dev_in_activated,
|
||||
.stop_dev = __cam_lrme_ctx_stop_dev_in_activated,
|
||||
.flush_dev = __cam_lrme_ctx_flush_dev_in_activated,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_lrme_ctx_handle_irq_in_activated,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx,
|
||||
struct cam_context *base_ctx,
|
||||
struct cam_hw_mgr_intf *hw_intf,
|
||||
uint32_t index)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter");
|
||||
|
||||
if (!base_ctx || !lrme_ctx) {
|
||||
CAM_ERR(CAM_LRME, "Invalid input");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(lrme_ctx, 0, sizeof(*lrme_ctx));
|
||||
|
||||
rc = cam_context_init(base_ctx, lrme_dev_name, CAM_LRME, index,
|
||||
NULL, hw_intf, lrme_ctx->req_base, CAM_CTX_REQ_MAX);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to init context");
|
||||
return rc;
|
||||
}
|
||||
lrme_ctx->base = base_ctx;
|
||||
lrme_ctx->index = index;
|
||||
base_ctx->ctx_priv = lrme_ctx;
|
||||
base_ctx->state_machine = cam_lrme_ctx_state_machine;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter");
|
||||
|
||||
if (!lrme_ctx) {
|
||||
CAM_ERR(CAM_LRME, "No ctx to deinit");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = cam_context_deinit(lrme_ctx->base);
|
||||
|
||||
memset(lrme_ctx, 0, sizeof(*lrme_ctx));
|
||||
return rc;
|
||||
}
|
33
drivers/cam_lrme/cam_lrme_context.h
Normal file
33
drivers/cam_lrme/cam_lrme_context.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_CONTEXT_H_
|
||||
#define _CAM_LRME_CONTEXT_H_
|
||||
|
||||
#include "cam_context.h"
|
||||
#include "cam_context_utils.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_req_mgr_interface.h"
|
||||
|
||||
#define CAM_LRME_CTX_INDEX_SHIFT 32
|
||||
|
||||
/**
|
||||
* struct cam_lrme_context
|
||||
*
|
||||
* @base : Base context pointer for this LRME context
|
||||
* @req_base : List of base request for this LRME context
|
||||
*/
|
||||
struct cam_lrme_context {
|
||||
struct cam_context *base;
|
||||
struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
|
||||
uint64_t index;
|
||||
};
|
||||
|
||||
int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx,
|
||||
struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf,
|
||||
uint32_t index);
|
||||
int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx);
|
||||
|
||||
#endif /* _CAM_LRME_CONTEXT_H_ */
|
235
drivers/cam_lrme/cam_lrme_dev.c
Normal file
235
drivers/cam_lrme/cam_lrme_dev.c
Normal file
@@ -0,0 +1,235 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cam_subdev.h"
|
||||
#include "cam_node.h"
|
||||
#include "cam_lrme_context.h"
|
||||
#include "cam_lrme_hw_mgr.h"
|
||||
#include "cam_lrme_hw_mgr_intf.h"
|
||||
|
||||
#define CAM_LRME_DEV_NAME "cam-lrme"
|
||||
|
||||
/**
|
||||
* struct cam_lrme_dev
|
||||
*
|
||||
* @sd : Subdev information
|
||||
* @ctx : List of base contexts
|
||||
* @lrme_ctx : List of LRME contexts
|
||||
* @lock : Mutex for LRME subdev
|
||||
* @open_cnt : Open count of LRME subdev
|
||||
*/
|
||||
struct cam_lrme_dev {
|
||||
struct cam_subdev sd;
|
||||
struct cam_context ctx[CAM_CTX_MAX];
|
||||
struct cam_lrme_context lrme_ctx[CAM_CTX_MAX];
|
||||
struct mutex lock;
|
||||
uint32_t open_cnt;
|
||||
};
|
||||
|
||||
static struct cam_lrme_dev *g_lrme_dev;
|
||||
|
||||
static int cam_lrme_dev_buf_done_cb(void *ctxt_to_hw_map, uint32_t evt_id,
|
||||
void *evt_data)
|
||||
{
|
||||
uint64_t index;
|
||||
struct cam_context *ctx;
|
||||
int rc;
|
||||
|
||||
index = CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map);
|
||||
CAM_DBG(CAM_LRME, "ctx index %llu, evt_id %u\n", index, evt_id);
|
||||
ctx = &g_lrme_dev->ctx[index];
|
||||
rc = ctx->irq_cb_intf(ctx, evt_id, evt_data);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "irq callback failed");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_dev_open(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct cam_lrme_dev *lrme_dev = g_lrme_dev;
|
||||
|
||||
if (!lrme_dev) {
|
||||
CAM_ERR(CAM_LRME,
|
||||
"LRME Dev not initialized, dev=%pK", lrme_dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&lrme_dev->lock);
|
||||
lrme_dev->open_cnt++;
|
||||
mutex_unlock(&lrme_dev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_lrme_dev_close(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_lrme_dev *lrme_dev = g_lrme_dev;
|
||||
struct cam_node *node = v4l2_get_subdevdata(sd);
|
||||
|
||||
if (!lrme_dev) {
|
||||
CAM_ERR(CAM_LRME, "Invalid args");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&lrme_dev->lock);
|
||||
if (lrme_dev->open_cnt <= 0) {
|
||||
CAM_DBG(CAM_LRME, "LRME subdev is already closed");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
lrme_dev->open_cnt--;
|
||||
if (!node) {
|
||||
CAM_ERR(CAM_LRME, "Node is NULL");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (lrme_dev->open_cnt == 0)
|
||||
cam_node_shutdown(node);
|
||||
|
||||
end:
|
||||
mutex_unlock(&lrme_dev->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = {
|
||||
.open = cam_lrme_dev_open,
|
||||
.close = cam_lrme_dev_close,
|
||||
};
|
||||
|
||||
static int cam_lrme_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
struct cam_hw_mgr_intf hw_mgr_intf;
|
||||
struct cam_node *node;
|
||||
|
||||
g_lrme_dev = kzalloc(sizeof(struct cam_lrme_dev), GFP_KERNEL);
|
||||
if (!g_lrme_dev) {
|
||||
CAM_ERR(CAM_LRME, "No memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops;
|
||||
|
||||
mutex_init(&g_lrme_dev->lock);
|
||||
|
||||
rc = cam_subdev_probe(&g_lrme_dev->sd, pdev, CAM_LRME_DEV_NAME,
|
||||
CAM_LRME_DEVICE_TYPE);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "LRME cam_subdev_probe failed");
|
||||
goto free_mem;
|
||||
}
|
||||
node = (struct cam_node *)g_lrme_dev->sd.token;
|
||||
|
||||
rc = cam_lrme_hw_mgr_init(&hw_mgr_intf, cam_lrme_dev_buf_done_cb);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Can not initialized LRME HW manager");
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
for (i = 0; i < CAM_CTX_MAX; i++) {
|
||||
rc = cam_lrme_context_init(&g_lrme_dev->lrme_ctx[i],
|
||||
&g_lrme_dev->ctx[i],
|
||||
&node->hw_mgr_intf, i);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "LRME context init failed");
|
||||
goto deinit_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
rc = cam_node_init(node, &hw_mgr_intf, g_lrme_dev->ctx, CAM_CTX_MAX,
|
||||
CAM_LRME_DEV_NAME);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "LRME node init failed");
|
||||
goto deinit_ctx;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_LRME, "%s probe complete", g_lrme_dev->sd.name);
|
||||
|
||||
return 0;
|
||||
|
||||
deinit_ctx:
|
||||
for (--i; i >= 0; i--) {
|
||||
if (cam_lrme_context_deinit(&g_lrme_dev->lrme_ctx[i]))
|
||||
CAM_ERR(CAM_LRME, "LRME context %d deinit failed", i);
|
||||
}
|
||||
unregister:
|
||||
if (cam_subdev_remove(&g_lrme_dev->sd))
|
||||
CAM_ERR(CAM_LRME, "Failed in subdev remove");
|
||||
free_mem:
|
||||
kfree(g_lrme_dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
for (i = 0; i < CAM_CTX_MAX; i++) {
|
||||
rc = cam_lrme_context_deinit(&g_lrme_dev->lrme_ctx[i]);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "LRME context %d deinit failed", i);
|
||||
}
|
||||
|
||||
rc = cam_lrme_hw_mgr_deinit();
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Failed in hw mgr deinit, rc=%d", rc);
|
||||
|
||||
rc = cam_subdev_remove(&g_lrme_dev->sd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Unregister failed");
|
||||
|
||||
mutex_destroy(&g_lrme_dev->lock);
|
||||
kfree(g_lrme_dev);
|
||||
g_lrme_dev = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_lrme_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,cam-lrme"
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver cam_lrme_driver = {
|
||||
.probe = cam_lrme_dev_probe,
|
||||
.remove = cam_lrme_dev_remove,
|
||||
.driver = {
|
||||
.name = "cam_lrme",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cam_lrme_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init cam_lrme_dev_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_lrme_driver);
|
||||
}
|
||||
|
||||
static void __exit cam_lrme_dev_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_lrme_driver);
|
||||
}
|
||||
|
||||
module_init(cam_lrme_dev_init_module);
|
||||
module_exit(cam_lrme_dev_exit_module);
|
||||
MODULE_DESCRIPTION("MSM LRME driver");
|
||||
MODULE_LICENSE("GPL v2");
|
16
drivers/cam_lrme/lrme_hw_mgr/Makefile
Normal file
16
drivers/cam_lrme/lrme_hw_mgr/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw
|
||||
ccflags-y += -I$(srctree)/techpack/camera
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_mgr.o
|
1155
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
Normal file
1155
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
Normal file
Diff onderdrukt omdat het te groot bestand
Laad Diff
126
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h
Normal file
126
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_MGR_H_
|
||||
#define _CAM_LRME_HW_MGR_H_
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <media/cam_lrme.h>
|
||||
#include "cam_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_req_mgr_workq.h"
|
||||
#include "cam_lrme_hw_intf.h"
|
||||
#include "cam_context.h"
|
||||
|
||||
#define CAM_LRME_HW_MAX 1
|
||||
#define CAM_LRME_WORKQ_NUM_TASK 10
|
||||
|
||||
#define CAM_LRME_DECODE_DEVICE_INDEX(ctxt_to_hw_map) \
|
||||
((uintptr_t)ctxt_to_hw_map & 0xF)
|
||||
|
||||
#define CAM_LRME_DECODE_PRIORITY(ctxt_to_hw_map) \
|
||||
(((uintptr_t)ctxt_to_hw_map & 0xF0) >> 4)
|
||||
|
||||
#define CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map) \
|
||||
((uint64_t)(uintptr_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT)
|
||||
|
||||
/**
|
||||
* enum cam_lrme_hw_mgr_ctx_priority
|
||||
*
|
||||
* CAM_LRME_PRIORITY_HIGH : High priority client
|
||||
* CAM_LRME_PRIORITY_NORMAL : Normal priority client
|
||||
*/
|
||||
enum cam_lrme_hw_mgr_ctx_priority {
|
||||
CAM_LRME_PRIORITY_HIGH,
|
||||
CAM_LRME_PRIORITY_NORMAL,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_mgr_work_data : HW Mgr work data
|
||||
*
|
||||
* @hw_device : Pointer to the hw device
|
||||
*/
|
||||
struct cam_lrme_mgr_work_data {
|
||||
struct cam_lrme_device *hw_device;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_debugfs_entry : debugfs entry struct
|
||||
*
|
||||
* @dentry : entry of debugfs
|
||||
* @dump_register : flag to dump registers
|
||||
*/
|
||||
struct cam_lrme_debugfs_entry {
|
||||
struct dentry *dentry;
|
||||
bool dump_register;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_device : LRME HW device
|
||||
*
|
||||
* @hw_caps : HW device's capabilities
|
||||
* @hw_intf : HW device's interface information
|
||||
* @num_context : Number of contexts using this device
|
||||
* @valid : Whether this device is valid
|
||||
* @work : HW device's work queue
|
||||
* @work_data : HW device's work data
|
||||
* @frame_pending_list_high : High priority request queue
|
||||
* @frame_pending_list_normal : Normal priority request queue
|
||||
* @high_req_lock : Spinlock of high priority queue
|
||||
* @normal_req_lock : Spinlock of normal priority queue
|
||||
*/
|
||||
struct cam_lrme_device {
|
||||
struct cam_lrme_dev_cap hw_caps;
|
||||
struct cam_hw_intf hw_intf;
|
||||
uint32_t num_context;
|
||||
bool valid;
|
||||
struct cam_req_mgr_core_workq *work;
|
||||
struct cam_lrme_mgr_work_data work_data[CAM_LRME_WORKQ_NUM_TASK];
|
||||
struct list_head frame_pending_list_high;
|
||||
struct list_head frame_pending_list_normal;
|
||||
spinlock_t high_req_lock;
|
||||
spinlock_t normal_req_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_mgr : LRME HW manager
|
||||
*
|
||||
* @device_count : Number of HW devices
|
||||
* @frame_free_list : List of free frame request
|
||||
* @hw_mgr_mutex : Mutex to protect HW manager data
|
||||
* @free_req_lock :Spinlock to protect frame_free_list
|
||||
* @hw_device : List of HW devices
|
||||
* @device_iommu : Device iommu
|
||||
* @cdm_iommu : cdm iommu
|
||||
* @frame_req : List of frame request to use
|
||||
* @lrme_caps : LRME capabilities
|
||||
* @event_cb : IRQ callback function
|
||||
* @debugfs_entry : debugfs entry to set debug prop
|
||||
*/
|
||||
struct cam_lrme_hw_mgr {
|
||||
uint32_t device_count;
|
||||
struct list_head frame_free_list;
|
||||
struct mutex hw_mgr_mutex;
|
||||
spinlock_t free_req_lock;
|
||||
struct cam_lrme_device hw_device[CAM_LRME_HW_MAX];
|
||||
struct cam_iommu_handle device_iommu;
|
||||
struct cam_iommu_handle cdm_iommu;
|
||||
struct cam_lrme_frame_request frame_req[CAM_CTX_REQ_MAX * CAM_CTX_MAX];
|
||||
struct cam_lrme_query_cap_cmd lrme_caps;
|
||||
cam_hw_event_cb_func event_cb;
|
||||
struct cam_lrme_debugfs_entry debugfs_entry;
|
||||
};
|
||||
|
||||
int cam_lrme_mgr_register_device(struct cam_hw_intf *lrme_hw_intf,
|
||||
struct cam_iommu_handle *device_iommu,
|
||||
struct cam_iommu_handle *cdm_iommu);
|
||||
int cam_lrme_mgr_deregister_device(int device_index);
|
||||
|
||||
#endif /* _CAM_LRME_HW_MGR_H_ */
|
18
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h
Normal file
18
drivers/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr_intf.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_MGR_INTF_H_
|
||||
#define _CAM_LRME_HW_MGR_INTF_H_
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
|
||||
int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf,
|
||||
cam_hw_event_cb_func cam_lrme_dev_buf_done_cb);
|
||||
int cam_lrme_hw_mgr_deinit(void);
|
||||
|
||||
#endif /* _CAM_LRME_HW_MGR_INTF_H_ */
|
15
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile
Normal file
15
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sync
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_lrme/lrme_hw_mgr/lrme_hw
|
||||
ccflags-y += -I$(srctree)/techpack/camera0
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_lrme_hw_dev.o cam_lrme_hw_core.o cam_lrme_hw_soc.o
|
1274
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
Normal file
1274
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
Normal file
Diff onderdrukt omdat het te groot bestand
Laad Diff
451
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h
Normal file
451
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h
Normal file
@@ -0,0 +1,451 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_CORE_H_
|
||||
#define _CAM_LRME_HW_CORE_H_
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <media/cam_defs.h>
|
||||
#include <media/cam_lrme.h>
|
||||
|
||||
#include "cam_common_util.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_io_util.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_cdm_intf_api.h"
|
||||
#include "cam_lrme_hw_intf.h"
|
||||
#include "cam_lrme_hw_soc.h"
|
||||
#include "cam_req_mgr_workq.h"
|
||||
|
||||
#define CAM_LRME_HW_RESET_TIMEOUT 3000
|
||||
|
||||
#define CAM_LRME_BUS_RD_MAX_CLIENTS 2
|
||||
#define CAM_LRME_BUS_WR_MAX_CLIENTS 2
|
||||
|
||||
#define CAM_LRME_HW_WORKQ_NUM_TASK 30
|
||||
|
||||
#define CAM_LRME_TOP_IRQ_MASK 0x19
|
||||
#define CAM_LRME_WE_IRQ_MASK_0 0x2
|
||||
#define CAM_LRME_WE_IRQ_MASK_1 0x0
|
||||
#define CAM_LRME_FE_IRQ_MASK 0x0
|
||||
|
||||
#define CAM_LRME_MAX_REG_PAIR_NUM 60
|
||||
|
||||
/**
|
||||
* enum cam_lrme_irq_set
|
||||
*
|
||||
* @CAM_LRME_IRQ_ENABLE : Enable irqs
|
||||
* @CAM_LRME_IRQ_DISABLE : Disable irqs
|
||||
*/
|
||||
enum cam_lrme_irq_set {
|
||||
CAM_LRME_IRQ_ENABLE,
|
||||
CAM_LRME_IRQ_DISABLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_cdm_info : information used to submit cdm command
|
||||
*
|
||||
* @cdm_handle : CDM handle for this device
|
||||
* @cdm_ops : CDM ops
|
||||
* @cdm_cmd : CDM command pointer
|
||||
*/
|
||||
struct cam_lrme_cdm_info {
|
||||
uint32_t cdm_handle;
|
||||
struct cam_cdm_utils_ops *cdm_ops;
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_work_data : Work data for HW work queue
|
||||
*
|
||||
* @top_irq_status : Top registers irq status
|
||||
* @fe_irq_status : FE engine irq status
|
||||
* @we_irq_status : WE engine irq status
|
||||
*/
|
||||
struct cam_lrme_hw_work_data {
|
||||
uint32_t top_irq_status;
|
||||
uint32_t fe_irq_status;
|
||||
uint32_t we_irq_status[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_lrme_core_state : LRME core states
|
||||
*
|
||||
* @CAM_LRME_CORE_STATE_UNINIT : LRME is in uninit state
|
||||
* @CAM_LRME_CORE_STATE_INIT : LRME is in init state after probe
|
||||
* @ CAM_LRME_CORE_STATE_IDLE : LRME is in idle state. Hardware is in
|
||||
* this state when no frame is processing
|
||||
* or waiting for this core.
|
||||
* @CAM_LRME_CORE_STATE_REQ_PENDING : LRME is in pending state. One frame is
|
||||
* waiting for processing
|
||||
* @CAM_LRME_CORE_STATE_PROCESSING : LRME is in processing state. HW manager
|
||||
* can submit one more frame to HW
|
||||
* @CAM_LRME_CORE_STATE_REQ_PROC_PEND : Indicate two frames are inside HW.
|
||||
* @CAM_LRME_CORE_STATE_RECOVERY : Indicate core is in the process of reset
|
||||
* @CAM_LRME_CORE_STATE_MAX : upper limit of states
|
||||
*/
|
||||
enum cam_lrme_core_state {
|
||||
CAM_LRME_CORE_STATE_UNINIT,
|
||||
CAM_LRME_CORE_STATE_INIT,
|
||||
CAM_LRME_CORE_STATE_IDLE,
|
||||
CAM_LRME_CORE_STATE_REQ_PENDING,
|
||||
CAM_LRME_CORE_STATE_PROCESSING,
|
||||
CAM_LRME_CORE_STATE_REQ_PROC_PEND,
|
||||
CAM_LRME_CORE_STATE_RECOVERY,
|
||||
CAM_LRME_CORE_STATE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_core : LRME HW core information
|
||||
*
|
||||
* @hw_info : Pointer to base HW information structure
|
||||
* @device_iommu : Device iommu handle
|
||||
* @cdm_iommu : CDM iommu handle
|
||||
* @hw_caps : Hardware capabilities
|
||||
* @state : Hardware state
|
||||
* @reset_complete : Reset completion
|
||||
* @work : Hardware workqueue to handle irq events
|
||||
* @work_data : Work data used by hardware workqueue
|
||||
* @hw_mgr_cb : Hw manager callback
|
||||
* @req_proc : Pointer to the processing frame request
|
||||
* @req_submit : Pointer to the frame request waiting for processing
|
||||
* @hw_cdm_info : CDM information used by this device
|
||||
* @hw_idx : Hardware index
|
||||
*/
|
||||
struct cam_lrme_core {
|
||||
struct cam_lrme_hw_info *hw_info;
|
||||
struct cam_iommu_handle device_iommu;
|
||||
struct cam_iommu_handle cdm_iommu;
|
||||
struct cam_lrme_dev_cap hw_caps;
|
||||
enum cam_lrme_core_state state;
|
||||
struct completion reset_complete;
|
||||
struct cam_req_mgr_core_workq *work;
|
||||
struct cam_lrme_hw_work_data work_data[CAM_LRME_HW_WORKQ_NUM_TASK];
|
||||
struct cam_lrme_hw_cmd_set_cb hw_mgr_cb;
|
||||
struct cam_lrme_frame_request *req_proc;
|
||||
struct cam_lrme_frame_request *req_submit;
|
||||
struct cam_lrme_cdm_info *hw_cdm_info;
|
||||
uint32_t hw_idx;
|
||||
bool dump_flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_rd_reg_common : Offsets of FE common registers
|
||||
*
|
||||
* @hw_version : Offset of hw_version register
|
||||
* @hw_capability : Offset of hw_capability register
|
||||
* @sw_reset : Offset of sw_reset register
|
||||
* @cgc_override : Offset of cgc_override register
|
||||
* @irq_mask : Offset of irq_mask register
|
||||
* @irq_clear : Offset of irq_clear register
|
||||
* @irq_cmd : Offset of irq_cmd register
|
||||
* @irq_status : Offset of irq_status register
|
||||
* @cmd : Offset of cmd register
|
||||
* @irq_set : Offset of irq_set register
|
||||
* @misr_reset : Offset of misr_reset register
|
||||
* @security_cfg : Offset of security_cfg register
|
||||
* @pwr_iso_cfg : Offset of pwr_iso_cfg register
|
||||
* @pwr_iso_seed : Offset of pwr_iso_seed register
|
||||
* @test_bus_ctrl : Offset of test_bus_ctrl register
|
||||
* @spare : Offset of spare register
|
||||
*/
|
||||
struct cam_lrme_bus_rd_reg_common {
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_capability;
|
||||
uint32_t sw_reset;
|
||||
uint32_t cgc_override;
|
||||
uint32_t irq_mask;
|
||||
uint32_t irq_clear;
|
||||
uint32_t irq_cmd;
|
||||
uint32_t irq_status;
|
||||
uint32_t cmd;
|
||||
uint32_t irq_set;
|
||||
uint32_t misr_reset;
|
||||
uint32_t security_cfg;
|
||||
uint32_t pwr_iso_cfg;
|
||||
uint32_t pwr_iso_seed;
|
||||
uint32_t test_bus_ctrl;
|
||||
uint32_t spare;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_wr_reg_common : Offset of WE common registers
|
||||
* @hw_version : Offset of hw_version register
|
||||
* @hw_capability : Offset of hw_capability register
|
||||
* @sw_reset : Offset of sw_reset register
|
||||
* @cgc_override : Offset of cgc_override register
|
||||
* @misr_reset : Offset of misr_reset register
|
||||
* @pwr_iso_cfg : Offset of pwr_iso_cfg register
|
||||
* @test_bus_ctrl : Offset of test_bus_ctrl register
|
||||
* @composite_mask_0 : Offset of composite_mask_0 register
|
||||
* @irq_mask_0 : Offset of irq_mask_0 register
|
||||
* @irq_mask_1 : Offset of irq_mask_1 register
|
||||
* @irq_clear_0 : Offset of irq_clear_0 register
|
||||
* @irq_clear_1 : Offset of irq_clear_1 register
|
||||
* @irq_status_0 : Offset of irq_status_0 register
|
||||
* @irq_status_1 : Offset of irq_status_1 register
|
||||
* @irq_cmd : Offset of irq_cmd register
|
||||
* @irq_set_0 : Offset of irq_set_0 register
|
||||
* @irq_set_1 : Offset of irq_set_1 register
|
||||
* @addr_fifo_status : Offset of addr_fifo_status register
|
||||
* @frame_header_cfg0 : Offset of frame_header_cfg0 register
|
||||
* @frame_header_cfg1 : Offset of frame_header_cfg1 register
|
||||
* @spare : Offset of spare register
|
||||
*/
|
||||
struct cam_lrme_bus_wr_reg_common {
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_capability;
|
||||
uint32_t sw_reset;
|
||||
uint32_t cgc_override;
|
||||
uint32_t misr_reset;
|
||||
uint32_t pwr_iso_cfg;
|
||||
uint32_t test_bus_ctrl;
|
||||
uint32_t composite_mask_0;
|
||||
uint32_t irq_mask_0;
|
||||
uint32_t irq_mask_1;
|
||||
uint32_t irq_clear_0;
|
||||
uint32_t irq_clear_1;
|
||||
uint32_t irq_status_0;
|
||||
uint32_t irq_status_1;
|
||||
uint32_t irq_cmd;
|
||||
uint32_t irq_set_0;
|
||||
uint32_t irq_set_1;
|
||||
uint32_t addr_fifo_status;
|
||||
uint32_t frame_header_cfg0;
|
||||
uint32_t frame_header_cfg1;
|
||||
uint32_t spare;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_rd_bus_client : Offset of FE registers
|
||||
*
|
||||
* @core_cfg : Offset of core_cfg register
|
||||
* @ccif_meta_data : Offset of ccif_meta_data register
|
||||
* @addr_image : Offset of addr_image register
|
||||
* @rd_buffer_size : Offset of rd_buffer_size register
|
||||
* @rd_stride : Offset of rd_stride register
|
||||
* @unpack_cfg_0 : Offset of unpack_cfg_0 register
|
||||
* @latency_buff_allocation : Offset of latency_buff_allocation register
|
||||
* @burst_limit_cfg : Offset of burst_limit_cfg register
|
||||
* @misr_cfg_0 : Offset of misr_cfg_0 register
|
||||
* @misr_cfg_1 : Offset of misr_cfg_1 register
|
||||
* @misr_rd_val : Offset of misr_rd_val register
|
||||
* @debug_status_cfg : Offset of debug_status_cfg register
|
||||
* @debug_status_0 : Offset of debug_status_0 register
|
||||
* @debug_status_1 : Offset of debug_status_1 register
|
||||
*/
|
||||
struct cam_lrme_bus_rd_bus_client {
|
||||
uint32_t core_cfg;
|
||||
uint32_t ccif_meta_data;
|
||||
uint32_t addr_image;
|
||||
uint32_t rd_buffer_size;
|
||||
uint32_t rd_stride;
|
||||
uint32_t unpack_cfg_0;
|
||||
uint32_t latency_buff_allocation;
|
||||
uint32_t burst_limit_cfg;
|
||||
uint32_t misr_cfg_0;
|
||||
uint32_t misr_cfg_1;
|
||||
uint32_t misr_rd_val;
|
||||
uint32_t debug_status_cfg;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_wr_bus_client : Offset of WE registers
|
||||
*
|
||||
* @status_0 : Offset of status_0 register
|
||||
* @status_1 : Offset of status_1 register
|
||||
* @cfg : Offset of cfg register
|
||||
* @addr_frame_header : Offset of addr_frame_header register
|
||||
* @frame_header_cfg : Offset of frame_header_cfg register
|
||||
* @addr_image : Offset of addr_image register
|
||||
* @addr_image_offset : Offset of addr_image_offset register
|
||||
* @buffer_width_cfg : Offset of buffer_width_cfg register
|
||||
* @buffer_height_cfg : Offset of buffer_height_cfg register
|
||||
* @packer_cfg : Offset of packer_cfg register
|
||||
* @wr_stride : Offset of wr_stride register
|
||||
* @irq_subsample_cfg_period : Offset of irq_subsample_cfg_period register
|
||||
* @irq_subsample_cfg_pattern : Offset of irq_subsample_cfg_pattern register
|
||||
* @burst_limit_cfg : Offset of burst_limit_cfg register
|
||||
* @misr_cfg : Offset of misr_cfg register
|
||||
* @misr_rd_word_sel : Offset of misr_rd_word_sel register
|
||||
* @misr_val : Offset of misr_val register
|
||||
* @debug_status_cfg : Offset of debug_status_cfg register
|
||||
* @debug_status_0 : Offset of debug_status_0 register
|
||||
* @debug_status_1 : Offset of debug_status_1 register
|
||||
*/
|
||||
struct cam_lrme_bus_wr_bus_client {
|
||||
uint32_t status_0;
|
||||
uint32_t status_1;
|
||||
uint32_t cfg;
|
||||
uint32_t addr_frame_header;
|
||||
uint32_t frame_header_cfg;
|
||||
uint32_t addr_image;
|
||||
uint32_t addr_image_offset;
|
||||
uint32_t buffer_width_cfg;
|
||||
uint32_t buffer_height_cfg;
|
||||
uint32_t packer_cfg;
|
||||
uint32_t wr_stride;
|
||||
uint32_t irq_subsample_cfg_period;
|
||||
uint32_t irq_subsample_cfg_pattern;
|
||||
uint32_t burst_limit_cfg;
|
||||
uint32_t misr_cfg;
|
||||
uint32_t misr_rd_word_sel;
|
||||
uint32_t misr_val;
|
||||
uint32_t debug_status_cfg;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_rd_hw_info : FE registers information
|
||||
*
|
||||
* @common_reg : FE common register
|
||||
* @bus_client_reg : List of FE bus registers information
|
||||
*/
|
||||
struct cam_lrme_bus_rd_hw_info {
|
||||
struct cam_lrme_bus_rd_reg_common common_reg;
|
||||
struct cam_lrme_bus_rd_bus_client
|
||||
bus_client_reg[CAM_LRME_BUS_RD_MAX_CLIENTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_bus_wr_hw_info : WE engine registers information
|
||||
*
|
||||
* @common_reg : WE common register
|
||||
* @bus_client_reg : List of WE bus registers information
|
||||
*/
|
||||
struct cam_lrme_bus_wr_hw_info {
|
||||
struct cam_lrme_bus_wr_reg_common common_reg;
|
||||
struct cam_lrme_bus_wr_bus_client
|
||||
bus_client_reg[CAM_LRME_BUS_WR_MAX_CLIENTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_clc_reg : Offset of clc registers
|
||||
*
|
||||
* @clc_hw_version : Offset of clc_hw_version register
|
||||
* @clc_hw_status : Offset of clc_hw_status register
|
||||
* @clc_hw_status_dbg : Offset of clc_hw_status_dbg register
|
||||
* @clc_module_cfg : Offset of clc_module_cfg register
|
||||
* @clc_moduleformat : Offset of clc_moduleformat register
|
||||
* @clc_rangestep : Offset of clc_rangestep register
|
||||
* @clc_offset : Offset of clc_offset register
|
||||
* @clc_maxallowedsad : Offset of clc_maxallowedsad register
|
||||
* @clc_minallowedtarmad : Offset of clc_minallowedtarmad register
|
||||
* @clc_meaningfulsaddiff : Offset of clc_meaningfulsaddiff register
|
||||
* @clc_minsaddiffdenom : Offset of clc_minsaddiffdenom register
|
||||
* @clc_robustnessmeasuredistmap_0 : Offset of measuredistmap_0 register
|
||||
* @clc_robustnessmeasuredistmap_1 : Offset of measuredistmap_1 register
|
||||
* @clc_robustnessmeasuredistmap_2 : Offset of measuredistmap_2 register
|
||||
* @clc_robustnessmeasuredistmap_3 : Offset of measuredistmap_3 register
|
||||
* @clc_robustnessmeasuredistmap_4 : Offset of measuredistmap_4 register
|
||||
* @clc_robustnessmeasuredistmap_5 : Offset of measuredistmap_5 register
|
||||
* @clc_robustnessmeasuredistmap_6 : Offset of measuredistmap_6 register
|
||||
* @clc_robustnessmeasuredistmap_7 : Offset of measuredistmap_7 register
|
||||
* @clc_ds_crop_horizontal : Offset of clc_ds_crop_horizontal register
|
||||
* @clc_ds_crop_vertical : Offset of clc_ds_crop_vertical register
|
||||
* @clc_tar_pd_unpacker : Offset of clc_tar_pd_unpacker register
|
||||
* @clc_ref_pd_unpacker : Offset of clc_ref_pd_unpacker register
|
||||
* @clc_sw_override : Offset of clc_sw_override register
|
||||
* @clc_tar_height : Offset of clc_tar_height register
|
||||
* @clc_test_bus_ctrl : Offset of clc_test_bus_ctrl register
|
||||
* @clc_spare : Offset of clc_spare register
|
||||
*/
|
||||
struct cam_lrme_clc_reg {
|
||||
uint32_t clc_hw_version;
|
||||
uint32_t clc_hw_status;
|
||||
uint32_t clc_hw_status_dbg;
|
||||
uint32_t clc_module_cfg;
|
||||
uint32_t clc_moduleformat;
|
||||
uint32_t clc_rangestep;
|
||||
uint32_t clc_offset;
|
||||
uint32_t clc_maxallowedsad;
|
||||
uint32_t clc_minallowedtarmad;
|
||||
uint32_t clc_meaningfulsaddiff;
|
||||
uint32_t clc_minsaddiffdenom;
|
||||
uint32_t clc_robustnessmeasuredistmap_0;
|
||||
uint32_t clc_robustnessmeasuredistmap_1;
|
||||
uint32_t clc_robustnessmeasuredistmap_2;
|
||||
uint32_t clc_robustnessmeasuredistmap_3;
|
||||
uint32_t clc_robustnessmeasuredistmap_4;
|
||||
uint32_t clc_robustnessmeasuredistmap_5;
|
||||
uint32_t clc_robustnessmeasuredistmap_6;
|
||||
uint32_t clc_robustnessmeasuredistmap_7;
|
||||
uint32_t clc_ds_crop_horizontal;
|
||||
uint32_t clc_ds_crop_vertical;
|
||||
uint32_t clc_tar_pd_unpacker;
|
||||
uint32_t clc_ref_pd_unpacker;
|
||||
uint32_t clc_sw_override;
|
||||
uint32_t clc_tar_height;
|
||||
uint32_t clc_ref_height;
|
||||
uint32_t clc_test_bus_ctrl;
|
||||
uint32_t clc_spare;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_titan_reg : Offset of LRME top registers
|
||||
*
|
||||
* @top_hw_version : Offset of top_hw_version register
|
||||
* @top_titan_version : Offset of top_titan_version register
|
||||
* @top_rst_cmd : Offset of top_rst_cmd register
|
||||
* @top_core_clk_cfg : Offset of top_core_clk_cfg register
|
||||
* @top_irq_status : Offset of top_irq_status register
|
||||
* @top_irq_mask : Offset of top_irq_mask register
|
||||
* @top_irq_clear : Offset of top_irq_clear register
|
||||
* @top_irq_set : Offset of top_irq_set register
|
||||
* @top_irq_cmd : Offset of top_irq_cmd register
|
||||
* @top_violation_status : Offset of top_violation_status register
|
||||
* @top_spare : Offset of top_spare register
|
||||
*/
|
||||
struct cam_lrme_titan_reg {
|
||||
uint32_t top_hw_version;
|
||||
uint32_t top_titan_version;
|
||||
uint32_t top_rst_cmd;
|
||||
uint32_t top_core_clk_cfg;
|
||||
uint32_t top_irq_status;
|
||||
uint32_t top_irq_mask;
|
||||
uint32_t top_irq_clear;
|
||||
uint32_t top_irq_set;
|
||||
uint32_t top_irq_cmd;
|
||||
uint32_t top_violation_status;
|
||||
uint32_t top_spare;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_info : LRME registers information
|
||||
*
|
||||
* @clc_reg : LRME CLC registers
|
||||
* @bus_rd_reg : LRME FE registers
|
||||
* @bus_wr_reg : LRME WE registers
|
||||
* @titan_reg : LRME top reisters
|
||||
*/
|
||||
struct cam_lrme_hw_info {
|
||||
struct cam_lrme_clc_reg clc_reg;
|
||||
struct cam_lrme_bus_rd_hw_info bus_rd_reg;
|
||||
struct cam_lrme_bus_wr_hw_info bus_wr_reg;
|
||||
struct cam_lrme_titan_reg titan_reg;
|
||||
};
|
||||
|
||||
int cam_lrme_hw_process_irq(void *priv, void *data);
|
||||
int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
|
||||
uint32_t arg_size);
|
||||
int cam_lrme_hw_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size);
|
||||
int cam_lrme_hw_stop(void *hw_priv, void *stop_args, uint32_t arg_size);
|
||||
int cam_lrme_hw_get_caps(void *hw_priv, void *get_hw_cap_args,
|
||||
uint32_t arg_size);
|
||||
irqreturn_t cam_lrme_hw_irq(int irq_num, void *data);
|
||||
int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size);
|
||||
int cam_lrme_hw_util_get_caps(struct cam_hw_info *lrme_hw,
|
||||
struct cam_lrme_dev_cap *hw_caps);
|
||||
int cam_lrme_hw_start(void *hw_priv, void *hw_init_args, uint32_t arg_size);
|
||||
int cam_lrme_hw_flush(void *hw_priv, void *hw_flush_args, uint32_t arg_size);
|
||||
void cam_lrme_set_irq(struct cam_hw_info *lrme_hw, enum cam_lrme_irq_set set);
|
||||
|
||||
#endif /* _CAM_LRME_HW_CORE_H_ */
|
304
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
Normal file
304
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
Normal file
@@ -0,0 +1,304 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <media/cam_req_mgr.h>
|
||||
|
||||
#include "cam_subdev.h"
|
||||
#include "cam_lrme_hw_intf.h"
|
||||
#include "cam_lrme_hw_core.h"
|
||||
#include "cam_lrme_hw_soc.h"
|
||||
#include "cam_lrme_hw_reg.h"
|
||||
#include "cam_req_mgr_workq.h"
|
||||
#include "cam_lrme_hw_mgr.h"
|
||||
#include "cam_mem_mgr_api.h"
|
||||
#include "cam_smmu_api.h"
|
||||
|
||||
static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core,
|
||||
struct cam_hw_info *lrme_hw)
|
||||
{
|
||||
int rc, i;
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
struct cam_cdm_acquire_data cdm_acquire;
|
||||
struct cam_lrme_cdm_info *hw_cdm_info;
|
||||
|
||||
hw_cdm_info = kzalloc(sizeof(struct cam_lrme_cdm_info),
|
||||
GFP_KERNEL);
|
||||
if (!hw_cdm_info) {
|
||||
CAM_ERR(CAM_LRME, "No memory for hw_cdm_info");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cdm_cmd = kzalloc((sizeof(struct cam_cdm_bl_request) +
|
||||
((CAM_LRME_MAX_HW_ENTRIES - 1) *
|
||||
sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
|
||||
if (!cdm_cmd) {
|
||||
CAM_ERR(CAM_LRME, "No memory for cdm_cmd");
|
||||
kfree(hw_cdm_info);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(&cdm_acquire, 0, sizeof(cdm_acquire));
|
||||
strlcpy(cdm_acquire.identifier, "lrmecdm", sizeof("lrmecdm"));
|
||||
cdm_acquire.cell_index = lrme_hw->soc_info.index;
|
||||
cdm_acquire.handle = 0;
|
||||
cdm_acquire.userdata = hw_cdm_info;
|
||||
cdm_acquire.cam_cdm_callback = NULL;
|
||||
cdm_acquire.id = CAM_CDM_VIRTUAL;
|
||||
cdm_acquire.base_array_cnt = lrme_hw->soc_info.num_reg_map;
|
||||
for (i = 0; i < lrme_hw->soc_info.num_reg_map; i++)
|
||||
cdm_acquire.base_array[i] = &lrme_hw->soc_info.reg_map[i];
|
||||
|
||||
rc = cam_cdm_acquire(&cdm_acquire);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Can't acquire cdm");
|
||||
goto error;
|
||||
}
|
||||
|
||||
hw_cdm_info->cdm_cmd = cdm_cmd;
|
||||
hw_cdm_info->cdm_ops = cdm_acquire.ops;
|
||||
hw_cdm_info->cdm_handle = cdm_acquire.handle;
|
||||
|
||||
lrme_core->hw_cdm_info = hw_cdm_info;
|
||||
CAM_DBG(CAM_LRME, "cdm acquire done");
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(cdm_cmd);
|
||||
kfree(hw_cdm_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_hw_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cam_hw_info *lrme_hw;
|
||||
struct cam_hw_intf lrme_hw_intf;
|
||||
struct cam_lrme_core *lrme_core;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_lrme_hw_info *hw_info;
|
||||
int rc, i;
|
||||
|
||||
lrme_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!lrme_hw) {
|
||||
CAM_ERR(CAM_LRME, "No memory to create lrme_hw");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lrme_core = kzalloc(sizeof(struct cam_lrme_core), GFP_KERNEL);
|
||||
if (!lrme_core) {
|
||||
CAM_ERR(CAM_LRME, "No memory to create lrme_core");
|
||||
kfree(lrme_hw);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lrme_hw->core_info = lrme_core;
|
||||
lrme_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||
lrme_hw->soc_info.pdev = pdev;
|
||||
lrme_hw->soc_info.dev = &pdev->dev;
|
||||
lrme_hw->soc_info.dev_name = pdev->name;
|
||||
lrme_hw->open_count = 0;
|
||||
lrme_core->state = CAM_LRME_CORE_STATE_INIT;
|
||||
|
||||
mutex_init(&lrme_hw->hw_mutex);
|
||||
spin_lock_init(&lrme_hw->hw_lock);
|
||||
init_completion(&lrme_hw->hw_complete);
|
||||
init_completion(&lrme_core->reset_complete);
|
||||
|
||||
rc = cam_req_mgr_workq_create("cam_lrme_hw_worker",
|
||||
CAM_LRME_HW_WORKQ_NUM_TASK,
|
||||
&lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc);
|
||||
goto free_memory;
|
||||
}
|
||||
|
||||
for (i = 0; i < CAM_LRME_HW_WORKQ_NUM_TASK; i++)
|
||||
lrme_core->work->task.pool[i].payload =
|
||||
&lrme_core->work_data[i];
|
||||
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev || !match_dev->data) {
|
||||
CAM_ERR(CAM_LRME, "No Of_match data, %pK", match_dev);
|
||||
rc = -EINVAL;
|
||||
goto destroy_workqueue;
|
||||
}
|
||||
hw_info = (struct cam_lrme_hw_info *)match_dev->data;
|
||||
lrme_core->hw_info = hw_info;
|
||||
|
||||
rc = cam_lrme_soc_init_resources(&lrme_hw->soc_info,
|
||||
cam_lrme_hw_irq, lrme_hw);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to init soc, rc=%d", rc);
|
||||
goto destroy_workqueue;
|
||||
}
|
||||
|
||||
rc = cam_lrme_hw_dev_util_cdm_acquire(lrme_core, lrme_hw);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to acquire cdm");
|
||||
goto deinit_platform_res;
|
||||
}
|
||||
|
||||
rc = cam_smmu_get_handle("lrme", &lrme_core->device_iommu.non_secure);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Get iommu handle failed");
|
||||
goto release_cdm;
|
||||
}
|
||||
|
||||
rc = cam_lrme_hw_start(lrme_hw, NULL, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to hw init, rc=%d", rc);
|
||||
goto detach_smmu;
|
||||
}
|
||||
|
||||
rc = cam_lrme_hw_util_get_caps(lrme_hw, &lrme_core->hw_caps);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to get hw caps, rc=%d", rc);
|
||||
if (cam_lrme_hw_stop(lrme_hw, NULL, 0))
|
||||
CAM_ERR(CAM_LRME, "Failed in hw deinit");
|
||||
goto detach_smmu;
|
||||
}
|
||||
|
||||
rc = cam_lrme_hw_stop(lrme_hw, NULL, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to deinit hw, rc=%d", rc);
|
||||
goto detach_smmu;
|
||||
}
|
||||
|
||||
lrme_core->hw_idx = lrme_hw->soc_info.index;
|
||||
lrme_hw_intf.hw_priv = lrme_hw;
|
||||
lrme_hw_intf.hw_idx = lrme_hw->soc_info.index;
|
||||
lrme_hw_intf.hw_ops.get_hw_caps = cam_lrme_hw_get_caps;
|
||||
lrme_hw_intf.hw_ops.init = NULL;
|
||||
lrme_hw_intf.hw_ops.deinit = NULL;
|
||||
lrme_hw_intf.hw_ops.reset = cam_lrme_hw_reset;
|
||||
lrme_hw_intf.hw_ops.reserve = NULL;
|
||||
lrme_hw_intf.hw_ops.release = NULL;
|
||||
lrme_hw_intf.hw_ops.start = cam_lrme_hw_start;
|
||||
lrme_hw_intf.hw_ops.stop = cam_lrme_hw_stop;
|
||||
lrme_hw_intf.hw_ops.read = NULL;
|
||||
lrme_hw_intf.hw_ops.write = NULL;
|
||||
lrme_hw_intf.hw_ops.process_cmd = cam_lrme_hw_process_cmd;
|
||||
lrme_hw_intf.hw_ops.flush = cam_lrme_hw_flush;
|
||||
lrme_hw_intf.hw_type = CAM_HW_LRME;
|
||||
|
||||
rc = cam_cdm_get_iommu_handle("lrmecdm", &lrme_core->cdm_iommu);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to acquire the CDM iommu handles");
|
||||
goto detach_smmu;
|
||||
}
|
||||
|
||||
rc = cam_lrme_mgr_register_device(&lrme_hw_intf,
|
||||
&lrme_core->device_iommu,
|
||||
&lrme_core->cdm_iommu);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to register device");
|
||||
goto detach_smmu;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, lrme_hw);
|
||||
CAM_DBG(CAM_LRME, "LRME-%d probe successful", lrme_hw_intf.hw_idx);
|
||||
|
||||
return rc;
|
||||
|
||||
detach_smmu:
|
||||
cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure);
|
||||
release_cdm:
|
||||
cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle);
|
||||
kfree(lrme_core->hw_cdm_info->cdm_cmd);
|
||||
kfree(lrme_core->hw_cdm_info);
|
||||
deinit_platform_res:
|
||||
if (cam_lrme_soc_deinit_resources(&lrme_hw->soc_info))
|
||||
CAM_ERR(CAM_LRME, "Failed in soc deinit");
|
||||
mutex_destroy(&lrme_hw->hw_mutex);
|
||||
destroy_workqueue:
|
||||
cam_req_mgr_workq_destroy(&lrme_core->work);
|
||||
free_memory:
|
||||
mutex_destroy(&lrme_hw->hw_mutex);
|
||||
kfree(lrme_hw);
|
||||
kfree(lrme_core);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_hw_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_hw_info *lrme_hw;
|
||||
struct cam_lrme_core *lrme_core;
|
||||
|
||||
lrme_hw = platform_get_drvdata(pdev);
|
||||
if (!lrme_hw) {
|
||||
CAM_ERR(CAM_LRME, "Invalid lrme_hw from fd_hw_intf");
|
||||
rc = -ENODEV;
|
||||
goto deinit_platform_res;
|
||||
}
|
||||
|
||||
lrme_core = (struct cam_lrme_core *)lrme_hw->core_info;
|
||||
if (!lrme_core) {
|
||||
CAM_ERR(CAM_LRME, "Invalid lrme_core from fd_hw");
|
||||
rc = -EINVAL;
|
||||
goto deinit_platform_res;
|
||||
}
|
||||
|
||||
cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure);
|
||||
cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle);
|
||||
cam_lrme_mgr_deregister_device(lrme_core->hw_idx);
|
||||
|
||||
kfree(lrme_core->hw_cdm_info->cdm_cmd);
|
||||
kfree(lrme_core->hw_cdm_info);
|
||||
kfree(lrme_core);
|
||||
|
||||
deinit_platform_res:
|
||||
rc = cam_lrme_soc_deinit_resources(&lrme_hw->soc_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Error in LRME soc deinit, rc=%d", rc);
|
||||
|
||||
mutex_destroy(&lrme_hw->hw_mutex);
|
||||
kfree(lrme_hw);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_lrme_hw_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,lrme",
|
||||
.data = &cam_lrme10_hw_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, cam_lrme_hw_dt_match);
|
||||
|
||||
static struct platform_driver cam_lrme_hw_driver = {
|
||||
.probe = cam_lrme_hw_dev_probe,
|
||||
.remove = cam_lrme_hw_dev_remove,
|
||||
.driver = {
|
||||
.name = "cam_lrme_hw",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cam_lrme_hw_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init cam_lrme_hw_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_lrme_hw_driver);
|
||||
}
|
||||
|
||||
static void __exit cam_lrme_hw_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_lrme_hw_driver);
|
||||
}
|
||||
|
||||
module_init(cam_lrme_hw_init_module);
|
||||
module_exit(cam_lrme_hw_exit_module);
|
||||
MODULE_DESCRIPTION("CAM LRME HW driver");
|
||||
MODULE_LICENSE("GPL v2");
|
195
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h
Normal file
195
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_INTF_H_
|
||||
#define _CAM_LRME_HW_INTF_H_
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <media/cam_cpas.h>
|
||||
#include <media/cam_req_mgr.h>
|
||||
#include <media/cam_lrme.h>
|
||||
|
||||
#include "cam_io_util.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_subdev.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
|
||||
#define CAM_LRME_MAX_IO_BUFFER 2
|
||||
#define CAM_LRME_MAX_HW_ENTRIES 5
|
||||
|
||||
#define CAM_LRME_BASE_IDX 0
|
||||
|
||||
/**
|
||||
* enum cam_lrme_hw_type : Enum for LRME HW type
|
||||
*
|
||||
* @CAM_HW_LRME : LRME HW type
|
||||
*/
|
||||
enum cam_lrme_hw_type {
|
||||
CAM_HW_LRME,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_lrme_cb_type : HW manager call back type
|
||||
*
|
||||
* @CAM_LRME_CB_BUF_DONE : Indicate buf done has been generated
|
||||
* @CAM_LRME_CB_COMP_REG_UPDATE : Indicate receiving WE comp reg update
|
||||
* @CAM_LRME_CB_PUT_FRAME : Request HW manager to put back the frame
|
||||
* @CAM_LRME_CB_ERROR : Indicate error irq has been generated
|
||||
*/
|
||||
enum cam_lrme_cb_type {
|
||||
CAM_LRME_CB_BUF_DONE = 1,
|
||||
CAM_LRME_CB_COMP_REG_UPDATE = 1 << 1,
|
||||
CAM_LRME_CB_PUT_FRAME = 1 << 2,
|
||||
CAM_LRME_CB_ERROR = 1 << 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_lrme_hw_cmd_type : HW CMD type
|
||||
*
|
||||
* @CAM_LRME_HW_CMD_prepare_hw_update : Prepare HW update
|
||||
* @CAM_LRME_HW_CMD_REGISTER_CB : register HW manager callback
|
||||
* @CAM_LRME_HW_CMD_SUBMIT : Submit frame to HW
|
||||
* @CAM_LRME_HW_CMD_DUMP_REGISTER : dump register values
|
||||
*/
|
||||
enum cam_lrme_hw_cmd_type {
|
||||
CAM_LRME_HW_CMD_PREPARE_HW_UPDATE,
|
||||
CAM_LRME_HW_CMD_REGISTER_CB,
|
||||
CAM_LRME_HW_CMD_SUBMIT,
|
||||
CAM_LRME_HW_CMD_DUMP_REGISTER,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_lrme_hw_reset_type : Type of reset
|
||||
*
|
||||
* @CAM_LRME_HW_RESET_TYPE_HW_RESET : HW reset
|
||||
* @CAM_LRME_HW_RESET_TYPE_SW_RESET : SW reset
|
||||
*/
|
||||
enum cam_lrme_hw_reset_type {
|
||||
CAM_LRME_HW_RESET_TYPE_HW_RESET,
|
||||
CAM_LRME_HW_RESET_TYPE_SW_RESET,
|
||||
};
|
||||
|
||||
/**
|
||||
*struct cam_lrme_frame_request : LRME frame request
|
||||
*
|
||||
* @frame_list : List head
|
||||
* @req_id : Request ID
|
||||
* @ctxt_to_hw_map : Information about context id, priority and device id
|
||||
* @hw_device : Pointer to HW device
|
||||
* @hw_update_entries : List of hw_update_entries
|
||||
* @num_hw_update_entries : number of hw_update_entries
|
||||
*/
|
||||
struct cam_lrme_frame_request {
|
||||
struct list_head frame_list;
|
||||
uint64_t req_id;
|
||||
void *ctxt_to_hw_map;
|
||||
struct cam_lrme_device *hw_device;
|
||||
struct cam_hw_update_entry hw_update_entries[CAM_LRME_MAX_HW_ENTRIES];
|
||||
uint32_t num_hw_update_entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_io_buffer : IO buffer information
|
||||
*
|
||||
* @valid : Indicate whether this IO config is valid
|
||||
* @io_cfg : Pointer to IO configuration
|
||||
* @num_buf : Number of buffers
|
||||
* @num_plane : Number of planes
|
||||
* @io_addr : List of IO address
|
||||
*/
|
||||
struct cam_lrme_hw_io_buffer {
|
||||
bool valid;
|
||||
struct cam_buf_io_cfg *io_cfg;
|
||||
uint32_t num_buf;
|
||||
uint32_t num_plane;
|
||||
uint64_t io_addr[CAM_PACKET_MAX_PLANES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_cmd_config_args : Args for prepare HW update
|
||||
*
|
||||
* @hw_device : Pointer to HW device
|
||||
* @input_buf : List of input buffers
|
||||
* @output_buf : List of output buffers
|
||||
* @cmd_buf_addr : Pointer to available KMD buffer
|
||||
* @size : Available KMD buffer size
|
||||
* @config_buf_size : Size used to prepare update
|
||||
*/
|
||||
struct cam_lrme_hw_cmd_config_args {
|
||||
struct cam_lrme_device *hw_device;
|
||||
struct cam_lrme_hw_io_buffer input_buf[CAM_LRME_MAX_IO_BUFFER];
|
||||
struct cam_lrme_hw_io_buffer output_buf[CAM_LRME_MAX_IO_BUFFER];
|
||||
uint32_t *cmd_buf_addr;
|
||||
uint32_t size;
|
||||
uint32_t config_buf_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_flush_args : Args for flush HW
|
||||
*
|
||||
* @ctxt_to_hw_map : Identity of context
|
||||
* @req_to_flush : Pointer to the frame need to flush in
|
||||
* case of single frame flush
|
||||
* @flush_type : Flush type
|
||||
*/
|
||||
struct cam_lrme_hw_flush_args {
|
||||
void *ctxt_to_hw_map;
|
||||
struct cam_lrme_frame_request *req_to_flush;
|
||||
uint32_t flush_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_reset_args : Args for reset HW
|
||||
*
|
||||
* @reset_type : Enum cam_lrme_hw_reset_type
|
||||
*/
|
||||
struct cam_lrme_hw_reset_args {
|
||||
uint32_t reset_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_cb_args : HW manager callback args
|
||||
*
|
||||
* @cb_type : Callback event type
|
||||
* @frame_req : Pointer to the frame associated with the cb
|
||||
*/
|
||||
struct cam_lrme_hw_cb_args {
|
||||
uint32_t cb_type;
|
||||
struct cam_lrme_frame_request *frame_req;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_cmd_set_cb : Args for set callback function
|
||||
*
|
||||
* @cam_lrme_hw_mgr_cb : Callback function pointer
|
||||
* @data : Data sent along with callback function
|
||||
*/
|
||||
struct cam_lrme_hw_cmd_set_cb {
|
||||
int (*cam_lrme_hw_mgr_cb)(void *data,
|
||||
struct cam_lrme_hw_cb_args *args);
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_submit_args : Args for submit request
|
||||
*
|
||||
* @hw_update_entries : List of hw update entries used to program registers
|
||||
* @num_hw_update_entries : Number of hw update entries
|
||||
* @frame_req : Pointer to the frame request
|
||||
*/
|
||||
struct cam_lrme_hw_submit_args {
|
||||
struct cam_hw_update_entry *hw_update_entries;
|
||||
uint32_t num_hw_update_entries;
|
||||
struct cam_lrme_frame_request *frame_req;
|
||||
};
|
||||
|
||||
#endif /* _CAM_LRME_HW_INTF_H_ */
|
186
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h
Normal file
186
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_reg.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_REG_H_
|
||||
#define _CAM_LRME_HW_REG_H_
|
||||
|
||||
#include "cam_lrme_hw_core.h"
|
||||
|
||||
static struct cam_lrme_hw_info cam_lrme10_hw_info = {
|
||||
.clc_reg = {
|
||||
.clc_hw_version = 0x00000000,
|
||||
.clc_hw_status = 0x00000004,
|
||||
.clc_hw_status_dbg = 0x00000008,
|
||||
.clc_module_cfg = 0x00000060,
|
||||
.clc_moduleformat = 0x000000A8,
|
||||
.clc_rangestep = 0x00000068,
|
||||
.clc_offset = 0x0000006C,
|
||||
.clc_maxallowedsad = 0x00000070,
|
||||
.clc_minallowedtarmad = 0x00000074,
|
||||
.clc_meaningfulsaddiff = 0x00000078,
|
||||
.clc_minsaddiffdenom = 0x0000007C,
|
||||
.clc_robustnessmeasuredistmap_0 = 0x00000080,
|
||||
.clc_robustnessmeasuredistmap_1 = 0x00000084,
|
||||
.clc_robustnessmeasuredistmap_2 = 0x00000088,
|
||||
.clc_robustnessmeasuredistmap_3 = 0x0000008C,
|
||||
.clc_robustnessmeasuredistmap_4 = 0x00000090,
|
||||
.clc_robustnessmeasuredistmap_5 = 0x00000094,
|
||||
.clc_robustnessmeasuredistmap_6 = 0x00000098,
|
||||
.clc_robustnessmeasuredistmap_7 = 0x0000009C,
|
||||
.clc_ds_crop_horizontal = 0x000000A0,
|
||||
.clc_ds_crop_vertical = 0x000000A4,
|
||||
.clc_tar_pd_unpacker = 0x000000AC,
|
||||
.clc_ref_pd_unpacker = 0x000000B0,
|
||||
.clc_sw_override = 0x000000B4,
|
||||
.clc_tar_height = 0x000000B8,
|
||||
.clc_ref_height = 0x000000BC,
|
||||
.clc_test_bus_ctrl = 0x000001F8,
|
||||
.clc_spare = 0x000001FC,
|
||||
},
|
||||
.bus_rd_reg = {
|
||||
.common_reg = {
|
||||
.hw_version = 0x00000200,
|
||||
.hw_capability = 0x00000204,
|
||||
.sw_reset = 0x00000208,
|
||||
.cgc_override = 0x0000020C,
|
||||
.irq_mask = 0x00000210,
|
||||
.irq_clear = 0x00000214,
|
||||
.irq_cmd = 0x00000218,
|
||||
.irq_status = 0x0000021C,
|
||||
.cmd = 0x00000220,
|
||||
.irq_set = 0x00000224,
|
||||
.misr_reset = 0x0000022C,
|
||||
.security_cfg = 0x00000230,
|
||||
.pwr_iso_cfg = 0x00000234,
|
||||
.pwr_iso_seed = 0x00000238,
|
||||
.test_bus_ctrl = 0x00000248,
|
||||
.spare = 0x0000024C,
|
||||
},
|
||||
.bus_client_reg = {
|
||||
/* bus client 0 */
|
||||
{
|
||||
.core_cfg = 0x00000250,
|
||||
.ccif_meta_data = 0x00000254,
|
||||
.addr_image = 0x00000258,
|
||||
.rd_buffer_size = 0x0000025C,
|
||||
.rd_stride = 0x00000260,
|
||||
.unpack_cfg_0 = 0x00000264,
|
||||
.latency_buff_allocation = 0x00000278,
|
||||
.burst_limit_cfg = 0x00000280,
|
||||
.misr_cfg_0 = 0x00000284,
|
||||
.misr_cfg_1 = 0x00000288,
|
||||
.misr_rd_val = 0x0000028C,
|
||||
.debug_status_cfg = 0x00000290,
|
||||
.debug_status_0 = 0x00000294,
|
||||
.debug_status_1 = 0x00000298,
|
||||
},
|
||||
/* bus client 1 */
|
||||
{
|
||||
.core_cfg = 0x000002F0,
|
||||
.ccif_meta_data = 0x000002F4,
|
||||
.addr_image = 0x000002F8,
|
||||
.rd_buffer_size = 0x000002FC,
|
||||
.rd_stride = 0x00000300,
|
||||
.unpack_cfg_0 = 0x00000304,
|
||||
.latency_buff_allocation = 0x00000318,
|
||||
.burst_limit_cfg = 0x00000320,
|
||||
.misr_cfg_0 = 0x00000324,
|
||||
.misr_cfg_1 = 0x00000328,
|
||||
.misr_rd_val = 0x0000032C,
|
||||
.debug_status_cfg = 0x00000330,
|
||||
.debug_status_0 = 0x00000334,
|
||||
.debug_status_1 = 0x00000338,
|
||||
},
|
||||
},
|
||||
},
|
||||
.bus_wr_reg = {
|
||||
.common_reg = {
|
||||
.hw_version = 0x00000500,
|
||||
.hw_capability = 0x00000504,
|
||||
.sw_reset = 0x00000508,
|
||||
.cgc_override = 0x0000050C,
|
||||
.misr_reset = 0x000005C8,
|
||||
.pwr_iso_cfg = 0x000005CC,
|
||||
.test_bus_ctrl = 0x0000061C,
|
||||
.composite_mask_0 = 0x00000510,
|
||||
.irq_mask_0 = 0x00000544,
|
||||
.irq_mask_1 = 0x00000548,
|
||||
.irq_clear_0 = 0x00000550,
|
||||
.irq_clear_1 = 0x00000554,
|
||||
.irq_status_0 = 0x0000055C,
|
||||
.irq_status_1 = 0x00000560,
|
||||
.irq_cmd = 0x00000568,
|
||||
.irq_set_0 = 0x000005BC,
|
||||
.irq_set_1 = 0x000005C0,
|
||||
.addr_fifo_status = 0x000005A8,
|
||||
.frame_header_cfg0 = 0x000005AC,
|
||||
.frame_header_cfg1 = 0x000005B0,
|
||||
.spare = 0x00000620,
|
||||
},
|
||||
.bus_client_reg = {
|
||||
/* bus client 0 */
|
||||
{
|
||||
.status_0 = 0x00000700,
|
||||
.status_1 = 0x00000704,
|
||||
.cfg = 0x00000708,
|
||||
.addr_frame_header = 0x0000070C,
|
||||
.frame_header_cfg = 0x00000710,
|
||||
.addr_image = 0x00000714,
|
||||
.addr_image_offset = 0x00000718,
|
||||
.buffer_width_cfg = 0x0000071C,
|
||||
.buffer_height_cfg = 0x00000720,
|
||||
.packer_cfg = 0x00000724,
|
||||
.wr_stride = 0x00000728,
|
||||
.irq_subsample_cfg_period = 0x00000748,
|
||||
.irq_subsample_cfg_pattern = 0x0000074C,
|
||||
.burst_limit_cfg = 0x0000075C,
|
||||
.misr_cfg = 0x00000760,
|
||||
.misr_rd_word_sel = 0x00000764,
|
||||
.misr_val = 0x00000768,
|
||||
.debug_status_cfg = 0x0000076C,
|
||||
.debug_status_0 = 0x00000770,
|
||||
.debug_status_1 = 0x00000774,
|
||||
},
|
||||
/* bus client 1 */
|
||||
{
|
||||
.status_0 = 0x00000800,
|
||||
.status_1 = 0x00000804,
|
||||
.cfg = 0x00000808,
|
||||
.addr_frame_header = 0x0000080C,
|
||||
.frame_header_cfg = 0x00000810,
|
||||
.addr_image = 0x00000814,
|
||||
.addr_image_offset = 0x00000818,
|
||||
.buffer_width_cfg = 0x0000081C,
|
||||
.buffer_height_cfg = 0x00000820,
|
||||
.packer_cfg = 0x00000824,
|
||||
.wr_stride = 0x00000828,
|
||||
.irq_subsample_cfg_period = 0x00000848,
|
||||
.irq_subsample_cfg_pattern = 0x0000084C,
|
||||
.burst_limit_cfg = 0x0000085C,
|
||||
.misr_cfg = 0x00000860,
|
||||
.misr_rd_word_sel = 0x00000864,
|
||||
.misr_val = 0x00000868,
|
||||
.debug_status_cfg = 0x0000086C,
|
||||
.debug_status_0 = 0x00000870,
|
||||
.debug_status_1 = 0x00000874,
|
||||
},
|
||||
},
|
||||
},
|
||||
.titan_reg = {
|
||||
.top_hw_version = 0x00000900,
|
||||
.top_titan_version = 0x00000904,
|
||||
.top_rst_cmd = 0x00000908,
|
||||
.top_core_clk_cfg = 0x00000920,
|
||||
.top_irq_status = 0x0000090C,
|
||||
.top_irq_mask = 0x00000910,
|
||||
.top_irq_clear = 0x00000914,
|
||||
.top_irq_set = 0x00000918,
|
||||
.top_irq_cmd = 0x0000091C,
|
||||
.top_violation_status = 0x00000924,
|
||||
.top_spare = 0x000009FC,
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* _CAM_LRME_HW_REG_H_ */
|
161
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c
Normal file
161
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.c
Normal file
@@ -0,0 +1,161 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cam_lrme_hw_core.h"
|
||||
#include "cam_lrme_hw_soc.h"
|
||||
|
||||
|
||||
int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info;
|
||||
struct cam_lrme_soc_private *soc_private =
|
||||
(struct cam_lrme_soc_private *)soc_info->soc_private;
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote = {0};
|
||||
int rc = 0;
|
||||
|
||||
ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
axi_vote.num_paths = 2;
|
||||
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
|
||||
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ;
|
||||
axi_vote.axi_path[0].camnoc_bw = 7200000;
|
||||
axi_vote.axi_path[0].mnoc_ab_bw = 7200000;
|
||||
axi_vote.axi_path[0].mnoc_ib_bw = 7200000;
|
||||
axi_vote.axi_path[1].path_data_type = CAM_AXI_PATH_DATA_ALL;
|
||||
axi_vote.axi_path[1].transac_type = CAM_AXI_TRANSACTION_WRITE;
|
||||
axi_vote.axi_path[1].camnoc_bw = 7200000;
|
||||
axi_vote.axi_path[1].mnoc_ab_bw = 7200000;
|
||||
axi_vote.axi_path[1].mnoc_ib_bw = 7200000;
|
||||
|
||||
rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to start cpas, rc %d", rc);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true, CAM_SVS_VOTE,
|
||||
true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME,
|
||||
"Failed to enable platform resource, rc %d", rc);
|
||||
goto stop_cpas;
|
||||
}
|
||||
|
||||
cam_lrme_set_irq(lrme_hw, CAM_LRME_IRQ_ENABLE);
|
||||
|
||||
return rc;
|
||||
|
||||
stop_cpas:
|
||||
if (cam_cpas_stop(soc_private->cpas_handle))
|
||||
CAM_ERR(CAM_LRME, "Failed to stop cpas");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_lrme_soc_disable_resources(struct cam_hw_info *lrme_hw)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info;
|
||||
struct cam_lrme_soc_private *soc_private;
|
||||
int rc = 0;
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
cam_lrme_set_irq(lrme_hw, CAM_LRME_IRQ_DISABLE);
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to disable platform resource");
|
||||
return rc;
|
||||
}
|
||||
rc = cam_cpas_stop(soc_private->cpas_handle);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Failed to stop cpas");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_lrme_soc_init_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t irq_handler, void *private_data)
|
||||
{
|
||||
struct cam_lrme_soc_private *soc_private;
|
||||
struct cam_cpas_register_params cpas_register_param;
|
||||
int rc;
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed in get_dt_properties, rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_request_platform_resource(soc_info, irq_handler,
|
||||
private_data);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed in request_platform_resource rc=%d",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
soc_private = kzalloc(sizeof(struct cam_lrme_soc_private), GFP_KERNEL);
|
||||
if (!soc_private) {
|
||||
rc = -ENOMEM;
|
||||
goto release_res;
|
||||
}
|
||||
soc_info->soc_private = soc_private;
|
||||
|
||||
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
|
||||
strlcpy(cpas_register_param.identifier,
|
||||
"lrmecpas", CAM_HW_IDENTIFIER_LENGTH);
|
||||
cpas_register_param.cell_index = soc_info->index;
|
||||
cpas_register_param.dev = &soc_info->pdev->dev;
|
||||
cpas_register_param.userdata = private_data;
|
||||
cpas_register_param.cam_cpas_client_cb = NULL;
|
||||
|
||||
rc = cam_cpas_register_client(&cpas_register_param);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "CPAS registration failed");
|
||||
goto free_soc_private;
|
||||
}
|
||||
soc_private->cpas_handle = cpas_register_param.client_handle;
|
||||
CAM_DBG(CAM_LRME, "CPAS handle=%d", soc_private->cpas_handle);
|
||||
|
||||
return rc;
|
||||
|
||||
free_soc_private:
|
||||
kfree(soc_info->soc_private);
|
||||
soc_info->soc_private = NULL;
|
||||
release_res:
|
||||
cam_soc_util_release_platform_resource(soc_info);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_lrme_soc_deinit_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
struct cam_lrme_soc_private *soc_private =
|
||||
(struct cam_lrme_soc_private *)soc_info->soc_private;
|
||||
int rc;
|
||||
|
||||
rc = cam_cpas_unregister_client(soc_private->cpas_handle);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Unregister cpas failed, handle=%d, rc=%d",
|
||||
soc_private->cpas_handle, rc);
|
||||
|
||||
rc = cam_soc_util_release_platform_resource(soc_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "release platform failed, rc=%d", rc);
|
||||
|
||||
kfree(soc_info->soc_private);
|
||||
soc_info->soc_private = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
21
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h
Normal file
21
drivers/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_soc.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_SOC_H_
|
||||
#define _CAM_LRME_HW_SOC_H_
|
||||
|
||||
#include "cam_soc_util.h"
|
||||
|
||||
struct cam_lrme_soc_private {
|
||||
uint32_t cpas_handle;
|
||||
};
|
||||
|
||||
int cam_lrme_soc_enable_resources(struct cam_hw_info *lrme_hw);
|
||||
int cam_lrme_soc_disable_resources(struct cam_hw_info *lrme_hw);
|
||||
int cam_lrme_soc_init_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t irq_handler, void *private_data);
|
||||
int cam_lrme_soc_deinit_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
#endif /* _CAM_LRME_HW_SOC_H_ */
|
Verwijs in nieuw issue
Block a user