|
@@ -17,6 +17,7 @@
|
|
#include <media/v4l2-ioctl.h>
|
|
#include <media/v4l2-ioctl.h>
|
|
#include <media/cam_req_mgr.h>
|
|
#include <media/cam_req_mgr.h>
|
|
#include <media/cam_defs.h>
|
|
#include <media/cam_defs.h>
|
|
|
|
+#include <linux/list_sort.h>
|
|
|
|
|
|
#include "cam_req_mgr_dev.h"
|
|
#include "cam_req_mgr_dev.h"
|
|
#include "cam_req_mgr_util.h"
|
|
#include "cam_req_mgr_util.h"
|
|
@@ -32,6 +33,7 @@
|
|
|
|
|
|
static struct cam_req_mgr_device g_dev;
|
|
static struct cam_req_mgr_device g_dev;
|
|
struct kmem_cache *g_cam_req_mgr_timer_cachep;
|
|
struct kmem_cache *g_cam_req_mgr_timer_cachep;
|
|
|
|
+static struct list_head cam_req_mgr_ordered_sd_list;
|
|
|
|
|
|
static struct device_attribute camera_debug_sysfs_attr =
|
|
static struct device_attribute camera_debug_sysfs_attr =
|
|
__ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store);
|
|
__ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store);
|
|
@@ -122,6 +124,7 @@ static int cam_req_mgr_open(struct file *filep)
|
|
spin_unlock_bh(&g_dev.cam_eventq_lock);
|
|
spin_unlock_bh(&g_dev.cam_eventq_lock);
|
|
|
|
|
|
g_dev.open_cnt++;
|
|
g_dev.open_cnt++;
|
|
|
|
+ g_dev.read_active_dev_id_hdls = 0;
|
|
rc = cam_mem_mgr_init();
|
|
rc = cam_mem_mgr_init();
|
|
if (rc) {
|
|
if (rc) {
|
|
g_dev.open_cnt--;
|
|
g_dev.open_cnt--;
|
|
@@ -158,6 +161,7 @@ static unsigned int cam_req_mgr_poll(struct file *f,
|
|
static int cam_req_mgr_close(struct file *filep)
|
|
static int cam_req_mgr_close(struct file *filep)
|
|
{
|
|
{
|
|
struct v4l2_subdev *sd;
|
|
struct v4l2_subdev *sd;
|
|
|
|
+ struct cam_subdev *csd;
|
|
struct v4l2_fh *vfh = filep->private_data;
|
|
struct v4l2_fh *vfh = filep->private_data;
|
|
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
|
|
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
|
|
|
|
|
|
@@ -172,18 +176,23 @@ static int cam_req_mgr_close(struct file *filep)
|
|
}
|
|
}
|
|
|
|
|
|
cam_req_mgr_handle_core_shutdown();
|
|
cam_req_mgr_handle_core_shutdown();
|
|
|
|
+ g_dev.shutdown_state = true;
|
|
|
|
|
|
- list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) {
|
|
|
|
|
|
+ list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) {
|
|
|
|
+ sd = &csd->sd;
|
|
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
|
|
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
|
|
continue;
|
|
continue;
|
|
- if (sd->internal_ops && sd->internal_ops->close) {
|
|
|
|
|
|
+ if (sd->internal_ops) {
|
|
CAM_DBG(CAM_CRM, "Invoke subdev close for device %s",
|
|
CAM_DBG(CAM_CRM, "Invoke subdev close for device %s",
|
|
sd->name);
|
|
sd->name);
|
|
- sd->internal_ops->close(sd, subdev_fh);
|
|
|
|
|
|
+ v4l2_subdev_call(sd, core, ioctl,
|
|
|
|
+ CAM_SD_SHUTDOWN, subdev_fh);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
g_dev.open_cnt--;
|
|
g_dev.open_cnt--;
|
|
|
|
+ g_dev.shutdown_state = false;
|
|
|
|
+ g_dev.read_active_dev_id_hdls = 0;
|
|
v4l2_fh_release(filep);
|
|
v4l2_fh_release(filep);
|
|
|
|
|
|
spin_lock_bh(&g_dev.cam_eventq_lock);
|
|
spin_lock_bh(&g_dev.cam_eventq_lock);
|
|
@@ -659,6 +668,51 @@ void cam_subdev_notify_message(u32 subdev_type,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(cam_subdev_notify_message);
|
|
EXPORT_SYMBOL(cam_subdev_notify_message);
|
|
|
|
|
|
|
|
+
|
|
|
|
+static int cam_req_mgr_ordered_list_cmp(void *priv,
|
|
|
|
+ struct list_head *head_1, struct list_head *head_2)
|
|
|
|
+{
|
|
|
|
+ struct cam_subdev *entry_1 =
|
|
|
|
+ list_entry(head_1, struct cam_subdev, list);
|
|
|
|
+ struct cam_subdev *entry_2 =
|
|
|
|
+ list_entry(head_2, struct cam_subdev, list);
|
|
|
|
+ int ret = -1;
|
|
|
|
+
|
|
|
|
+ if (entry_1->close_seq_prior > entry_2->close_seq_prior)
|
|
|
|
+ return 1;
|
|
|
|
+ else if (entry_1->close_seq_prior < entry_2->close_seq_prior)
|
|
|
|
+ return ret;
|
|
|
|
+ else
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool cam_req_mgr_is_open(uint64_t dev_id)
|
|
|
|
+{
|
|
|
|
+ bool crm_status;
|
|
|
|
+ bool dev_id_status;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&g_dev.cam_lock);
|
|
|
|
+ crm_status = g_dev.open_cnt ? true : false;
|
|
|
|
+
|
|
|
|
+ if (!g_dev.read_active_dev_id_hdls) {
|
|
|
|
+ g_dev.active_dev_id_hdls = cam_get_dev_handle_status();
|
|
|
|
+ g_dev.read_active_dev_id_hdls++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false;
|
|
|
|
+ crm_status &= dev_id_status;
|
|
|
|
+ mutex_unlock(&g_dev.cam_lock);
|
|
|
|
+
|
|
|
|
+ return crm_status;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(cam_req_mgr_is_open);
|
|
|
|
+
|
|
|
|
+bool cam_req_mgr_is_shutdown(void)
|
|
|
|
+{
|
|
|
|
+ return g_dev.shutdown_state;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(cam_req_mgr_is_shutdown);
|
|
|
|
+
|
|
int cam_register_subdev(struct cam_subdev *csd)
|
|
int cam_register_subdev(struct cam_subdev *csd)
|
|
{
|
|
{
|
|
struct v4l2_subdev *sd;
|
|
struct v4l2_subdev *sd;
|
|
@@ -687,6 +741,10 @@ int cam_register_subdev(struct cam_subdev *csd)
|
|
sd->entity.pads = NULL;
|
|
sd->entity.pads = NULL;
|
|
sd->entity.function = csd->ent_function;
|
|
sd->entity.function = csd->ent_function;
|
|
|
|
|
|
|
|
+ list_add(&csd->list, &cam_req_mgr_ordered_sd_list);
|
|
|
|
+ list_sort(NULL, &cam_req_mgr_ordered_sd_list,
|
|
|
|
+ cam_req_mgr_ordered_list_cmp);
|
|
|
|
+
|
|
rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd);
|
|
rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd);
|
|
if (rc) {
|
|
if (rc) {
|
|
CAM_ERR(CAM_CRM, "register subdev failed");
|
|
CAM_ERR(CAM_CRM, "register subdev failed");
|
|
@@ -747,6 +805,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev)
|
|
goto video_setup_fail;
|
|
goto video_setup_fail;
|
|
|
|
|
|
g_dev.open_cnt = 0;
|
|
g_dev.open_cnt = 0;
|
|
|
|
+ g_dev.shutdown_state = false;
|
|
mutex_init(&g_dev.cam_lock);
|
|
mutex_init(&g_dev.cam_lock);
|
|
spin_lock_init(&g_dev.cam_eventq_lock);
|
|
spin_lock_init(&g_dev.cam_eventq_lock);
|
|
mutex_init(&g_dev.dev_lock);
|
|
mutex_init(&g_dev.dev_lock);
|
|
@@ -764,6 +823,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev)
|
|
}
|
|
}
|
|
|
|
|
|
g_dev.state = true;
|
|
g_dev.state = true;
|
|
|
|
+ INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list);
|
|
|
|
|
|
if (g_cam_req_mgr_timer_cachep == NULL) {
|
|
if (g_cam_req_mgr_timer_cachep == NULL) {
|
|
g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer",
|
|
g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer",
|