Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87534398 authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add Face Detection driver" into dev/msm-4.9-camx

parents c1f7106a 5719f21e
Loading
Loading
Loading
Loading
+149 −0
Original line number Diff line number Diff line
* Qualcomm Technologies, Inc. MSM Camera FD

The MSM camera Face Detection device provides dependency definitions
for enabling Camera FD HW. MSM camera FD is implemented in multiple
device nodes. The root FD device node has properties defined to hint
the driver about the FD HW nodes available during the probe sequence.
Each node has multiple properties defined for interrupts, clocks and
regulators.

=======================
Required Node Structure
=======================
FD root interface node takes care of the handling Face Detection high level
driver handling and controls underlying FD hardware present.

- compatible
  Usage: required
  Value type: <string>
  Definition: Should be "qcom,cam-fd".

- compat-hw-name
  Usage: required
  Value type: <string>
  Definition: Should be "qcom,fd".

- num-fd
  Usage: required
  Value type: <u32>
  Definition: Number of supported FD HW blocks.

Example:
	qcom,cam-fd {
		compatible = "qcom,cam-fd";
		compat-hw-name = "qcom,fd";
		num-fd = <1>;
	};

=======================
Required Node Structure
=======================
FD Node provides interface for Face Detection hardware driver
about the device register map, interrupt map, clocks, regulators.

- cell-index
  Usage: required
  Value type: <u32>
  Definition: Node instance number.

- compatible
  Usage: required
  Value type: <string>
  Definition: Should be "qcom,fd41".

- reg-names
  Usage: optional
  Value type: <string>
  Definition: Name of the register resources.

- reg
  Usage: optional
  Value type: <u32>
  Definition: Register values.

- reg-cam-base
  Usage: optional
  Value type: <u32>
  Definition: Offset of the register space compared to
              to Camera base register space.

- interrupt-names
  Usage: optional
  Value type: <string>
  Definition: Name of the interrupt.

- interrupts
  Usage: optional
  Value type: <u32>
  Definition: Interrupt line associated with FD HW.

- regulator-names
  Usage: required
  Value type: <string>
  Definition: Name of the regulator resources for FD HW.

- camss-vdd-supply
  Usage: required
  Value type: <phandle>
  Definition: Regulator reference corresponding to the names listed
              in "regulator-names".

- clock-names
  Usage: required
  Value type: <string>
  Definition: List of clock names required for FD HW.

- clocks
  Usage: required
  Value type: <phandle>
  Definition: List of clocks required for FD HW.

- clock-rates
  Usage: required
  Value type: <u32>
  Definition: List of clocks rates.

- src-clock-name
  Usage: required
  Value type: <string>
  Definition: Source clock name.

- clock-cntl-level
  Usage: required
  Value type: <string>
  Definition: List of strings corresponds clock-rates levels.
  Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo.

Examples:
	cam_fd: qcom,fd@ac5a000 {
		cell-index = <0>;
		compatible = "qcom,fd41";
		reg-names = "fd_core", "fd_wrapper";
		reg = <0xac5a000 0x1000>,
			<0xac5b000 0x400>;
		reg-cam-base = <0x5a000 0x5b000>;
		interrupt-names = "fd";
		interrupts = <0 462 0>;
		regulator-names = "camss-vdd";
		camss-vdd-supply = <&titan_top_gdsc>;
		clock-names = "gcc_ahb_clk",
			"gcc_axi_clk",
			"soc_ahb_clk",
			"cpas_ahb_clk",
			"camnoc_axi_clk",
			"fd_core_clk_src",
			"fd_core_clk",
			"fd_core_uar_clk";
		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
			<&clock_gcc GCC_CAMERA_AXI_CLK>,
			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
			<&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
			<&clock_camcc CAM_CC_FD_CORE_CLK_SRC>,
			<&clock_camcc CAM_CC_FD_CORE_CLK>,
			<&clock_camcc CAM_CC_FD_CORE_UAR_CLK>;
		src-clock-name = "fd_core_clk_src";
		clock-cntl-level = "svs";
		clock-rates = <0 0 0 0 0 400000000 0 0>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -9,3 +9,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_module/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd/
+14 −0
Original line number Diff line number Diff line
ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu
ccflags-y += -Idrivers/media/platform/msm/camera/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw
ccflags-y += -Idrivers/media/platform/msm/camera
ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include

obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw_mgr/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_dev.o cam_fd_context.o
+236 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/kernel.h>

#include "cam_debug_util.h"
#include "cam_fd_context.h"

/* Functions in Available state */
static int __cam_fd_ctx_acquire_dev_in_available(struct cam_context *ctx,
	struct cam_acquire_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_acquire_dev_to_hw(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Acquire dev, rc=%d", rc);
		return rc;
	}

	ctx->state = CAM_CTX_ACQUIRED;

	return rc;
}

/* Functions in Acquired state */
static int __cam_fd_ctx_release_dev_in_acquired(struct cam_context *ctx,
	struct cam_release_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_release_dev_to_hw(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Release dev, rc=%d", rc);
		return rc;
	}

	ctx->state = CAM_CTX_AVAILABLE;

	return rc;
}

static int __cam_fd_ctx_config_dev_in_acquired(struct cam_context *ctx,
	struct cam_config_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_prepare_dev_to_hw(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Prepare dev, rc=%d", rc);
		return rc;
	}

	return rc;
}

static int __cam_fd_ctx_start_dev_in_acquired(struct cam_context *ctx,
	struct cam_start_stop_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_start_dev_to_hw(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Start dev, rc=%d", rc);
		return rc;
	}

	ctx->state = CAM_CTX_ACTIVATED;

	return rc;
}

/* Functions in Activated state */
static int __cam_fd_ctx_stop_dev_in_activated(struct cam_context *ctx,
	struct cam_start_stop_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_stop_dev_to_hw(ctx);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Stop dev, rc=%d", rc);
		return rc;
	}

	ctx->state = CAM_CTX_ACQUIRED;

	return rc;
}

