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:
Jigarkumar Zala
2019-05-24 17:56:58 -07:00
bovenliggende 9be583aa80
commit 05349feaa2
356 gewijzigde bestanden met toevoegingen van 134959 en 10 verwijderingen

16
drivers/cam_lrme/Makefile Normal file
Bestand weergeven

@@ -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

Bestand weergeven

@@ -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;
}

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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");

Bestand weergeven

@@ -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

Diff onderdrukt omdat het te groot bestand Laad Diff

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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

Diff onderdrukt omdat het te groot bestand Laad Diff

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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");

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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_ */

Bestand weergeven

@@ -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;
}

Bestand weergeven

@@ -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_ */