static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx,
	struct cam_release_dev_cmd *cmd)
{
	int rc;

	rc = __cam_fd_ctx_stop_dev_in_activated(ctx, NULL);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Stop dev, rc=%d", rc);
		return rc;
	}

	rc = __cam_fd_ctx_release_dev_in_acquired(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Release dev, rc=%d", rc);
		return rc;
	}

	return rc;
}

static int __cam_fd_ctx_config_dev_in_activated(
	struct cam_context *ctx, struct cam_config_dev_cmd *cmd)
{
	int rc;

	rc = cam_context_prepare_dev_to_hw(ctx, cmd);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in Prepare dev, rc=%d", rc);
		return rc;
	}

	return rc;
}

static int __cam_fd_ctx_handle_irq_in_activated(void *context,
	uint32_t evt_id, void *evt_data)
{
	int rc;

	rc = cam_context_buf_done_from_hw(context, evt_data, evt_id);
	if (rc) {
		CAM_ERR(CAM_FD, "Failed in buf done, rc=%d", rc);
		return rc;
	}

	return rc;
}

/* top state machine */
static struct cam_ctx_ops
	cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = {
	/* Uninit */
	{
		.ioctl_ops = {},
		.crm_ops = {},
		.irq_ops = NULL,
	},
	/* Available */
	{
		.ioctl_ops = {
			.acquire_dev = __cam_fd_ctx_acquire_dev_in_available,
		},
		.crm_ops = {},
		.irq_ops = NULL,
	},
	/* Acquired */
	{
		.ioctl_ops = {
			.release_dev = __cam_fd_ctx_release_dev_in_acquired,
			.config_dev = __cam_fd_ctx_config_dev_in_acquired,
			.start_dev = __cam_fd_ctx_start_dev_in_acquired,
		},
		.crm_ops = {},
		.irq_ops = NULL,
	},
	/* Ready */
	{
		.ioctl_ops = { },
		.crm_ops = {},
		.irq_ops = NULL,
	},
	/* Activated */
	{
		.ioctl_ops = {
			.stop_dev = __cam_fd_ctx_stop_dev_in_activated,
			.release_dev = __cam_fd_ctx_release_dev_in_activated,
			.config_dev = __cam_fd_ctx_config_dev_in_activated,
		},
		.crm_ops = {},
		.irq_ops = __cam_fd_ctx_handle_irq_in_activated,
	},
};


int cam_fd_context_init(struct cam_fd_context *fd_ctx,
	struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf)
{
	int rc;

	if (!base_ctx || !fd_ctx) {
		CAM_ERR(CAM_FD, "Invalid Context %pK %pK", base_ctx, fd_ctx);
		return -EINVAL;
	}

	memset(fd_ctx, 0, sizeof(*fd_ctx));

	rc = cam_context_init(base_ctx, NULL, hw_intf, fd_ctx->req_base,
		CAM_CTX_REQ_MAX);
	if (rc) {
		CAM_ERR(CAM_FD, "Camera Context Base init failed, rc=%d", rc);
		return rc;
	}

	fd_ctx->base = base_ctx;
	base_ctx->ctx_priv = fd_ctx;
	base_ctx->state_machine = cam_fd_ctx_state_machine;

	return rc;
}

int cam_fd_context_deinit(struct cam_fd_context *fd_ctx)
{
	int rc = 0;

	if (!fd_ctx || !fd_ctx->base) {
		CAM_ERR(CAM_FD, "Invalid inputs %pK", fd_ctx);
		return -EINVAL;
	}

	rc = cam_context_deinit(fd_ctx->base);
	if (rc)
		CAM_ERR(CAM_FD, "Error in base deinit, rc=%d", rc);

	memset(fd_ctx, 0, sizeof(*fd_ctx));

	return rc;
}
+36 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef _CAM_FD_CONTEXT_H_
#define _CAM_FD_CONTEXT_H_

#include "cam_context.h"
#include "cam_context_utils.h"
#include "cam_hw_mgr_intf.h"
#include "cam_req_mgr_interface.h"

/**
 * struct cam_fd_context - Face Detection context information
 *
 * @base     : Base context pointer for this FD context
 * @req_base : List of base requests for this FD context
 */
struct cam_fd_context {
	struct cam_context       *base;
	struct cam_ctx_request    req_base[CAM_CTX_REQ_MAX];
};

int cam_fd_context_init(struct cam_fd_context *fd_ctx,
	struct cam_context *base_ctx, struct cam_hw_mgr_intf *hw_intf);
int cam_fd_context_deinit(struct cam_fd_context *ctx);

#endif /* _CAM_FD_CONTEXT_H_ */
Loading