Merge "msm: camera: sensor: Add tpg driver support" into camera-kernel.lnx.5.0
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
9e5e021304
5
Kbuild
5
Kbuild
@@ -191,6 +191,11 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
|
||||
drivers/cam_sensor_module/cam_cci/cam_cci_dev.o \
|
||||
drivers/cam_sensor_module/cam_cci/cam_cci_core.o \
|
||||
drivers/cam_sensor_module/cam_cci/cam_cci_soc.o \
|
||||
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.o \
|
||||
drivers/cam_sensor_module/cam_tpg/cam_tpg_core.o \
|
||||
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.o \
|
||||
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_0/tpg_hw_v_1_0.o \
|
||||
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3.o \
|
||||
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.o \
|
||||
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.o \
|
||||
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.o \
|
||||
|
@@ -186,6 +186,7 @@ enum cam_req_mgr_device_error {
|
||||
* @EXTERNAL_1 : third party device
|
||||
* @EXTERNAL_2 : third party device
|
||||
* @EXTERNAL_3 : third party device
|
||||
* @TPG : Test Pattern Generator
|
||||
* @MAX : invalid device id
|
||||
*/
|
||||
enum cam_req_mgr_device_id {
|
||||
@@ -198,6 +199,7 @@ enum cam_req_mgr_device_id {
|
||||
CAM_REQ_MGR_DEVICE_EXTERNAL_1,
|
||||
CAM_REQ_MGR_DEVICE_EXTERNAL_2,
|
||||
CAM_REQ_MGR_DEVICE_EXTERNAL_3,
|
||||
CAM_REQ_MGR_DEVICE_TPG,
|
||||
CAM_REQ_MGR_DEVICE_ID_MAX,
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_SENSOR_CMN_HEADER_
|
||||
@@ -27,6 +27,7 @@
|
||||
#define CAM_FLASH_NAME "cam-flash"
|
||||
#define CAM_EEPROM_NAME "cam-eeprom"
|
||||
#define CAM_OIS_NAME "cam-ois"
|
||||
#define CAM_TPG_NAME "cam-tpg"
|
||||
|
||||
#define MAX_SYSTEM_PIPELINE_DELAY 2
|
||||
|
||||
|
748
drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c
Normal file
748
drivers/cam_sensor_module/cam_tpg/cam_tpg_core.c
Normal file
@@ -0,0 +1,748 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cam_tpg_core.h"
|
||||
#include "cam_packet_util.h"
|
||||
#include <cam_mem_mgr.h>
|
||||
#include "tpg_hw/tpg_hw.h"
|
||||
|
||||
int cam_tpg_shutdown(struct cam_tpg_device *tpg_dev)
|
||||
{
|
||||
if (tpg_dev != NULL) {
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] shutdown cleanup.",
|
||||
tpg_dev->soc_info.index);
|
||||
tpg_hw_reset(&tpg_dev->tpg_hw);
|
||||
tpg_dev->state = CAM_TPG_STATE_INIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_tpg_publish_dev_info(
|
||||
struct cam_req_mgr_device_info *info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tpg_device *tpg_dev = NULL;
|
||||
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
tpg_dev = (struct cam_tpg_device *)
|
||||
cam_get_device_priv(info->dev_hdl);
|
||||
|
||||
if (!tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "Device data is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->dev_id = CAM_REQ_MGR_DEVICE_TPG;
|
||||
strlcpy(info->name, CAM_TPG_NAME, sizeof(info->name));
|
||||
/* Hard code for now */
|
||||
info->p_delay = 2;
|
||||
info->trigger = CAM_TRIGGER_POINT_SOF;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tpg_setup_link(
|
||||
struct cam_req_mgr_core_dev_link_setup *link)
|
||||
{
|
||||
struct cam_tpg_device *tpg_dev = NULL;
|
||||
|
||||
if (!link)
|
||||
return -EINVAL;
|
||||
|
||||
tpg_dev = (struct cam_tpg_device *)
|
||||
cam_get_device_priv(link->dev_hdl);
|
||||
if (!tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "Device data is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&tpg_dev->mutex);
|
||||
if (link->link_enable) {
|
||||
tpg_dev->crm_intf.link_hdl = link->link_hdl;
|
||||
tpg_dev->crm_intf.crm_cb = link->crm_cb;
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] CRM enable link done", tpg_dev->soc_info.index);
|
||||
} else {
|
||||
tpg_dev->crm_intf.link_hdl = -1;
|
||||
tpg_dev->crm_intf.crm_cb = NULL;
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] CRM disable link done", tpg_dev->soc_info.index);
|
||||
}
|
||||
mutex_unlock(&tpg_dev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_notify_frame_skip(
|
||||
struct cam_req_mgr_apply_request *apply)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "Got Skip frame from crm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_apply_req(
|
||||
struct cam_req_mgr_apply_request *apply)
|
||||
{
|
||||
if (!apply) {
|
||||
CAM_ERR(CAM_TPG, "invalid parameters");
|
||||
return -EINVAL;
|
||||
}
|
||||
CAM_DBG(CAM_TPG, "Got Apply request from crm %lld", apply->request_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_flush_req(
|
||||
struct cam_req_mgr_flush_request *flush)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "Got Flush request from crm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_process_crm_evt(
|
||||
struct cam_req_mgr_link_evt_data *event)
|
||||
{
|
||||
|
||||
struct cam_tpg_device *tpg_dev = NULL;
|
||||
if (!event) {
|
||||
CAM_ERR(CAM_TPG, "Invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_dev = cam_get_device_priv(event->dev_hdl);
|
||||
if (!tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "Invalid dev_hdl");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch(event->evt_type) {
|
||||
case CAM_REQ_MGR_LINK_EVT_SOF_FREEZE:
|
||||
tpg_hw_dump_status(&tpg_dev->tpg_hw);
|
||||
break;
|
||||
default:
|
||||
CAM_DBG(CAM_TPG, "Got crm event notification: %d", event->evt_type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_dump_req(
|
||||
struct cam_req_mgr_dump_info *dump_info)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "Got dump request from CRM");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_crm_intf_init(
|
||||
struct cam_tpg_device *tpg_dev)
|
||||
{
|
||||
if (tpg_dev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
tpg_dev->crm_intf.device_hdl = -1;
|
||||
tpg_dev->crm_intf.link_hdl = -1;
|
||||
tpg_dev->crm_intf.ops.get_dev_info = cam_tpg_publish_dev_info;
|
||||
tpg_dev->crm_intf.ops.link_setup = cam_tpg_setup_link;
|
||||
tpg_dev->crm_intf.ops.apply_req = cam_tpg_apply_req;
|
||||
tpg_dev->crm_intf.ops.notify_frame_skip =
|
||||
cam_tpg_notify_frame_skip;
|
||||
tpg_dev->crm_intf.ops.flush_req = cam_tpg_flush_req;
|
||||
tpg_dev->crm_intf.ops.process_evt = cam_tpg_process_crm_evt;
|
||||
tpg_dev->crm_intf.ops.dump_req = cam_tpg_dump_req;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_query_cap(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_tpg_query_cap *query)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
|
||||
if (!tpg_dev || !query) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = &tpg_dev->soc_info;
|
||||
CAM_DBG(CAM_TPG, "Handling tpg query capability for %d slot: %d phy:%d",
|
||||
soc_info->index, tpg_dev->slot_id, tpg_dev->phy_id);
|
||||
query->slot_info = soc_info->index;
|
||||
query->csiphy_slot_id = tpg_dev->phy_id;
|
||||
query->version = 0x0;
|
||||
if (tpg_dev->tpg_hw.hw_info) {
|
||||
query->version = tpg_dev->tpg_hw.hw_info->version;
|
||||
} else {
|
||||
CAM_ERR(CAM_TPG, "Invalid hw info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_acquire_dev(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_tpg_acquire_dev *acquire)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_create_dev_hdl crm_intf_params;
|
||||
|
||||
if (!tpg_dev || !acquire) {
|
||||
CAM_ERR(CAM_TPG, "invalid input ");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (tpg_dev->state != CAM_TPG_STATE_INIT) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] not in right state[%d] to acquire",
|
||||
tpg_dev->soc_info.index, tpg_dev->state);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
crm_intf_params.session_hdl = acquire->session_handle;
|
||||
crm_intf_params.ops = &tpg_dev->crm_intf.ops;
|
||||
crm_intf_params.v4l2_sub_dev_flag = 0;
|
||||
crm_intf_params.media_entity_flag = 0;
|
||||
crm_intf_params.priv = tpg_dev;
|
||||
crm_intf_params.dev_id = CAM_TPG;
|
||||
|
||||
acquire->device_handle =
|
||||
cam_create_device_hdl(&crm_intf_params);
|
||||
tpg_dev->crm_intf.device_hdl = acquire->device_handle;
|
||||
tpg_dev->crm_intf.session_hdl = acquire->session_handle;
|
||||
rc = tpg_hw_acquire(&tpg_dev->tpg_hw, (struct tpg_hw_acquire_args *)NULL);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] hw acquire failed", tpg_dev->soc_info.index);
|
||||
cam_destroy_device_hdl(tpg_dev->crm_intf.device_hdl);
|
||||
tpg_dev->crm_intf.device_hdl = -1;
|
||||
tpg_dev->crm_intf.session_hdl = -1;
|
||||
} else {
|
||||
tpg_dev->state = CAM_TPG_STATE_ACQUIRE;
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] Acquire Device done", tpg_dev->soc_info.index);
|
||||
}
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_release_dev(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_release_dev_cmd *release)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!release || !tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (release->dev_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid device handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (release->session_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid session handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tpg_dev->state == CAM_TPG_STATE_INIT) {
|
||||
CAM_WARN(CAM_TPG, "TPG[%d] not in right state[%d] to release",
|
||||
tpg_dev->soc_info.index, tpg_dev->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tpg_dev->state == CAM_TPG_STATE_START) {
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] release from start state",
|
||||
tpg_dev->soc_info.index);
|
||||
rc = tpg_hw_stop(&tpg_dev->tpg_hw);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] unable to stop tpg",
|
||||
tpg_dev->soc_info.index);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rc = tpg_hw_release(&tpg_dev->tpg_hw);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] hw release failed",
|
||||
tpg_dev->soc_info.index);
|
||||
} else {
|
||||
cam_destroy_device_hdl(tpg_dev->crm_intf.device_hdl);
|
||||
tpg_dev->crm_intf.device_hdl = -1;
|
||||
tpg_dev->crm_intf.session_hdl = -1;
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] Release Done.", tpg_dev->soc_info.index);
|
||||
tpg_dev->state = CAM_TPG_STATE_INIT;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_start_dev(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_start_stop_dev_cmd *start)
|
||||
{
|
||||
int rc = 0;
|
||||
if (!start || !tpg_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (start->dev_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid device handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (start->session_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid session handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tpg_dev->state != CAM_TPG_STATE_ACQUIRE) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] not in right state[%d] to start",
|
||||
tpg_dev->soc_info.index, tpg_dev->state);
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = tpg_hw_start(&tpg_dev->tpg_hw);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] START_DEV failed", tpg_dev->soc_info.index);
|
||||
} else {
|
||||
tpg_dev->state = CAM_TPG_STATE_START;
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] START_DEV done.", tpg_dev->soc_info.index);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_stop_dev(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_start_stop_dev_cmd *stop)
|
||||
{
|
||||
int rc = 0;
|
||||
if (!stop || !tpg_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (stop->dev_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid device handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (stop->session_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid session handle for context");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tpg_dev->state != CAM_TPG_STATE_START) {
|
||||
CAM_WARN(CAM_TPG, "TPG[%d] not in right state[%d] to stop",
|
||||
tpg_dev->soc_info.index, tpg_dev->state);
|
||||
}
|
||||
rc = tpg_hw_stop(&tpg_dev->tpg_hw);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] STOP_DEV failed", tpg_dev->soc_info.index);
|
||||
} else {
|
||||
/* Free all allocated streams during stop dev */
|
||||
tpg_hw_free_streams(&tpg_dev->tpg_hw);
|
||||
tpg_dev->state = CAM_TPG_STATE_ACQUIRE;
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] STOP_DEV done.", tpg_dev->soc_info.index);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_tpg_validate_cmd_descriptor(
|
||||
struct cam_cmd_buf_desc *cmd_desc,
|
||||
uint32_t *cmd_type, uintptr_t *cmd_addr)
|
||||
{
|
||||
int rc = 0;
|
||||
uintptr_t generic_ptr;
|
||||
size_t len_of_buff = 0;
|
||||
uint32_t *cmd_buf = NULL;
|
||||
struct tpg_command_header_t *cmd_header = NULL;
|
||||
|
||||
if (!cmd_desc || !cmd_type || !cmd_addr)
|
||||
return -EINVAL;
|
||||
|
||||
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
|
||||
&generic_ptr, &len_of_buff);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG,
|
||||
"Failed to get cmd buf Mem address : %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmd_buf = (uint32_t *)generic_ptr;
|
||||
cmd_buf += cmd_desc->offset / 4;
|
||||
cmd_header = (struct tpg_command_header_t *)cmd_buf;
|
||||
|
||||
if (len_of_buff < sizeof(struct tpg_command_header_t)) {
|
||||
CAM_ERR(CAM_TPG, "Got invalid command descriptor of invalid cmd buffer size");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (cmd_header->cmd_type) {
|
||||
case TPG_CMD_TYPE_GLOBAL_CONFIG: {
|
||||
if (cmd_header->size != sizeof(struct tpg_global_config_t)) {
|
||||
CAM_ERR(CAM_TPG, "Got invalid global config command recv: %d exp: %d",
|
||||
cmd_header->size,
|
||||
sizeof(struct tpg_global_config_t));
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
CAM_INFO(CAM_TPG, "Got global config cmd");
|
||||
*cmd_type = TPG_CMD_TYPE_GLOBAL_CONFIG;
|
||||
break;
|
||||
}
|
||||
case TPG_CMD_TYPE_STREAM_CONFIG: {
|
||||
if (cmd_header->size != sizeof(struct tpg_stream_config_t)) {
|
||||
CAM_ERR(CAM_TPG, "Got invalid stream config command recv: %d exp: %d",
|
||||
cmd_header->size,
|
||||
sizeof(struct tpg_stream_config_t));
|
||||
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
CAM_INFO(CAM_TPG, "Got stream config cmd");
|
||||
*cmd_type = TPG_CMD_TYPE_STREAM_CONFIG;
|
||||
break;
|
||||
}
|
||||
case TPG_CMD_TYPE_ILLUMINATION_CONFIG: {
|
||||
if (cmd_header->size != sizeof(struct tpg_illumination_control)) {
|
||||
CAM_ERR(CAM_TPG, "Got invalid illumination config command");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
*cmd_type = TPG_CMD_TYPE_ILLUMINATION_CONFIG;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
CAM_ERR(CAM_TPG, "invalid config command");
|
||||
goto end;
|
||||
}
|
||||
if ((ssize_t)cmd_desc->offset > (len_of_buff - cmd_header->size)) {
|
||||
CAM_ERR(CAM_TPG, "cmd header offset mismatch");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
*cmd_addr = (uintptr_t)cmd_header;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_tpg_cmd_buf_parse(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_packet *packet)
|
||||
{
|
||||
int rc = 0, i = 0;
|
||||
struct cam_cmd_buf_desc *cmd_desc = NULL;
|
||||
|
||||
if (!tpg_dev || !packet)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < packet->num_cmd_buf; i++) {
|
||||
uint32_t cmd_type = TPG_CMD_TYPE_INVALID;
|
||||
uintptr_t cmd_addr;
|
||||
|
||||
cmd_desc = (struct cam_cmd_buf_desc *)
|
||||
((uint32_t *)&packet->payload +
|
||||
(packet->cmd_buf_offset / 4) +
|
||||
(i * (sizeof(struct cam_cmd_buf_desc)/4)));
|
||||
|
||||
rc = cam_tpg_validate_cmd_descriptor(cmd_desc,
|
||||
&cmd_type, &cmd_addr);
|
||||
if (rc < 0)
|
||||
goto end;
|
||||
|
||||
switch (cmd_type) {
|
||||
case TPG_CMD_TYPE_GLOBAL_CONFIG:
|
||||
rc = tpg_hw_copy_global_config(&tpg_dev->tpg_hw,
|
||||
(struct tpg_global_config_t *)cmd_addr);
|
||||
break;
|
||||
case TPG_CMD_TYPE_STREAM_CONFIG: {
|
||||
rc = tpg_hw_add_stream(&tpg_dev->tpg_hw,
|
||||
(struct tpg_stream_config_t *)cmd_addr);
|
||||
break;
|
||||
}
|
||||
case TPG_CMD_TYPE_ILLUMINATION_CONFIG:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] ILLUMINATION CONFIG not supported now ",
|
||||
tpg_dev->soc_info.index);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] invalid command %d",
|
||||
tpg_dev->soc_info.index,
|
||||
cmd_type);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_tpg_packet_parse(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_config_dev_cmd *config)
|
||||
{
|
||||
int rc = 0;
|
||||
uintptr_t generic_ptr;
|
||||
size_t len_of_buff = 0, remain_len = 0;
|
||||
struct cam_packet *csl_packet = NULL;
|
||||
|
||||
rc = cam_mem_get_cpu_buf(config->packet_handle,
|
||||
&generic_ptr, &len_of_buff);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "Failed in getting the packet: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((sizeof(struct cam_packet) > len_of_buff) ||
|
||||
((size_t)config->offset >= len_of_buff -
|
||||
sizeof(struct cam_packet))) {
|
||||
CAM_ERR(CAM_TPG,
|
||||
"Inval cam_packet struct size: %zu, len_of_buff: %zu",
|
||||
sizeof(struct cam_packet), len_of_buff);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
remain_len = len_of_buff;
|
||||
remain_len -= (size_t)config->offset;
|
||||
csl_packet = (struct cam_packet *)(generic_ptr +
|
||||
(uint32_t)config->offset);
|
||||
|
||||
if (cam_packet_util_validate_packet(csl_packet,
|
||||
remain_len)) {
|
||||
CAM_ERR(CAM_TPG, "Invalid packet params");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] "
|
||||
"CONFIG_DEV, Packet opcode = %d num_cmds: %d num_ios: %d num_patch: %d",
|
||||
tpg_dev->soc_info.index,
|
||||
(csl_packet->header.op_code & 0xFF),
|
||||
csl_packet->num_cmd_buf,
|
||||
csl_packet->num_io_configs,
|
||||
csl_packet->num_patches);
|
||||
switch ((csl_packet->header.op_code & 0xFF)) {
|
||||
case CAM_TPG_PACKET_OPCODE_INITIAL_CONFIG: {
|
||||
if (csl_packet->num_cmd_buf <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Expecting atleast one command in Init packet");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
rc = cam_tpg_cmd_buf_parse(tpg_dev, csl_packet);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "CMD buffer parse failed");
|
||||
goto end;
|
||||
}
|
||||
tpg_hw_config(&tpg_dev->tpg_hw, TPG_HW_CMD_INIT_CONFIG, NULL);
|
||||
break;
|
||||
}
|
||||
case CAM_TPG_PACKET_OPCODE_NOP: {
|
||||
struct cam_req_mgr_add_request add_req = {0};
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] NOP packet request id : %llu",
|
||||
tpg_dev->soc_info.index,
|
||||
csl_packet->header.request_id);
|
||||
if ((tpg_dev->crm_intf.link_hdl != -1) &&
|
||||
(tpg_dev->crm_intf.device_hdl != -1) &&
|
||||
(tpg_dev->crm_intf.crm_cb != NULL)) {
|
||||
add_req.link_hdl = tpg_dev->crm_intf.link_hdl;
|
||||
add_req.dev_hdl = tpg_dev->crm_intf.device_hdl;
|
||||
add_req.req_id = csl_packet->header.request_id;
|
||||
tpg_dev->crm_intf.crm_cb->add_req(&add_req);
|
||||
} else {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] invalid link req: %llu",
|
||||
tpg_dev->soc_info.index,
|
||||
csl_packet->header.request_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Invalid packet %x",
|
||||
tpg_dev->soc_info.index,
|
||||
(csl_packet->header.op_code & 0xFF));
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_tpg_handle_config_dev(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_config_dev_cmd *config)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!config || !tpg_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (config->dev_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Invalid device handle",
|
||||
tpg_dev->soc_info.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (config->session_handle <= 0) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Invalid session handle",
|
||||
tpg_dev->soc_info.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tpg_dev->state < CAM_TPG_STATE_ACQUIRE) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] not in right state[%d] to configure",
|
||||
tpg_dev->soc_info.index, tpg_dev->state);
|
||||
}
|
||||
// Handle Config Dev
|
||||
rc = cam_tpg_packet_parse(tpg_dev, config);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int validate_ioctl_params(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
struct cam_control *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!tpg_dev || !cmd) {
|
||||
CAM_ERR(CAM_TPG, "Invalid input args");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Invalid handle type: %d",
|
||||
tpg_dev->soc_info.index,
|
||||
cmd->handle_type);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] Opcode: %d", tpg_dev->soc_info.index, cmd->op_code);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tpg_core_cfg(
|
||||
struct cam_tpg_device *tpg_dev,
|
||||
void *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_control *cmd = (struct cam_control *)arg;
|
||||
|
||||
rc = validate_ioctl_params(tpg_dev, cmd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&tpg_dev->mutex);
|
||||
switch (cmd->op_code) {
|
||||
case CAM_QUERY_CAP: {
|
||||
struct cam_tpg_query_cap query = {0};
|
||||
|
||||
if (copy_from_user(&query, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(query))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = __cam_tpg_handle_query_cap(tpg_dev, &query);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] querycap is failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_user(u64_to_user_ptr(cmd->handle), &query,
|
||||
sizeof(query)))
|
||||
rc = -EFAULT;
|
||||
|
||||
break;
|
||||
}
|
||||
case CAM_ACQUIRE_DEV: {
|
||||
struct cam_tpg_acquire_dev acquire = {0};
|
||||
|
||||
if (copy_from_user(&acquire, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(acquire))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
rc = __cam_tpg_handle_acquire_dev(tpg_dev, &acquire);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] acquire device failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
break;
|
||||
}
|
||||
if (copy_to_user(u64_to_user_ptr(cmd->handle), &acquire,
|
||||
sizeof(acquire)))
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CAM_RELEASE_DEV: {
|
||||
struct cam_release_dev_cmd release;
|
||||
|
||||
if (copy_from_user(&release, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(release)))
|
||||
rc = -EFAULT;
|
||||
else {
|
||||
rc = __cam_tpg_handle_release_dev(tpg_dev, &release);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG,
|
||||
"TPG[%d] release device failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAM_START_DEV: {
|
||||
struct cam_start_stop_dev_cmd start;
|
||||
|
||||
if (copy_from_user(&start, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(start)))
|
||||
rc = -EFAULT;
|
||||
else {
|
||||
rc = __cam_tpg_handle_start_dev(tpg_dev, &start);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG,
|
||||
"TPG[%d] start device failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAM_STOP_DEV: {
|
||||
struct cam_start_stop_dev_cmd stop;
|
||||
|
||||
if (copy_from_user(&stop, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(stop)))
|
||||
rc = -EFAULT;
|
||||
else {
|
||||
rc = __cam_tpg_handle_stop_dev(tpg_dev, &stop);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG,
|
||||
"TPG[%d] stop device failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case CAM_CONFIG_DEV: {
|
||||
struct cam_config_dev_cmd config;
|
||||
|
||||
if (copy_from_user(&config, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(config)))
|
||||
rc = -EFAULT;
|
||||
else {
|
||||
rc = __cam_tpg_handle_config_dev(tpg_dev, &config);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG,
|
||||
"TPG[%d] config device failed(rc = %d)",
|
||||
tpg_dev->soc_info.index,
|
||||
rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "Invalid ioctl : %d", cmd->op_code);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&tpg_dev->mutex);
|
||||
return rc;
|
||||
}
|
39
drivers/cam_sensor_module/cam_tpg/cam_tpg_core.h
Normal file
39
drivers/cam_sensor_module/cam_tpg/cam_tpg_core.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CAM_TPG_CORE_H__
|
||||
#define __CAM_TPG_CORE_H__
|
||||
|
||||
#include "cam_tpg_dev.h"
|
||||
|
||||
/**
|
||||
* @brief : do clean up of driver on user space process restart
|
||||
*
|
||||
* @param tpg_dev: tpg device
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int cam_tpg_shutdown(struct cam_tpg_device *tpg_dev);
|
||||
|
||||
/**
|
||||
* @brief initialize crm interface
|
||||
*
|
||||
* @param tpg_dev: tpg device instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_crm_intf_init(struct cam_tpg_device *tpg_dev);
|
||||
|
||||
/**
|
||||
* @brief : handle tpg device configuration
|
||||
*
|
||||
* @param tpg_dev : tpg device instance
|
||||
* @param arg : configuration argument
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int32_t cam_tpg_core_cfg(struct cam_tpg_device *tpg_dev, void *arg);
|
||||
|
||||
#endif
|
381
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.c
Normal file
381
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.c
Normal file
@@ -0,0 +1,381 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cam_tpg_dev.h"
|
||||
#include "cam_tpg_core.h"
|
||||
#include "camera_main.h"
|
||||
#include "tpg_hw/tpg_hw_v_1_0/tpg_hw_v_1_0_data.h"
|
||||
#include "tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h"
|
||||
|
||||
static long cam_tpg_subdev_ioctl(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
struct cam_tpg_device *tpg_dev = v4l2_get_subdevdata(sd);
|
||||
int rc = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case VIDIOC_CAM_CONTROL:
|
||||
rc = cam_tpg_core_cfg(tpg_dev, arg);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "Wrong ioctl : %d", cmd);
|
||||
rc = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long cam_tpg_subdev_compat_ioctl(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct cam_control cmd_data;
|
||||
|
||||
if (copy_from_user(&cmd_data, (void __user *)arg,
|
||||
sizeof(cmd_data))) {
|
||||
CAM_ERR(CAM_TPG, "Failed to copy from user_ptr=%pK size=%zu",
|
||||
(void __user *)arg, sizeof(cmd_data));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* All the arguments converted to 64 bit here
|
||||
* Passed to the api in core.c
|
||||
*/
|
||||
switch (cmd) {
|
||||
case VIDIOC_CAM_CONTROL:
|
||||
rc = cam_tpg_subdev_ioctl(sd, cmd, &cmd_data);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG,
|
||||
"Failed in subdev_ioctl: %d", rc);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "Invalid compat ioctl cmd: %d", cmd);
|
||||
rc = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
if (copy_to_user((void __user *)arg, &cmd_data,
|
||||
sizeof(cmd_data))) {
|
||||
CAM_ERR(CAM_TPG,
|
||||
"Failed to copy to user_ptr=%pK size=%zu",
|
||||
(void __user *)arg, sizeof(cmd_data));
|
||||
rc = -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static struct v4l2_subdev_core_ops tpg_subdev_core_ops = {
|
||||
.ioctl = cam_tpg_subdev_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl32 = cam_tpg_subdev_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int cam_tpg_subdev_close(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct cam_tpg_device *tpg_dev =
|
||||
v4l2_get_subdevdata(sd);
|
||||
|
||||
if (!tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "tpg_dev ptr is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&tpg_dev->mutex);
|
||||
cam_tpg_shutdown(tpg_dev);
|
||||
mutex_unlock(&tpg_dev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_ops tpg_subdev_ops = {
|
||||
.core = &tpg_subdev_core_ops,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_internal_ops tpg_subdev_intern_ops = {
|
||||
.close = cam_tpg_subdev_close,
|
||||
};
|
||||
|
||||
irqreturn_t cam_tpg_irq_handler(int irq_num, void *data)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "tpg irq handler");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static int tpg_subdev_init(struct cam_tpg_device *tpg_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
tpg_dev->tpg_subdev.pdev = pdev;
|
||||
tpg_dev->tpg_subdev.internal_ops = &tpg_subdev_intern_ops;
|
||||
tpg_dev->tpg_subdev.ops = &tpg_subdev_ops;
|
||||
tpg_dev->tpg_subdev.name = tpg_dev->device_name;
|
||||
tpg_dev->tpg_subdev.sd_flags =
|
||||
(V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
|
||||
tpg_dev->tpg_subdev.ent_function = CAM_TPG_DEVICE_TYPE;
|
||||
tpg_dev->tpg_subdev.msg_cb = NULL;
|
||||
tpg_dev->tpg_subdev.token = tpg_dev;
|
||||
|
||||
rc = cam_register_subdev(&(tpg_dev->tpg_subdev));
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG, "cam_register_subdev Failed rc: %d", rc);
|
||||
else
|
||||
CAM_DBG(CAM_TPG, "TPG subdev init done");
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static int tpg_soc_info_init(struct cam_tpg_device *tpg_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct device_node *of_node = NULL;
|
||||
|
||||
tpg_dev->soc_info.pdev = pdev;
|
||||
tpg_dev->soc_info.dev = &pdev->dev;
|
||||
tpg_dev->soc_info.dev_name = pdev->name;
|
||||
if (!dev || !tpg_dev)
|
||||
return -EINVAL;
|
||||
|
||||
of_node = dev->of_node;
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(&tpg_dev->soc_info);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CSIPHY, "parsing common soc dt(rc %d)", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(of_node, "phy-id", &(tpg_dev->phy_id));
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "device %s failed to read phy-id",
|
||||
tpg_dev->soc_info.dev_name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_request_platform_resource(
|
||||
&tpg_dev->soc_info,
|
||||
cam_tpg_irq_handler,
|
||||
tpg_dev);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG, "unable to request platfrom resources");
|
||||
else
|
||||
CAM_DBG(CAM_TPG, "TPG dt parse done");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpg_register_cpas_client(struct cam_tpg_device *tpg_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct cam_cpas_register_params cpas_parms;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
cpas_parms.cam_cpas_client_cb = NULL;
|
||||
cpas_parms.cell_index = tpg_dev->soc_info.index;
|
||||
cpas_parms.dev = &pdev->dev;
|
||||
cpas_parms.userdata = tpg_dev;
|
||||
|
||||
strlcpy(cpas_parms.identifier, "tpg", CAM_HW_IDENTIFIER_LENGTH);
|
||||
|
||||
rc = cam_cpas_register_client(&cpas_parms);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "CPAS registration failed rc: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
tpg_dev->cpas_handle = cpas_parms.client_handle;
|
||||
CAM_DBG(CAM_TPG, "CPAS registration successful handle=%d",
|
||||
cpas_parms.client_handle);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_tpg_hw_layer_init(struct cam_tpg_device *tpg_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
int i = 0;
|
||||
/* get top tpg hw information */
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev) {
|
||||
CAM_ERR(CAM_TPG, "No matching table for the top tpg hw");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_dev->tpg_hw.hw_idx = tpg_dev->soc_info.index;
|
||||
tpg_dev->tpg_hw.hw_info = (struct tpg_hw_info *)match_dev->data;
|
||||
tpg_dev->tpg_hw.soc_info = &tpg_dev->soc_info;
|
||||
tpg_dev->tpg_hw.cpas_handle = tpg_dev->cpas_handle;
|
||||
mutex_init(&tpg_dev->tpg_hw.mutex);
|
||||
|
||||
tpg_dev->tpg_hw.vc_slots = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct tpg_vc_slot_info) * tpg_dev->tpg_hw.hw_info->max_vc_channels,
|
||||
GFP_KERNEL);
|
||||
if (!tpg_dev->tpg_hw.vc_slots) {
|
||||
CAM_ERR(CAM_TPG, "TPG VC slot allocation failed");
|
||||
mutex_destroy(&tpg_dev->tpg_hw.mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for(i = 0; i < tpg_dev->tpg_hw.hw_info->max_vc_channels; i++) {
|
||||
tpg_dev->tpg_hw.vc_slots[i].slot_id = i;
|
||||
tpg_dev->tpg_hw.vc_slots[i].vc = -1;
|
||||
tpg_dev->tpg_hw.vc_slots[i].stream_count = 0;
|
||||
INIT_LIST_HEAD(&(tpg_dev->tpg_hw.vc_slots[i].head));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_tpg_component_bind(struct device *dev,
|
||||
struct device *master_dev, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tpg_device *tpg_dev = NULL;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
tpg_dev = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct cam_tpg_device), GFP_KERNEL);
|
||||
if (!tpg_dev) {
|
||||
CAM_ERR(CAM_TPG, "TPG dev allocation failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strlcpy(tpg_dev->device_name, CAMX_TPG_DEV_NAME,
|
||||
sizeof(tpg_dev->device_name));
|
||||
mutex_init(&tpg_dev->mutex);
|
||||
tpg_dev->tpg_subdev.pdev = pdev;
|
||||
tpg_dev->state = CAM_TPG_STATE_INIT;
|
||||
rc = tpg_subdev_init(tpg_dev, dev);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "subdev init failed");
|
||||
goto bind_error_exit;
|
||||
}
|
||||
|
||||
rc = tpg_soc_info_init(tpg_dev, dev);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "soc init failed");
|
||||
goto release_subdev;
|
||||
}
|
||||
|
||||
rc = tpg_register_cpas_client(tpg_dev, dev);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "cpas register failed");
|
||||
goto release_subdev;
|
||||
}
|
||||
tpg_crm_intf_init(tpg_dev);
|
||||
rc = cam_tpg_hw_layer_init(tpg_dev, dev);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "Hw layer init failed");
|
||||
goto release_subdev;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
release_subdev:
|
||||
cam_unregister_subdev(&(tpg_dev->tpg_subdev));
|
||||
bind_error_exit:
|
||||
mutex_destroy(&tpg_dev->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cam_tpg_component_unbind(struct device *dev,
|
||||
struct device *master_dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
|
||||
struct cam_tpg_device *tpg_dev = v4l2_get_subdevdata(subdev);
|
||||
|
||||
CAM_INFO(CAM_TPG, "Unbind TPG component");
|
||||
cam_cpas_unregister_client(tpg_dev->cpas_handle);
|
||||
cam_soc_util_release_platform_resource(&tpg_dev->soc_info);
|
||||
mutex_destroy(&tpg_dev->mutex);
|
||||
mutex_destroy(&tpg_dev->tpg_hw.mutex);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
v4l2_set_subdevdata(&(tpg_dev->tpg_subdev.sd), NULL);
|
||||
cam_unregister_subdev(&(tpg_dev->tpg_subdev));
|
||||
}
|
||||
|
||||
const static struct component_ops cam_tpg_component_ops = {
|
||||
.bind = cam_tpg_component_bind,
|
||||
.unbind = cam_tpg_component_unbind,
|
||||
};
|
||||
|
||||
static int32_t cam_tpg_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_TPG, "Adding TPG component");
|
||||
rc = component_add(&pdev->dev, &cam_tpg_component_ops);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG, "failed to add component rc: %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int32_t cam_tpg_device_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &cam_tpg_component_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_tpg_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,cam-tpg101",
|
||||
.data = &tpg_v_1_0_hw_info,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,cam-tpg103",
|
||||
.data = &tpg_v_1_3_hw_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, cam_tpg_dt_match);
|
||||
|
||||
struct platform_driver cam_tpg_driver = {
|
||||
.probe = cam_tpg_platform_probe,
|
||||
.remove = cam_tpg_device_remove,
|
||||
.driver = {
|
||||
.name = CAMX_TPG_DEV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cam_tpg_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int32_t cam_tpg_init_module(void)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "tpg module init");
|
||||
return platform_driver_register(&cam_tpg_driver);
|
||||
}
|
||||
|
||||
void cam_tpg_exit_module(void)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "tpg exit module");
|
||||
platform_driver_unregister(&cam_tpg_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM TPG driver");
|
||||
MODULE_LICENSE("GPL v2");
|
142
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.h
Normal file
142
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CAM_TPG_DEV_H__
|
||||
#define __CAM_TPG_DEV_H__
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/cam_defs.h>
|
||||
#include <cam_sensor_cmn_header.h>
|
||||
#include <cam_req_mgr_interface.h>
|
||||
#include <cam_subdev.h>
|
||||
#include <cam_io_util.h>
|
||||
#include <media/cam_defs.h>
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_context.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include <cam_cpas_api.h>
|
||||
#include "tpg_hw/tpg_hw.h"
|
||||
|
||||
#define CAMX_TPG_DEV_NAME "cam-tpg-driver"
|
||||
|
||||
struct cam_tpg_device;
|
||||
struct tpg_hw;
|
||||
|
||||
struct cam_tpg_ioctl_ops {
|
||||
int (*acquire_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_acquire_dev_cmd *cmd);
|
||||
int (*release_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_release_dev_cmd *cmd);
|
||||
int (*config_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_config_dev_cmd *cmd);
|
||||
int (*start_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_start_stop_dev_cmd *cmd);
|
||||
int (*stop_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_start_stop_dev_cmd *cmd);
|
||||
int (*flush_dev)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_flush_dev_cmd *cmd);
|
||||
int (*acquire_hw)(struct cam_tpg_device *tpg_dev, void *args);
|
||||
int (*release_hw)(struct cam_tpg_device *tpg_dev, void *args);
|
||||
};
|
||||
|
||||
struct cam_tpg_crm_ops {
|
||||
int (*get_dev_info)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_device_info *device_info);
|
||||
int (*link)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_core_dev_link_setup *link);
|
||||
int (*unlink)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_core_dev_link_setup *unlink);
|
||||
int (*apply_req)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_apply_request *apply);
|
||||
int (*notify_frame_skip)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_apply_request *apply);
|
||||
int (*flush_req)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_flush_request *flush);
|
||||
int (*process_evt)(struct cam_tpg_device *tpg_dev,
|
||||
struct cam_req_mgr_link_evt_data *evt_data);
|
||||
};
|
||||
|
||||
struct tpg_device_ops {
|
||||
struct cam_tpg_ioctl_ops ioctl_ops;
|
||||
struct cam_tpg_crm_ops crm_ops;
|
||||
};
|
||||
|
||||
enum cam_tpg_state {
|
||||
CAM_TPG_STATE_INIT,
|
||||
CAM_TPG_STATE_ACQUIRE,
|
||||
CAM_TPG_STATE_START,
|
||||
CAM_TPG_STATE_STATE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tpg_crm_intf_params
|
||||
* @device_hdl: Device Handle
|
||||
* @session_hdl: Session Handle
|
||||
* @link_hdl: Link Handle
|
||||
* @ops: KMD operations
|
||||
* @crm_cb: Callback API pointers
|
||||
*/
|
||||
struct tpg_crm_intf_params {
|
||||
int32_t device_hdl;
|
||||
int32_t session_hdl;
|
||||
int32_t link_hdl;
|
||||
struct cam_req_mgr_kmd_ops ops;
|
||||
struct cam_req_mgr_crm_cb *crm_cb;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_tpg_device
|
||||
*
|
||||
* @device_name: tpg device name
|
||||
* @mutex: mutex object for private use
|
||||
* @tpg_subdev: tpg subdevice instance
|
||||
* @soc_info: tpg soc infrastructure
|
||||
* @cpas_handle: cpas handle
|
||||
* @state_machine: tpg state machine
|
||||
* @crm_intf: crm interface
|
||||
* @tpg_hw : tpg hw instance
|
||||
* @state : state machine states
|
||||
* @slot_id : slot index of this tpg
|
||||
* @phy_id : phy index mapped to this tpg
|
||||
*/
|
||||
struct cam_tpg_device {
|
||||
char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
|
||||
struct mutex mutex;
|
||||
struct cam_subdev tpg_subdev;
|
||||
struct cam_hw_soc_info soc_info;
|
||||
uint32_t cpas_handle;
|
||||
struct tpg_device_ops state_machine[CAM_TPG_STATE_STATE_MAX];
|
||||
struct tpg_crm_intf_params crm_intf;
|
||||
struct tpg_hw tpg_hw;
|
||||
int state;
|
||||
int slot_id;
|
||||
int phy_id;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief : tpg module init
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int32_t cam_tpg_init_module(void);
|
||||
|
||||
/**
|
||||
* @brief : tpg module exit
|
||||
*/
|
||||
void cam_tpg_exit_module(void);
|
||||
|
||||
#endif
|
671
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c
Normal file
671
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c
Normal file
@@ -0,0 +1,671 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "tpg_hw.h"
|
||||
|
||||
#define BYTES_PER_REGISTER 4
|
||||
#define NUM_REGISTER_PER_LINE 4
|
||||
#define REG_OFFSET(__start, __i) ((__start) + ((__i) * BYTES_PER_REGISTER))
|
||||
|
||||
static int cam_io_tpg_dump(void __iomem *base_addr,
|
||||
uint32_t start_offset, int size)
|
||||
{
|
||||
char line_str[128];
|
||||
char *p_str;
|
||||
int i;
|
||||
uint32_t data;
|
||||
|
||||
CAM_DBG(CAM_TPG, "addr=%pK offset=0x%x size=%d",
|
||||
base_addr, start_offset, size);
|
||||
|
||||
if (!base_addr || (size <= 0))
|
||||
return -EINVAL;
|
||||
|
||||
line_str[0] = '\0';
|
||||
p_str = line_str;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i % NUM_REGISTER_PER_LINE == 0) {
|
||||
snprintf(p_str, 12, "0x%08x: ",
|
||||
REG_OFFSET(start_offset, i));
|
||||
p_str += 11;
|
||||
}
|
||||
data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i));
|
||||
snprintf(p_str, 9, "%08x ", data);
|
||||
p_str += 8;
|
||||
if ((i + 1) % NUM_REGISTER_PER_LINE == 0) {
|
||||
CAM_DBG(CAM_TPG, "%s", line_str);
|
||||
line_str[0] = '\0';
|
||||
p_str = line_str;
|
||||
}
|
||||
}
|
||||
if (line_str[0] != '\0')
|
||||
CAM_ERR(CAM_TPG, "%s", line_str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t cam_tpg_mem_dmp(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
resource_size_t size = 0;
|
||||
void __iomem *addr = NULL;
|
||||
|
||||
if (!soc_info) {
|
||||
rc = -EINVAL;
|
||||
CAM_ERR(CAM_TPG, "invalid input %d", rc);
|
||||
return rc;
|
||||
}
|
||||
addr = soc_info->reg_map[0].mem_base;
|
||||
size = resource_size(soc_info->mem_block[0]);
|
||||
rc = cam_io_tpg_dump(addr, 0, (size >> 2));
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_TPG, "generating dump failed %d", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#define __TPG_DEBUG_DUMP__
|
||||
#ifdef __TPG_DEBUG_DUMP__
|
||||
static const char * const tpg_phy_type_strings[] = {
|
||||
"TPG_PHY_TYPE_INVALID",
|
||||
"TPG_PHY_TYPE_DPHY",
|
||||
"TPG_PHY_TYPE_CPHY",
|
||||
"TPG_PHY_TYPE_MAX"
|
||||
};
|
||||
|
||||
static const char * const tpg_interleaving_format_string[] = {
|
||||
"TPG_INTERLEAVING_FORMAT_INVALID",
|
||||
"TPG_INTERLEAVING_FORMAT_FRAME",
|
||||
"TPG_INTERLEAVING_FORMAT_LINE",
|
||||
"TPG_INTERLEAVING_FORMAT_MAX"
|
||||
};
|
||||
|
||||
static const char * const tpg_shutter_type_strings[] = {
|
||||
"TPG_SHUTTER_TYPE_INVALID",
|
||||
"TPG_SHUTTER_TYPE_ROLLING",
|
||||
"TPG_SHUTTER_TYPE_GLOBAL",
|
||||
"TPG_SHUTTER_TYPE_MAX"
|
||||
};
|
||||
|
||||
static const char *const tpg_pattern_type_strings[] = {
|
||||
"TPG_PATTERN_INVALID",
|
||||
"TPG_PATTERN_REAL_IMAGE",
|
||||
"TPG_PATTERN_RANDOM_PIXL",
|
||||
"TPG_PATTERN_RANDOM_INCREMENTING_PIXEL",
|
||||
"TPG_PATTERN_COLOR_BAR",
|
||||
"TPG_PATTERN_ALTERNATING_55_AA",
|
||||
"TPG_PATTERN_ALTERNATING_USER_DEFINED",
|
||||
"TPG_PATTERN_MAX"
|
||||
};
|
||||
|
||||
static const char *const tpg_color_bar_mode_strings[] = {
|
||||
"TPG_COLOR_BAR_MODE_INVALID",
|
||||
"TPG_COLOR_BAR_MODE_NORMAL",
|
||||
"TPG_COLOR_BAR_MODE_SPLIT",
|
||||
"TPG_COLOR_BAR_MODE_ROTATING",
|
||||
"TPG_COLOR_BAR_MODE_MAX"
|
||||
};
|
||||
|
||||
static const char *const tpg_stream_type_strings[] = {
|
||||
"TPG_STREAM_TYPE_INVALID",
|
||||
"TPG_STREAM_TYPE_IMAGE",
|
||||
"TPG_STREAM_TYPE_PDAF",
|
||||
"TPG_STREAM_TYPE_META",
|
||||
"TPG_STREAM_TYPE_MAX"
|
||||
};
|
||||
|
||||
static const char *const tpg_image_format_type_strings[] = {
|
||||
"TPG_IMAGE_FORMAT_INVALID",
|
||||
"TPG_IMAGE_FORMAT_BAYER",
|
||||
"TPG_IMAGE_FORMAT_QCFA",
|
||||
"TPG_IMAGE_FORMAT_YUV",
|
||||
"TPG_IMAGE_FORMAT_JPEG",
|
||||
"TPG_IMAGE_FORMAT_MAX"
|
||||
};
|
||||
#endif
|
||||
|
||||
int dump_global_configs(int idx,
|
||||
struct tpg_global_config_t *global)
|
||||
{
|
||||
#ifdef __TPG_DEBUG_DUMP__
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] phy_type : %s",
|
||||
idx,
|
||||
tpg_phy_type_strings[global->phy_type]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] lane_count : %d",
|
||||
idx,
|
||||
global->lane_count);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] interleaving_format : %s",
|
||||
idx,
|
||||
tpg_interleaving_format_string[global->interleaving_format]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] phy_mode : %d",
|
||||
idx,
|
||||
global->phy_mode);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] shutter_type : %s",
|
||||
idx,
|
||||
tpg_shutter_type_strings[global->shutter_type]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] skip pattern : 0x%x",
|
||||
idx,
|
||||
global->skip_pattern);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] tpg clock : %d",
|
||||
idx,
|
||||
global->tpg_clock);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_stream_configs(int hw_idx,
|
||||
int stream_idx,
|
||||
struct tpg_stream_config_t *stream)
|
||||
{
|
||||
#ifdef __TPG_DEBUG_DUMP__
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] pattern_type : %s",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
tpg_pattern_type_strings[stream->pattern_type]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] cb_mode : %s",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
tpg_color_bar_mode_strings[stream->cb_mode]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] frame_count : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->frame_count);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] stream_type : %s",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
tpg_stream_type_strings[stream->stream_type]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] left : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->stream_dimension.left);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] top : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->stream_dimension.top);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] width : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->stream_dimension.width);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] height : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->stream_dimension.height);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] pixel_depth : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->pixel_depth);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] cfa_arrangement : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->cfa_arrangement);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] output_format : %s",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
tpg_image_format_type_strings[stream->output_format]);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] vc : 0x%x",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->vc);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] dt : 0x%x",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->dt);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] hbi : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->hbi);
|
||||
CAM_DBG(CAM_TPG, "TPG[%d][%d] vbi : %d",
|
||||
hw_idx,
|
||||
stream_idx,
|
||||
stream->vbi);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int tpg_hw_soc_disable(struct tpg_hw *hw)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->soc_info) {
|
||||
CAM_ERR(CAM_TPG, "Error Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(hw->soc_info, true, false);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d",
|
||||
hw->hw_idx, rc);
|
||||
|
||||
if (cam_cpas_stop(hw->cpas_handle)) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] CPAS stop failed",
|
||||
hw->hw_idx);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpg_hw_soc_enable(
|
||||
struct tpg_hw *hw,
|
||||
enum cam_vote_level clk_level)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote = {0};
|
||||
|
||||
ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
axi_vote.num_paths = 1;
|
||||
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
|
||||
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE;
|
||||
|
||||
axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ",
|
||||
hw->hw_idx,
|
||||
axi_vote.axi_path[0].camnoc_bw,
|
||||
axi_vote.axi_path[0].mnoc_ab_bw,
|
||||
axi_vote.axi_path[0].mnoc_ib_bw);
|
||||
|
||||
rc = cam_cpas_start(hw->cpas_handle, &ahb_vote, &axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] CPAS start failed",
|
||||
hw->hw_idx);
|
||||
rc = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(hw->soc_info, true,
|
||||
clk_level, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] enable platform failed",
|
||||
hw->hw_idx);
|
||||
goto stop_cpas;
|
||||
}
|
||||
|
||||
return rc;
|
||||
stop_cpas:
|
||||
cam_cpas_stop(hw->cpas_handle);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpg_hw_start_default_new(struct tpg_hw *hw)
|
||||
{
|
||||
int i = 0;
|
||||
uint32_t stream_idx = 0;
|
||||
int num_vcs = 0;
|
||||
struct global_config_args globalargs = {0};
|
||||
if (!hw ||
|
||||
!hw->hw_info ||
|
||||
!hw->hw_info->ops ||
|
||||
!hw->hw_info->ops->process_cmd) {
|
||||
CAM_ERR(CAM_TPG, "Invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dump_global_configs(hw->hw_idx, &hw->global_config);
|
||||
for(i = 0; i < hw->hw_info->max_vc_channels; i++) {
|
||||
int dt_slot = 0;
|
||||
struct vc_config_args vc_config = {0};
|
||||
struct list_head *pos = NULL, *pos_next = NULL;
|
||||
struct tpg_hw_stream *entry = NULL, *vc_stream_entry = NULL;
|
||||
|
||||
if (hw->vc_slots[i].vc == -1)
|
||||
break;
|
||||
num_vcs++;
|
||||
vc_config.vc_slot = i;
|
||||
vc_config.num_dts = hw->vc_slots[i].stream_count;
|
||||
vc_stream_entry = list_first_entry(&hw->vc_slots[i].head,
|
||||
struct tpg_hw_stream, list);
|
||||
vc_config.stream = &vc_stream_entry->stream;
|
||||
hw->hw_info->ops->process_cmd(hw,
|
||||
TPG_CONFIG_VC, &vc_config);
|
||||
|
||||
list_for_each_safe(pos, pos_next, &hw->vc_slots[i].head) {
|
||||
struct dt_config_args dt_config = {0};
|
||||
entry = list_entry(pos, struct tpg_hw_stream, list);
|
||||
dump_stream_configs(hw->hw_idx,
|
||||
stream_idx++,
|
||||
&entry->stream);
|
||||
dt_config.vc_slot = i;
|
||||
dt_config.dt_slot = dt_slot++;
|
||||
dt_config.stream = &entry->stream;
|
||||
hw->hw_info->ops->process_cmd(hw, TPG_CONFIG_DT, &dt_config);
|
||||
}
|
||||
}
|
||||
|
||||
globalargs.num_vcs = num_vcs;
|
||||
globalargs.globalconfig = &hw->global_config;
|
||||
hw->hw_info->ops->process_cmd(hw,
|
||||
TPG_CONFIG_CTRL, &globalargs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_dump_status(struct tpg_hw *hw)
|
||||
{
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_3:
|
||||
if (hw->hw_info->ops->dump_status)
|
||||
hw->hw_info->ops->dump_status(hw, NULL);
|
||||
default:
|
||||
CAM_WARN(CAM_TPG, "Hw version doesn't support status dump");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_start(struct tpg_hw *hw)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
mutex_lock(&hw->mutex);
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_0:
|
||||
case TPG_HW_VERSION_1_1:
|
||||
if (hw->hw_info->ops->start)
|
||||
hw->hw_info->ops->start(hw, NULL);
|
||||
break;
|
||||
case TPG_HW_VERSION_1_3:
|
||||
if (hw->hw_info->ops->start)
|
||||
hw->hw_info->ops->start(hw, NULL);
|
||||
tpg_hw_start_default_new(hw);
|
||||
cam_tpg_mem_dmp(hw->soc_info);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&hw->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_stop(struct tpg_hw *hw)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
mutex_lock(&hw->mutex);
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_0:
|
||||
case TPG_HW_VERSION_1_1:
|
||||
case TPG_HW_VERSION_1_3:
|
||||
if (hw->hw_info->ops->stop)
|
||||
rc = hw->hw_info->ops->stop(hw, NULL);
|
||||
rc = tpg_hw_soc_disable(hw);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&hw->mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_acquire(struct tpg_hw *hw,
|
||||
struct tpg_hw_acquire_args *acquire)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&hw->mutex);
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_0:
|
||||
case TPG_HW_VERSION_1_1:
|
||||
case TPG_HW_VERSION_1_3:
|
||||
// Start Cpas and enable required clocks
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&hw->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_release(struct tpg_hw *hw)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
mutex_lock(&hw->mutex);
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_0:
|
||||
case TPG_HW_VERSION_1_1:
|
||||
case TPG_HW_VERSION_1_3:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&hw->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpg_hw_configure_init_settings(
|
||||
struct tpg_hw *hw,
|
||||
struct tpg_hw_initsettings *settings)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
mutex_lock(&hw->mutex);
|
||||
switch (hw->hw_info->version) {
|
||||
case TPG_HW_VERSION_1_0:
|
||||
case TPG_HW_VERSION_1_1:
|
||||
case TPG_HW_VERSION_1_3:
|
||||
rc = tpg_hw_soc_enable(hw, CAM_SVS_VOTE);
|
||||
if (hw->hw_info->ops->init)
|
||||
rc = hw->hw_info->ops->init(hw, settings);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported HW Version",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&hw->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_config(
|
||||
struct tpg_hw *hw,
|
||||
enum tpg_hw_cmd_t config_cmd,
|
||||
void *config_args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hw || !hw->hw_info || !hw->hw_info->ops)
|
||||
return -EINVAL;
|
||||
switch (config_cmd) {
|
||||
case TPG_HW_CMD_INIT_CONFIG:
|
||||
//validate_stream_list(hw);
|
||||
tpg_hw_configure_init_settings(hw,
|
||||
(struct tpg_hw_initsettings *)config_args);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unsupported hw config command",
|
||||
hw->hw_idx);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_free_streams(struct tpg_hw *hw)
|
||||
{
|
||||
struct list_head *pos = NULL, *pos_next = NULL;
|
||||
struct tpg_hw_stream *entry;
|
||||
int i = 0;
|
||||
|
||||
if (!hw)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&hw->mutex);
|
||||
/* free up the streams */
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] Freeing all the streams", hw->hw_idx);
|
||||
|
||||
/* reset the slots */
|
||||
for(i = 0; i < hw->hw_info->max_vc_channels; i++) {
|
||||
hw->vc_slots[i].slot_id = i;
|
||||
hw->vc_slots[i].vc = -1;
|
||||
hw->vc_slots[i].stream_count = 0;
|
||||
list_for_each_safe(pos, pos_next, &hw->vc_slots[i].head) {
|
||||
entry = list_entry(pos, struct tpg_hw_stream, list);
|
||||
list_del(pos);
|
||||
kfree(entry);
|
||||
}
|
||||
INIT_LIST_HEAD(&(hw->vc_slots[i].head));
|
||||
}
|
||||
hw->vc_count = 0;
|
||||
|
||||
mutex_unlock(&hw->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_copy_global_config(
|
||||
struct tpg_hw *hw,
|
||||
struct tpg_global_config_t *global)
|
||||
{
|
||||
if (!hw || !global) {
|
||||
CAM_ERR(CAM_TPG, "invalid parameter");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&hw->mutex);
|
||||
memcpy(&hw->global_config,
|
||||
global,
|
||||
sizeof(struct tpg_global_config_t));
|
||||
mutex_unlock(&hw->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int assign_vc_slot(
|
||||
struct tpg_hw *hw,
|
||||
int vc,
|
||||
struct tpg_hw_stream *stream
|
||||
)
|
||||
{
|
||||
int rc = -EINVAL, i = 0, slot_matched = 0;
|
||||
|
||||
if (!hw || !stream) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for(i = 0; i < hw->hw_info->max_vc_channels; i++) {
|
||||
/* Found a matching slot */
|
||||
if(hw->vc_slots[i].vc == vc) {
|
||||
slot_matched = 1;
|
||||
if (hw->vc_slots[i].stream_count
|
||||
< hw->hw_info->max_dt_channels_per_vc) {
|
||||
list_add_tail(&stream->list, &hw->vc_slots[i].head);
|
||||
hw->vc_slots[i].stream_count++;
|
||||
hw->vc_slots[i].vc = vc;
|
||||
rc = 0;
|
||||
CAM_DBG(CAM_TPG, "vc[%d]dt[%d]=>slot[%d]", vc, stream->stream.dt, i);
|
||||
break;
|
||||
} else {
|
||||
|
||||
/**
|
||||
* already slot was assigned for this vc
|
||||
* however this slot have been filled with
|
||||
* full streams
|
||||
*/
|
||||
rc = -EINVAL;
|
||||
CAM_ERR(CAM_TPG, "vc[%d]dt[%d]=>slot[%d] is overlfown",
|
||||
vc, stream->stream.dt, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* none of the above slots matched, and now found an empty slot
|
||||
* so assigning stream to that slot
|
||||
*/
|
||||
if (hw->vc_slots[i].vc == -1) {
|
||||
list_add_tail(&stream->list, &hw->vc_slots[i].head);
|
||||
hw->vc_slots[i].stream_count++;
|
||||
hw->vc_slots[i].vc = vc;
|
||||
hw->vc_count++;
|
||||
rc = 0;
|
||||
CAM_DBG(CAM_TPG, "vc[%d]dt[%d]=>slot[%d]", vc, stream->stream.dt, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((slot_matched == 0) && (rc != 0)) {
|
||||
CAM_ERR(CAM_TPG, "No slot matched");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_reset(struct tpg_hw *hw)
|
||||
{
|
||||
int rc = 0;
|
||||
if (!hw)
|
||||
return -EINVAL;
|
||||
|
||||
/* free up the streams if any*/
|
||||
rc = tpg_hw_free_streams(hw);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Unable to free up the streams", hw->hw_idx);
|
||||
|
||||
/* disable the hw */
|
||||
if (cam_cpas_stop(hw->cpas_handle)) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] CPAS stop failed",
|
||||
hw->hw_idx);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_add_stream(
|
||||
struct tpg_hw *hw,
|
||||
struct tpg_stream_config_t *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
struct tpg_hw_stream *stream = NULL;
|
||||
if (!hw || !cmd) {
|
||||
CAM_ERR(CAM_TPG, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&hw->mutex);
|
||||
stream = kzalloc(sizeof(struct tpg_hw_stream), GFP_KERNEL);
|
||||
if (!stream) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] stream allocation failed",
|
||||
hw->hw_idx);
|
||||
mutex_unlock(&hw->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(&stream->stream,
|
||||
cmd,
|
||||
sizeof(struct tpg_stream_config_t));
|
||||
|
||||
rc = assign_vc_slot(hw, stream->stream.vc, stream);
|
||||
mutex_unlock(&hw->mutex);
|
||||
return rc;
|
||||
}
|
314
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h
Normal file
314
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h
Normal file
@@ -0,0 +1,314 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TPG_HW_H__
|
||||
#define __TPG_HW_H__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include <cam_cpas_api.h>
|
||||
#include <media/cam_sensor.h>
|
||||
#define TPG_HW_VERSION_1_0 0x10000000
|
||||
#define TPG_HW_VERSION_1_1 0x10000001
|
||||
#define TPG_HW_VERSION_1_3 0x10000003
|
||||
|
||||
|
||||
struct tpg_hw;
|
||||
|
||||
/**
|
||||
* tpg_hw_ops : tpg hw operations
|
||||
*
|
||||
* @init : tpg hw layer init
|
||||
* @start : tpg hw start stream
|
||||
* @stop : tpg hw stop stream
|
||||
* @deinit : tpg hw deinit
|
||||
* @read : tpg hw read register
|
||||
* @write : tpg hw write register
|
||||
* @process_cmd : tpg hw process command
|
||||
* @dump_status : dump any status registers
|
||||
*/
|
||||
struct tpg_hw_ops {
|
||||
int (*init)(struct tpg_hw *hw, void *data);
|
||||
int (*start)(struct tpg_hw *hw, void *data);
|
||||
int (*stop)(struct tpg_hw *hw, void *data);
|
||||
int (*deinit)(struct tpg_hw *hw, void *data);
|
||||
int (*read)(struct tpg_hw *hw, uint32_t *addr, uint32_t *val);
|
||||
int (*write)(struct tpg_hw *hw, uint32_t *addr, uint32_t *val);
|
||||
int (*process_cmd)(struct tpg_hw *hw, uint32_t cmd, void *arg);
|
||||
int (*dump_status)(struct tpg_hw *hw, void *data);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief tpg_vc_slot_info
|
||||
* @slot_id : slot id of this vc slot
|
||||
* @vc : virtual channel configured
|
||||
* @stream_count : number of streams in this slot
|
||||
* @head : head pointing all data types in with this vc
|
||||
*/
|
||||
struct tpg_vc_slot_info {
|
||||
int slot_id;
|
||||
int vc;
|
||||
int stream_count;
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpg_hw_info : tpg hw layer info
|
||||
*
|
||||
* @version: version of tpg hw
|
||||
* @max_vc_channels: max number of virtual channels supported by tpg
|
||||
* @max_dt_channels_per_vc: max dts supported in each vc
|
||||
* @ops: tpg hw operations
|
||||
*/
|
||||
struct tpg_hw_info {
|
||||
uint32_t version;
|
||||
uint32_t max_vc_channels;
|
||||
uint32_t max_dt_channels_per_vc;
|
||||
struct tpg_hw_ops *ops;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* tpg_hw_stream : tpg hw stream
|
||||
*
|
||||
* @stream : tpg stream;
|
||||
* @list : entry to tpg stream list
|
||||
*/
|
||||
struct tpg_hw_stream {
|
||||
struct tpg_stream_config_t stream;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpg_hw : tpg hw
|
||||
*
|
||||
* @hw_idx : hw id
|
||||
* @state : tpg hw state
|
||||
* @cpas_handle : handle to cpas
|
||||
* @hw_info : tp hw info
|
||||
* @soc_info : soc info
|
||||
* @mutex : lock
|
||||
* @stream_list : list of tpg stream
|
||||
* @global_config : global configuration
|
||||
*/
|
||||
struct tpg_hw {
|
||||
uint32_t hw_idx;
|
||||
uint32_t state;
|
||||
uint32_t cpas_handle;
|
||||
uint32_t vc_count;
|
||||
struct tpg_hw_info *hw_info;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct mutex mutex;
|
||||
struct tpg_vc_slot_info *vc_slots;
|
||||
struct tpg_global_config_t global_config;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpg_hw_acquire_args : tpg hw acquire arguments
|
||||
*
|
||||
* @resource_list : list of resources to acquire
|
||||
* @count : number of resources to acquire
|
||||
*/
|
||||
struct tpg_hw_acquire_args {
|
||||
/* Integer id of resources */
|
||||
uint32_t *resource_list;
|
||||
ssize_t count;
|
||||
};
|
||||
|
||||
enum tpg_hw_cmd_t {
|
||||
TPG_HW_CMD_INVALID = 0,
|
||||
TPG_HW_CMD_INIT_CONFIG,
|
||||
TPG_HW_CMD_MAX,
|
||||
};
|
||||
|
||||
#define TPG_HW_CONFIG_BASE 0x4000
|
||||
#define TPG_CONFIG_CTRL (TPG_HW_CONFIG_BASE + 0)
|
||||
#define TPG_CONFIG_VC (TPG_HW_CONFIG_BASE + 1)
|
||||
#define TPG_CONFIG_DT (TPG_HW_CONFIG_BASE + 2)
|
||||
|
||||
/* pixel bit width */
|
||||
#define PACK_8_BIT 8
|
||||
#define PACK_10_BIT 10
|
||||
#define PACK_12_BIT 12
|
||||
#define PACK_14_BIT 14
|
||||
#define PACK_16_BIT 16
|
||||
|
||||
/**
|
||||
* @vc_config_args : arguments for vc config process cmd
|
||||
*
|
||||
* @vc_slot : slot to configure this vc
|
||||
* @num_dts : number of dts in this vc
|
||||
* @stream : output stream
|
||||
*/
|
||||
struct vc_config_args {
|
||||
uint32_t vc_slot;
|
||||
uint32_t num_dts;
|
||||
struct tpg_stream_config_t *stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* dt_config_args : arguments for dt config process cmd
|
||||
*
|
||||
* @vc_slot : vc slot to configure this dt
|
||||
* @dt_slot : dt slot to configure this dt
|
||||
* @stream : stream packet to configure for this dt
|
||||
*/
|
||||
struct dt_config_args {
|
||||
uint32_t vc_slot;
|
||||
uint32_t dt_slot;
|
||||
struct tpg_stream_config_t *stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* global_config_args : tpg global config args
|
||||
*
|
||||
* @num_vcs : number of vcs to be configured
|
||||
* @globalconfig: global config cmd
|
||||
*/
|
||||
struct global_config_args {
|
||||
uint32_t num_vcs;
|
||||
struct tpg_global_config_t *globalconfig;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpg_hw_initsettings : initial configurations
|
||||
*
|
||||
* @global_config : global configuration
|
||||
* @streamconfigs : array of stream configurations
|
||||
* @num_streams : number of streams in strea config array
|
||||
*/
|
||||
struct tpg_hw_initsettings {
|
||||
struct tpg_global_config_t globalconfig;
|
||||
struct tpg_stream_config_t *streamconfigs;
|
||||
uint32_t num_streams;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief dump the tpg memory info
|
||||
*
|
||||
* @param soc_info: soc info for soc related info
|
||||
*
|
||||
* @return : 0 on succuss
|
||||
*/
|
||||
int32_t cam_tpg_mem_dmp(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/**
|
||||
* @brief dump global config command
|
||||
*
|
||||
* @param idx : hw index
|
||||
* @param global : global config command
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int dump_global_configs(int idx, struct tpg_global_config_t *global);
|
||||
|
||||
/**
|
||||
* @brief : dump stream config command
|
||||
*
|
||||
* @param hw_idx: hw index
|
||||
* @param stream_idx: stream index
|
||||
* @param stream: stream config command
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int dump_stream_configs(int hw_idx, int stream_idx, struct tpg_stream_config_t *stream);
|
||||
|
||||
/**
|
||||
* @brief : dump any hw status registers
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_dump_status(struct tpg_hw *hw);
|
||||
/**
|
||||
* @brief : start tpg hw stream
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_start(struct tpg_hw *hw);
|
||||
|
||||
/**
|
||||
* @brief : stop tpg hw stream
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_stop(struct tpg_hw *hw);
|
||||
|
||||
/**
|
||||
* @brief : tpg hw acquire
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param acquire: list of resources to acquire
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_acquire(struct tpg_hw *hw,
|
||||
struct tpg_hw_acquire_args *acquire);
|
||||
/**
|
||||
* @brief release tpg hw
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_release(struct tpg_hw *hw);
|
||||
|
||||
/**
|
||||
* @brief : configure tpg hw
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param cmd: configuration command
|
||||
* @param arg: configuration command argument
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_config(struct tpg_hw *hw, enum tpg_hw_cmd_t cmd, void *arg);
|
||||
|
||||
/**
|
||||
* @brief : tpg free streams
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_free_streams(struct tpg_hw *hw);
|
||||
|
||||
/**
|
||||
* @brief : reset the tpg hw instance
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_reset(struct tpg_hw *hw);
|
||||
|
||||
/**
|
||||
* @brief : tp hw add stream
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param cmd: tpg hw command
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_add_stream(struct tpg_hw *hw, struct tpg_stream_config_t *cmd);
|
||||
|
||||
/**
|
||||
* @brief : copy global config command
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param global: global config command
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_copy_global_config(struct tpg_hw *hw, struct tpg_global_config_t *global);
|
||||
|
||||
#endif
|
@@ -0,0 +1,283 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "tpg_hw_v_1_0.h"
|
||||
|
||||
enum tpg_hw_encode_format_t {
|
||||
RAW_8_BIT = 1,
|
||||
RAW_10_BIT,
|
||||
RAW_12_BIT,
|
||||
RAW_14_BIT,
|
||||
RAW_16_BIT
|
||||
};
|
||||
|
||||
static struct cam_tpg_ver1_reg_offset cam_tpg101_reg = {
|
||||
.tpg_hw_version = 0x0,
|
||||
.tpg_hw_status = 0x4,
|
||||
.tpg_ctrl = 0x60,
|
||||
.tpg_vc_cfg0 = 0x64,
|
||||
.tpg_vc_cfg1 = 0x68,
|
||||
.tpg_lfsr_seed = 0x6c,
|
||||
.tpg_dt_0_cfg_0 = 0x70,
|
||||
.tpg_dt_1_cfg_0 = 0x74,
|
||||
.tpg_dt_2_cfg_0 = 0x78,
|
||||
.tpg_dt_3_cfg_0 = 0x7C,
|
||||
.tpg_dt_0_cfg_1 = 0x80,
|
||||
.tpg_dt_1_cfg_1 = 0x84,
|
||||
.tpg_dt_2_cfg_1 = 0x88,
|
||||
.tpg_dt_3_cfg_1 = 0x8C,
|
||||
.tpg_dt_0_cfg_2 = 0x90,
|
||||
.tpg_dt_1_cfg_2 = 0x94,
|
||||
.tpg_dt_2_cfg_2 = 0x98,
|
||||
.tpg_dt_3_cfg_2 = 0x9C,
|
||||
.tpg_color_bar_cfg = 0xA0,
|
||||
.tpg_common_gen_cfg = 0xA4,
|
||||
.tpg_vbi_cfg = 0xA8,
|
||||
.tpg_test_bus_crtl = 0xF8,
|
||||
.tpg_spare = 0xFC,
|
||||
|
||||
/* configurations */
|
||||
.major_version = 1,
|
||||
.minor_version = 0,
|
||||
.version_incr = 0,
|
||||
.tpg_en_shift_val = 0,
|
||||
.tpg_phy_sel_shift_val = 3,
|
||||
.tpg_num_active_lines_shift = 4,
|
||||
.tpg_fe_pkt_en_shift = 2,
|
||||
.tpg_fs_pkt_en_shift = 1,
|
||||
.tpg_line_interleaving_mode_shift = 10,
|
||||
.tpg_num_dts_shift_val = 8,
|
||||
.tpg_v_blank_cnt_shift = 12,
|
||||
.tpg_dt_encode_format_shift = 16,
|
||||
.tpg_payload_mode_color = 0x8,
|
||||
.tpg_split_en_shift = 5,
|
||||
.top_mux_reg_offset = 0x1C,
|
||||
};
|
||||
|
||||
static int configure_global_configs(struct tpg_hw *hw,
|
||||
struct tpg_global_config_t *configs)
|
||||
{
|
||||
uint32_t val;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver1_reg_offset *tpg_reg = &cam_tpg101_reg;
|
||||
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
val = cam_io_r_mb(soc_info->reg_map[1].mem_base +
|
||||
tpg_reg->top_mux_reg_offset);
|
||||
val |= (1 << hw->hw_idx);
|
||||
|
||||
cam_io_w_mb(val,
|
||||
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
|
||||
CAM_INFO(CAM_ISP, "TPG:%d Set top Mux: 0x%x",
|
||||
hw->hw_idx, val);
|
||||
|
||||
val = ((4 - 1) <<
|
||||
tpg_reg->tpg_num_active_lines_shift) |
|
||||
(1 << tpg_reg->tpg_fe_pkt_en_shift) |
|
||||
(1 << tpg_reg->tpg_fs_pkt_en_shift) |
|
||||
(0 << tpg_reg->tpg_phy_sel_shift_val) |
|
||||
(1 << tpg_reg->tpg_en_shift_val);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_tpg_encode_format(int sw_encode_format)
|
||||
{
|
||||
switch (sw_encode_format) {
|
||||
case PACK_8_BIT:
|
||||
return RAW_8_BIT;
|
||||
case PACK_10_BIT:
|
||||
return RAW_10_BIT;
|
||||
case PACK_12_BIT:
|
||||
return RAW_12_BIT;
|
||||
case PACK_14_BIT:
|
||||
return RAW_14_BIT;
|
||||
case PACK_16_BIT:
|
||||
return RAW_16_BIT;
|
||||
}
|
||||
return RAW_8_BIT;
|
||||
}
|
||||
|
||||
static int configure_dt(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t vc_slot,
|
||||
uint32_t dt_slot,
|
||||
struct tpg_stream_config_t *stream)
|
||||
{
|
||||
uint32_t val;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver1_reg_offset *tpg_reg = &cam_tpg101_reg;
|
||||
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] slot(%d,%d) <= dt:%d",
|
||||
hw->hw_idx,
|
||||
vc_slot,
|
||||
dt_slot,
|
||||
stream->dt);
|
||||
/* configure width and height */
|
||||
val = (((stream->stream_dimension.width & 0xFFFF) << 16) |
|
||||
(stream->stream_dimension.height & 0x3FFF));
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_0 + 0x10 * dt_slot);
|
||||
|
||||
/* configure data type */
|
||||
cam_io_w_mb(stream->dt,
|
||||
soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_1 + 0x10 * dt_slot);
|
||||
|
||||
/* configure bpp */
|
||||
val = ((get_tpg_encode_format(stream->pixel_depth) & 0xF) <<
|
||||
tpg_reg->tpg_dt_encode_format_shift) |
|
||||
tpg_reg->tpg_payload_mode_color;
|
||||
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_2 + 0x10 * dt_slot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int configure_vc(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t vc_slot,
|
||||
int num_dts,
|
||||
struct tpg_stream_config_t *stream)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver1_reg_offset *tpg_reg = &cam_tpg101_reg;
|
||||
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
CAM_DBG(CAM_TPG, "Configureing vc : %d at the slot : %d num_dts=%d",
|
||||
stream->vc, vc_slot, num_dts);
|
||||
val = ((num_dts - 1) <<
|
||||
tpg_reg->tpg_num_dts_shift_val) | stream->vc;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0);
|
||||
|
||||
cam_io_w_mb(stream->hbi,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1);
|
||||
|
||||
val = (1 << tpg_reg->tpg_split_en_shift);
|
||||
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_common_gen_cfg);
|
||||
|
||||
cam_io_w_mb(stream->vbi,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpg_hw_v_1_0_reset(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
uint32_t val;
|
||||
struct cam_tpg_ver1_reg_offset *tpg_reg = &cam_tpg101_reg;
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_ctrl);
|
||||
|
||||
/* Reset the TOP tpg mux sel*/
|
||||
val = cam_io_r_mb(soc_info->reg_map[1].mem_base +
|
||||
tpg_reg->top_mux_reg_offset);
|
||||
val &= ~(1 << hw->hw_idx);
|
||||
|
||||
cam_io_w_mb(val,
|
||||
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
|
||||
CAM_INFO(CAM_TPG, "TPG:%d Reset Top Mux: 0x%x",
|
||||
hw->hw_idx, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_0_process_cmd(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t cmd,
|
||||
void *arg)
|
||||
{
|
||||
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch(cmd) {
|
||||
case TPG_CONFIG_VC:
|
||||
{
|
||||
struct vc_config_args *vc_config =
|
||||
(struct vc_config_args *)arg;
|
||||
|
||||
if (vc_config == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
configure_vc(hw,
|
||||
vc_config->vc_slot,
|
||||
vc_config->num_dts,
|
||||
vc_config->stream);
|
||||
}
|
||||
break;
|
||||
case TPG_CONFIG_DT:
|
||||
{
|
||||
struct dt_config_args *dt_config =
|
||||
(struct dt_config_args *)arg;
|
||||
|
||||
if (dt_config == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
configure_dt(hw,
|
||||
dt_config->vc_slot,
|
||||
dt_config->dt_slot,
|
||||
dt_config->stream);
|
||||
}
|
||||
break;
|
||||
case TPG_CONFIG_CTRL:
|
||||
configure_global_configs(hw, arg);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_0_stop(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_INFO(CAM_TPG, "TPG V1.0 HWL stop");
|
||||
tpg_hw_v_1_0_reset(hw, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_0_start(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "TPG V1.3 HWL start");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_0_init(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_INFO(CAM_TPG, "TPG V1.0 HWL init");
|
||||
tpg_hw_v_1_0_reset(hw, data);
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TPG_HW_V_1_0_H__
|
||||
#define __TPG_HW_V_1_0_H__
|
||||
|
||||
#include "../tpg_hw.h"
|
||||
|
||||
struct cam_tpg_ver1_reg_offset {
|
||||
uint32_t tpg_hw_version;
|
||||
uint32_t tpg_hw_status;
|
||||
uint32_t tpg_ctrl;
|
||||
uint32_t tpg_vc_cfg0;
|
||||
uint32_t tpg_vc_cfg1;
|
||||
uint32_t tpg_lfsr_seed;
|
||||
uint32_t tpg_dt_0_cfg_0;
|
||||
uint32_t tpg_dt_1_cfg_0;
|
||||
uint32_t tpg_dt_2_cfg_0;
|
||||
uint32_t tpg_dt_3_cfg_0;
|
||||
uint32_t tpg_dt_0_cfg_1;
|
||||
uint32_t tpg_dt_1_cfg_1;
|
||||
uint32_t tpg_dt_2_cfg_1;
|
||||
uint32_t tpg_dt_3_cfg_1;
|
||||
uint32_t tpg_dt_0_cfg_2;
|
||||
uint32_t tpg_dt_1_cfg_2;
|
||||
uint32_t tpg_dt_2_cfg_2;
|
||||
uint32_t tpg_dt_3_cfg_2;
|
||||
uint32_t tpg_color_bar_cfg;
|
||||
uint32_t tpg_common_gen_cfg;
|
||||
uint32_t tpg_vbi_cfg;
|
||||
uint32_t tpg_test_bus_crtl;
|
||||
uint32_t tpg_spare;
|
||||
|
||||
/* configurations */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
uint32_t tpg_en_shift_val;
|
||||
uint32_t tpg_phy_sel_shift_val;
|
||||
uint32_t tpg_num_active_lines_shift;
|
||||
uint32_t tpg_fe_pkt_en_shift;
|
||||
uint32_t tpg_fs_pkt_en_shift;
|
||||
uint32_t tpg_line_interleaving_mode_shift;
|
||||
uint32_t tpg_num_dts_shift_val;
|
||||
uint32_t tpg_v_blank_cnt_shift;
|
||||
uint32_t tpg_dt_encode_format_shift;
|
||||
uint32_t tpg_payload_mode_color;
|
||||
uint32_t tpg_split_en_shift;
|
||||
uint32_t top_mux_reg_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief : initialize the tpg hw v 1.0
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param data: initialize data
|
||||
*
|
||||
* @return : return 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_0_init(struct tpg_hw *hw, void *data);
|
||||
|
||||
/**
|
||||
* @brief : start tpg hw v 1.0
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param data: start argument
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_0_start(struct tpg_hw *hw, void *data);
|
||||
|
||||
/**
|
||||
* @brief : stop tpg hw
|
||||
*
|
||||
* @param hw: tpg hw instance
|
||||
* @param data: arguments to stop tpg hw 1.0
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_0_stop(struct tpg_hw *hw, void *data);
|
||||
|
||||
|
||||
#endif
|
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TPG_HW_V_1_0_DATA_H__
|
||||
#define __TPG_HW_V_1_0_DATA_H__
|
||||
|
||||
#include "../tpg_hw.h"
|
||||
#include "tpg_hw_v_1_0.h"
|
||||
|
||||
struct tpg_hw_ops tpg_hw_v_1_0_ops = {
|
||||
.start = tpg_hw_v_1_0_start,
|
||||
.stop = tpg_hw_v_1_0_stop,
|
||||
.init = tpg_hw_v_1_0_init,
|
||||
};
|
||||
|
||||
struct tpg_hw_info tpg_v_1_0_hw_info = {
|
||||
.version = TPG_HW_VERSION_1_0,
|
||||
.max_vc_channels = 2,
|
||||
.max_dt_channels_per_vc = 4,
|
||||
.ops = &tpg_hw_v_1_0_ops,
|
||||
};
|
||||
|
||||
#endif
|
@@ -0,0 +1,486 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "tpg_hw_v_1_3.h"
|
||||
|
||||
enum tpg_hw_v_1_3_encode_fomat_t {
|
||||
RAW_8_BIT = 1,
|
||||
RAW_10_BIT,
|
||||
RAW_12_BIT,
|
||||
RAW_14_BIT,
|
||||
RAW_16_BIT
|
||||
};
|
||||
|
||||
static struct cam_tpg_ver_1_3_reg_offset cam_tpg103_reg = {
|
||||
.tpg_hw_version = 0x0,
|
||||
.tpg_hw_status = 0x4,
|
||||
.tpg_ctrl = 0x64,
|
||||
.tpg_vc0_cfg0 = 0x68,
|
||||
.tpg_vc0_lfsr_seed = 0x6C,
|
||||
.tpg_vc0_hbi_cfg = 0x70,
|
||||
.tpg_vc0_vbi_cfg = 0x74,
|
||||
.tpg_vc0_color_bar_cfg = 0x78,
|
||||
.tpg_vc0_dt_0_cfg_0 = 0x7C,
|
||||
.tpg_vc0_dt_0_cfg_1 = 0x80,
|
||||
.tpg_vc0_dt_0_cfg_2 = 0x84,
|
||||
.tpg_vc0_dt_1_cfg_0 = 0x88,
|
||||
.tpg_vc0_dt_1_cfg_1 = 0x8C,
|
||||
.tpg_vc0_dt_1_cfg_2 = 0x90,
|
||||
.tpg_vc0_dt_2_cfg_0 = 0x94,
|
||||
.tpg_vc0_dt_2_cfg_1 = 0x98,
|
||||
.tpg_vc0_dt_2_cfg_2 = 0x9C,
|
||||
.tpg_vc0_dt_3_cfg_0 = 0xA0,
|
||||
.tpg_vc0_dt_3_cfg_1 = 0xA4,
|
||||
.tpg_vc0_dt_3_cfg_2 = 0xA8,
|
||||
|
||||
.tpg_vc1_cfg0 = 0xC8,
|
||||
.tpg_vc1_lfsr_seed = 0xCC,
|
||||
.tpg_vc1_hbi_cfg = 0xD0,
|
||||
.tpg_vc1_vbi_cfg = 0xD4,
|
||||
.tpg_vc1_color_bar_cfg = 0xD8,
|
||||
.tpg_vc1_dt_0_cfg_0 = 0xDC,
|
||||
.tpg_vc1_dt_0_cfg_1 = 0xE0,
|
||||
.tpg_vc1_dt_0_cfg_2 = 0xE4,
|
||||
.tpg_vc1_dt_1_cfg_0 = 0xE8,
|
||||
.tpg_vc1_dt_1_cfg_1 = 0xEC,
|
||||
.tpg_vc1_dt_1_cfg_2 = 0xF0,
|
||||
.tpg_vc1_dt_2_cfg_0 = 0xF4,
|
||||
.tpg_vc1_dt_2_cfg_1 = 0xF8,
|
||||
.tpg_vc1_dt_2_cfg_2 = 0xFC,
|
||||
.tpg_vc1_dt_3_cfg_0 = 0x100,
|
||||
.tpg_vc1_dt_3_cfg_1 = 0x104,
|
||||
.tpg_vc1_dt_3_cfg_2 = 0x108,
|
||||
|
||||
.tpg_vc2_cfg0 = 0x128,
|
||||
.tpg_vc2_lfsr_seed = 0x12C,
|
||||
.tpg_vc2_hbi_cfg = 0x130,
|
||||
.tpg_vc2_vbi_cfg = 0x134,
|
||||
.tpg_vc2_color_bar_cfg = 0x138,
|
||||
.tpg_vc2_dt_0_cfg_0 = 0x13C,
|
||||
.tpg_vc2_dt_0_cfg_1 = 0x140,
|
||||
.tpg_vc2_dt_0_cfg_2 = 0x144,
|
||||
.tpg_vc2_dt_1_cfg_0 = 0x148,
|
||||
.tpg_vc2_dt_1_cfg_1 = 0x14C,
|
||||
.tpg_vc2_dt_1_cfg_2 = 0x150,
|
||||
.tpg_vc2_dt_2_cfg_0 = 0x154,
|
||||
.tpg_vc2_dt_2_cfg_1 = 0x158,
|
||||
.tpg_vc2_dt_2_cfg_2 = 0x15C,
|
||||
.tpg_vc2_dt_3_cfg_0 = 0x160,
|
||||
.tpg_vc2_dt_3_cfg_1 = 0x164,
|
||||
.tpg_vc2_dt_3_cfg_2 = 0x168,
|
||||
|
||||
.tpg_vc3_cfg0 = 0x188,
|
||||
.tpg_vc3_lfsr_seed = 0x18C,
|
||||
.tpg_vc3_hbi_cfg = 0x190,
|
||||
.tpg_vc3_vbi_cfg = 0x194,
|
||||
.tpg_vc3_color_bar_cfg = 0x198,
|
||||
.tpg_vc3_dt_0_cfg_0 = 0x19C,
|
||||
.tpg_vc3_dt_0_cfg_1 = 0x1A0,
|
||||
.tpg_vc3_dt_0_cfg_2 = 0x1A4,
|
||||
.tpg_vc3_dt_1_cfg_0 = 0x1A8,
|
||||
.tpg_vc3_dt_1_cfg_1 = 0x1AC,
|
||||
.tpg_vc3_dt_1_cfg_2 = 0x1B0,
|
||||
.tpg_vc3_dt_2_cfg_0 = 0x1B4,
|
||||
.tpg_vc3_dt_2_cfg_1 = 0x1B8,
|
||||
.tpg_vc3_dt_2_cfg_2 = 0x1BC,
|
||||
.tpg_vc3_dt_3_cfg_0 = 0x1C0,
|
||||
.tpg_vc3_dt_3_cfg_1 = 0x1C4,
|
||||
.tpg_vc3_dt_3_cfg_2 = 0x1C8,
|
||||
.tpg_throttle = 0x1CC,
|
||||
.tpg_top_irq_status = 0x1E0,
|
||||
.tpg_top_irq_mask = 0x1E4,
|
||||
.tpg_top_irq_clear = 0x1E8,
|
||||
.tpg_top_irq_set = 0x1EC,
|
||||
.tpg_top_irq_cmd = 0x1F0,
|
||||
.tpg_top_clear = 0x1F4,
|
||||
.tpg_test_bus_crtl = 0x1F8,
|
||||
.tpg_spare = 0x1FC,
|
||||
|
||||
/* configurations */
|
||||
.major_version = 2,
|
||||
.minor_version = 0,
|
||||
.version_incr = 0,
|
||||
.tpg_en_shift_val = 0,
|
||||
.tpg_cphy_dphy_sel_shift_val = 3,
|
||||
.tpg_num_active_lanes_shift = 4,
|
||||
.tpg_fe_pkt_en_shift = 2,
|
||||
.tpg_fs_pkt_en_shift = 1,
|
||||
.tpg_line_interleaving_mode_shift = 10,
|
||||
.tpg_num_frames_shift_val = 16,
|
||||
.tpg_num_dts_shift_val = 8,
|
||||
.tpg_v_blank_cnt_shift = 12,
|
||||
.tpg_dt_encode_format_shift = 20,
|
||||
.tpg_payload_mode_color = 0x8,
|
||||
.tpg_split_en_shift = 4,
|
||||
.top_mux_reg_offset = 0x1C,
|
||||
.tpg_vc_dt_pattern_id_shift = 6,
|
||||
.tpg_num_active_vcs_shift = 30,
|
||||
.tpg_color_bar_qcfa_en_shift = 3,
|
||||
.tpg_color_bar_qcfa_rotate_period_shift = 8,
|
||||
};
|
||||
|
||||
#define FRAME_INTERLEAVE 0x0
|
||||
#define LINE_INTERLEAVE 0x1
|
||||
#define SHDR_INTERLEAVE 0x2
|
||||
#define SPARSE_PD_INTERLEAVE 0x3
|
||||
static int get_tpg_vc_dt_pattern_id(
|
||||
enum tpg_interleaving_format_t vc_dt_pattern)
|
||||
{
|
||||
switch (vc_dt_pattern) {
|
||||
case TPG_INTERLEAVING_FORMAT_INVALID:
|
||||
case TPG_INTERLEAVING_FORMAT_MAX:
|
||||
case TPG_INTERLEAVING_FORMAT_FRAME:
|
||||
return FRAME_INTERLEAVE;
|
||||
case TPG_INTERLEAVING_FORMAT_LINE:
|
||||
return LINE_INTERLEAVE;
|
||||
case TPG_INTERLEAVING_FORMAT_SHDR:
|
||||
return SHDR_INTERLEAVE;
|
||||
case TPG_INTERLEAVING_FORMAT_SPARSE_PD:
|
||||
return SPARSE_PD_INTERLEAVE;
|
||||
|
||||
}
|
||||
return FRAME_INTERLEAVE;
|
||||
}
|
||||
|
||||
static int configure_global_configs(
|
||||
struct tpg_hw *hw,
|
||||
int num_vcs,
|
||||
struct tpg_global_config_t *configs)
|
||||
{
|
||||
uint32_t val, phy_type = 0;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver_1_3_reg_offset *tpg_reg = &cam_tpg103_reg;
|
||||
|
||||
if (!hw) {
|
||||
CAM_ERR(CAM_TPG, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
if (configs->phy_type == TPG_PHY_TYPE_CPHY)
|
||||
phy_type = 1;
|
||||
|
||||
if (num_vcs <= 0) {
|
||||
CAM_ERR(CAM_TPG, "Invalid vc count");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = configs->skip_pattern;
|
||||
cam_io_w_mb(val,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_throttle);
|
||||
CAM_DBG(CAM_TPG, "tpg[%d] throttle=0x%x", hw->hw_idx, val);
|
||||
|
||||
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_irq_mask);
|
||||
|
||||
|
||||
val = ((num_vcs - 1) <<
|
||||
(tpg_reg->tpg_num_active_vcs_shift) |
|
||||
(configs->lane_count - 1) <<
|
||||
tpg_reg->tpg_num_active_lanes_shift) |
|
||||
get_tpg_vc_dt_pattern_id(configs->interleaving_format) <<
|
||||
(tpg_reg->tpg_vc_dt_pattern_id_shift) |
|
||||
(phy_type << tpg_reg->tpg_cphy_dphy_sel_shift_val) |
|
||||
(1 << tpg_reg->tpg_en_shift_val);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
|
||||
CAM_DBG(CAM_TPG, "tpg[%d] tpg_ctrl=0x%x", hw->hw_idx, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_tpg_encode_format(int sw_encode_format)
|
||||
{
|
||||
switch (sw_encode_format) {
|
||||
case PACK_8_BIT:
|
||||
return RAW_8_BIT;
|
||||
case PACK_10_BIT:
|
||||
return RAW_10_BIT;
|
||||
case PACK_12_BIT:
|
||||
return RAW_12_BIT;
|
||||
case PACK_14_BIT:
|
||||
return RAW_14_BIT;
|
||||
case PACK_16_BIT:
|
||||
return RAW_16_BIT;
|
||||
}
|
||||
return RAW_8_BIT;
|
||||
}
|
||||
|
||||
#define INCREMENTING 0x0
|
||||
#define ALTERNATING_55_AA 0x1
|
||||
#define RANDOM 0x4
|
||||
#define USER_SPECIFIED 0x5
|
||||
#define COLOR_BARS 0x8
|
||||
|
||||
static int get_tpg_payload_mode(enum tpg_pattern_t pattern)
|
||||
{
|
||||
switch (pattern) {
|
||||
case TPG_PATTERN_INVALID:
|
||||
case TPG_PATTERN_REAL_IMAGE:
|
||||
case TPG_PATTERN_COLOR_BAR:
|
||||
return COLOR_BARS;
|
||||
case TPG_PATTERN_RANDOM_PIXL:
|
||||
case TPG_PATTERN_RANDOM_INCREMENTING_PIXEL:
|
||||
return RANDOM;
|
||||
case TPG_PATTERN_ALTERNATING_55_AA:
|
||||
return ALTERNATING_55_AA;
|
||||
case TPG_PATTERN_ALTERNATING_USER_DEFINED:
|
||||
return USER_SPECIFIED;
|
||||
default:
|
||||
return COLOR_BARS;
|
||||
}
|
||||
return COLOR_BARS;
|
||||
}
|
||||
|
||||
static int configure_dt(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t vc_slot,
|
||||
uint32_t dt_slot,
|
||||
struct tpg_stream_config_t *stream)
|
||||
{
|
||||
uint32_t val;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver_1_3_reg_offset *tpg_reg = &cam_tpg103_reg;
|
||||
if (!hw) {
|
||||
CAM_ERR(CAM_TPG, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] slot(%d,%d) <= dt:%d",
|
||||
hw->hw_idx,
|
||||
vc_slot,
|
||||
dt_slot,
|
||||
stream->dt);
|
||||
|
||||
val = (((stream->stream_dimension.width & 0xFFFF) << 16) |
|
||||
(stream->stream_dimension.height & 0xFFFF));
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_dt_0_cfg_0 +
|
||||
(0x60 * vc_slot) + (dt_slot * 0x0c));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_0=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, dt_slot, val);
|
||||
|
||||
cam_io_w_mb(stream->dt,
|
||||
soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_dt_0_cfg_1 +
|
||||
(0x60 * vc_slot) + (dt_slot * 0x0c));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_1=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, dt_slot, stream->dt);
|
||||
|
||||
val = ((get_tpg_encode_format(stream->pixel_depth) & 0xF) <<
|
||||
tpg_reg->tpg_dt_encode_format_shift) |
|
||||
get_tpg_payload_mode(stream->pattern_type);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_dt_0_cfg_2 +
|
||||
(0x60 * vc_slot) + (dt_slot * 0x0c));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_dt%d_cfg_2=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, dt_slot, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int configure_vc(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t vc_slot,
|
||||
int num_dts,
|
||||
struct tpg_stream_config_t *stream)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_tpg_ver_1_3_reg_offset *tpg_reg = &cam_tpg103_reg;
|
||||
if (!hw) {
|
||||
CAM_ERR(CAM_TPG, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = hw->soc_info;
|
||||
/* Use CFA pattern here */
|
||||
if (stream->output_format == TPG_IMAGE_FORMAT_QCFA)
|
||||
val |= (1 << tpg_reg->tpg_color_bar_qcfa_en_shift);
|
||||
|
||||
if (stream->cb_mode == TPG_COLOR_BAR_MODE_SPLIT)
|
||||
val |= (1 << tpg_reg->tpg_split_en_shift);
|
||||
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] period: %d", hw->hw_idx, stream->rotate_period);
|
||||
val |= ((stream->rotate_period & 0x3F) <<
|
||||
tpg_reg->tpg_color_bar_qcfa_rotate_period_shift);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_color_bar_cfg + (0x60 * vc_slot));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_color_bar_cfg=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, val);
|
||||
|
||||
val = stream->hbi;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_hbi_cfg + (0x60 * vc_slot));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_hbi_cfg=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, val);
|
||||
|
||||
val = stream->vbi;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_vbi_cfg + (0x60 * vc_slot));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_vbi_cgf=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, val);
|
||||
|
||||
cam_io_w_mb(0x12345678,
|
||||
soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_lfsr_seed + (0x60 * vc_slot));
|
||||
|
||||
val = ((0 << tpg_reg->tpg_num_frames_shift_val) |
|
||||
((num_dts-1) << tpg_reg->tpg_num_dts_shift_val) |
|
||||
stream->vc);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_vc0_cfg0 + (0x60 * vc_slot));
|
||||
CAM_DBG(CAM_TPG, "TPG[%d] vc%d_cfg0=0x%x",
|
||||
hw->hw_idx,
|
||||
vc_slot, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpg_hw_v_1_3_reset(
|
||||
struct tpg_hw *hw, void *data)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
uint32_t val;
|
||||
struct cam_tpg_ver_1_3_reg_offset *tpg_reg = &cam_tpg103_reg;
|
||||
if (!hw) {
|
||||
CAM_ERR(CAM_TPG, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = hw->soc_info;
|
||||
|
||||
/* Clear out tpg_ctrl and irqs before reset */
|
||||
cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
|
||||
|
||||
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_irq_mask);
|
||||
|
||||
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_irq_clear);
|
||||
|
||||
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_irq_cmd);
|
||||
|
||||
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_clear);
|
||||
|
||||
/* Read the version */
|
||||
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_hw_version);
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] TPG HW version: 0x%x started",
|
||||
hw->hw_idx, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_3_process_cmd(
|
||||
struct tpg_hw *hw,
|
||||
uint32_t cmd,
|
||||
void *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
if (hw == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch(cmd) {
|
||||
case TPG_CONFIG_VC:
|
||||
{
|
||||
struct vc_config_args *vc_config =
|
||||
(struct vc_config_args *)arg;
|
||||
|
||||
if (vc_config == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = configure_vc(hw,
|
||||
vc_config->vc_slot,
|
||||
vc_config->num_dts,
|
||||
vc_config->stream);
|
||||
}
|
||||
break;
|
||||
case TPG_CONFIG_DT:
|
||||
{
|
||||
struct dt_config_args *dt_config =
|
||||
(struct dt_config_args *)arg;
|
||||
|
||||
if (dt_config == NULL) {
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = configure_dt(hw,
|
||||
dt_config->vc_slot,
|
||||
dt_config->dt_slot,
|
||||
dt_config->stream);
|
||||
}
|
||||
break;
|
||||
case TPG_CONFIG_CTRL:
|
||||
{
|
||||
struct global_config_args *global_args =
|
||||
(struct global_config_args *)arg;
|
||||
rc = configure_global_configs(hw,
|
||||
global_args->num_vcs,
|
||||
global_args->globalconfig);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_TPG, "invalid argument");
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_3_start(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "TPG V1.3 HWL start");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_3_stop(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "TPG V1.3 HWL stop");
|
||||
tpg_hw_v_1_3_reset(hw, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_3_dump_status(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
uint32_t val;
|
||||
struct cam_tpg_ver_1_3_reg_offset *tpg_reg = &cam_tpg103_reg;
|
||||
|
||||
if (!hw) {
|
||||
CAM_ERR(CAM_TPG, "invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = hw->soc_info;
|
||||
CAM_DBG(CAM_TPG, "TPG V1.3 HWL status dump");
|
||||
/* Read the version */
|
||||
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_hw_status);
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] TPG HW status: 0x%x started",
|
||||
hw->hw_idx, val);
|
||||
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_top_irq_status);
|
||||
CAM_INFO(CAM_TPG, "TPG[%d] TPG HW irq status: 0x%x started",
|
||||
hw->hw_idx, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpg_hw_v_1_3_init(struct tpg_hw *hw, void *data)
|
||||
{
|
||||
CAM_DBG(CAM_TPG, "TPG V1.3 HWL init");
|
||||
tpg_hw_v_1_3_reset(hw, data);
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,172 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TPG_HW_V_1_3_H__
|
||||
#define __TPG_HW_V_1_3_H__
|
||||
|
||||
#include "../tpg_hw.h"
|
||||
|
||||
struct cam_tpg_ver_1_3_reg_offset {
|
||||
uint32_t tpg_hw_version;
|
||||
uint32_t tpg_hw_status;
|
||||
uint32_t tpg_ctrl;
|
||||
uint32_t tpg_vc0_cfg0;
|
||||
uint32_t tpg_vc0_lfsr_seed;
|
||||
uint32_t tpg_vc0_hbi_cfg;
|
||||
uint32_t tpg_vc0_vbi_cfg;
|
||||
uint32_t tpg_vc0_color_bar_cfg;
|
||||
uint32_t tpg_vc0_dt_0_cfg_0;
|
||||
uint32_t tpg_vc0_dt_0_cfg_1;
|
||||
uint32_t tpg_vc0_dt_0_cfg_2;
|
||||
uint32_t tpg_vc0_dt_1_cfg_0;
|
||||
uint32_t tpg_vc0_dt_1_cfg_1;
|
||||
uint32_t tpg_vc0_dt_1_cfg_2;
|
||||
uint32_t tpg_vc0_dt_2_cfg_0;
|
||||
uint32_t tpg_vc0_dt_2_cfg_1;
|
||||
uint32_t tpg_vc0_dt_2_cfg_2;
|
||||
uint32_t tpg_vc0_dt_3_cfg_0;
|
||||
uint32_t tpg_vc0_dt_3_cfg_1;
|
||||
uint32_t tpg_vc0_dt_3_cfg_2;
|
||||
|
||||
uint32_t tpg_vc1_cfg0;
|
||||
uint32_t tpg_vc1_lfsr_seed;
|
||||
uint32_t tpg_vc1_hbi_cfg;
|
||||
uint32_t tpg_vc1_vbi_cfg;
|
||||
uint32_t tpg_vc1_color_bar_cfg;
|
||||
uint32_t tpg_vc1_dt_0_cfg_0;
|
||||
uint32_t tpg_vc1_dt_0_cfg_1;
|
||||
uint32_t tpg_vc1_dt_0_cfg_2;
|
||||
uint32_t tpg_vc1_dt_1_cfg_0;
|
||||
uint32_t tpg_vc1_dt_1_cfg_1;
|
||||
uint32_t tpg_vc1_dt_1_cfg_2;
|
||||
uint32_t tpg_vc1_dt_2_cfg_0;
|
||||
uint32_t tpg_vc1_dt_2_cfg_1;
|
||||
uint32_t tpg_vc1_dt_2_cfg_2;
|
||||
uint32_t tpg_vc1_dt_3_cfg_0;
|
||||
uint32_t tpg_vc1_dt_3_cfg_1;
|
||||
uint32_t tpg_vc1_dt_3_cfg_2;
|
||||
|
||||
uint32_t tpg_vc2_cfg0;
|
||||
uint32_t tpg_vc2_lfsr_seed;
|
||||
uint32_t tpg_vc2_hbi_cfg;
|
||||
uint32_t tpg_vc2_vbi_cfg;
|
||||
uint32_t tpg_vc2_color_bar_cfg;
|
||||
uint32_t tpg_vc2_dt_0_cfg_0;
|
||||
uint32_t tpg_vc2_dt_0_cfg_1;
|
||||
uint32_t tpg_vc2_dt_0_cfg_2;
|
||||
uint32_t tpg_vc2_dt_1_cfg_0;
|
||||
uint32_t tpg_vc2_dt_1_cfg_1;
|
||||
uint32_t tpg_vc2_dt_1_cfg_2;
|
||||
uint32_t tpg_vc2_dt_2_cfg_0;
|
||||
uint32_t tpg_vc2_dt_2_cfg_1;
|
||||
uint32_t tpg_vc2_dt_2_cfg_2;
|
||||
uint32_t tpg_vc2_dt_3_cfg_0;
|
||||
uint32_t tpg_vc2_dt_3_cfg_1;
|
||||
uint32_t tpg_vc2_dt_3_cfg_2;
|
||||
|
||||
uint32_t tpg_vc3_cfg0;
|
||||
uint32_t tpg_vc3_lfsr_seed;
|
||||
uint32_t tpg_vc3_hbi_cfg;
|
||||
uint32_t tpg_vc3_vbi_cfg;
|
||||
uint32_t tpg_vc3_color_bar_cfg;
|
||||
uint32_t tpg_vc3_dt_0_cfg_0;
|
||||
uint32_t tpg_vc3_dt_0_cfg_1;
|
||||
uint32_t tpg_vc3_dt_0_cfg_2;
|
||||
uint32_t tpg_vc3_dt_1_cfg_0;
|
||||
uint32_t tpg_vc3_dt_1_cfg_1;
|
||||
uint32_t tpg_vc3_dt_1_cfg_2;
|
||||
uint32_t tpg_vc3_dt_2_cfg_0;
|
||||
uint32_t tpg_vc3_dt_2_cfg_1;
|
||||
uint32_t tpg_vc3_dt_2_cfg_2;
|
||||
uint32_t tpg_vc3_dt_3_cfg_0;
|
||||
uint32_t tpg_vc3_dt_3_cfg_1;
|
||||
uint32_t tpg_vc3_dt_3_cfg_2;
|
||||
uint32_t tpg_throttle;
|
||||
uint32_t tpg_top_irq_status;
|
||||
uint32_t tpg_top_irq_mask;
|
||||
uint32_t tpg_top_irq_clear;
|
||||
uint32_t tpg_top_irq_set;
|
||||
uint32_t tpg_top_irq_cmd;
|
||||
uint32_t tpg_top_clear;
|
||||
uint32_t tpg_test_bus_crtl;
|
||||
uint32_t tpg_spare;
|
||||
|
||||
/* configurations */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
uint32_t tpg_en_shift_val;
|
||||
uint32_t tpg_cphy_dphy_sel_shift_val;
|
||||
uint32_t tpg_num_active_lanes_shift;
|
||||
uint32_t tpg_fe_pkt_en_shift;
|
||||
uint32_t tpg_fs_pkt_en_shift;
|
||||
uint32_t tpg_line_interleaving_mode_shift;
|
||||
uint32_t tpg_num_frames_shift_val;
|
||||
uint32_t tpg_num_dts_shift_val;
|
||||
uint32_t tpg_v_blank_cnt_shift;
|
||||
uint32_t tpg_dt_encode_format_shift;
|
||||
uint32_t tpg_payload_mode_color;
|
||||
uint32_t tpg_split_en_shift;
|
||||
uint32_t top_mux_reg_offset;
|
||||
uint32_t tpg_vc_dt_pattern_id_shift;
|
||||
uint32_t tpg_num_active_vcs_shift;
|
||||
uint32_t tpg_color_bar_qcfa_en_shift;
|
||||
uint32_t tpg_color_bar_qcfa_rotate_period_shift;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief initialize the tpg hw instance
|
||||
*
|
||||
* @param hw : tpg hw instance
|
||||
* @param data : argument for initialize
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_3_init(struct tpg_hw *hw, void *data);
|
||||
|
||||
/**
|
||||
* @brief start tpg hw
|
||||
*
|
||||
* @param hw : tpg hw instance
|
||||
* @param data : tpg hw instance data
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_3_start(struct tpg_hw *hw, void *data);
|
||||
|
||||
/**
|
||||
* @brief stop tpg hw
|
||||
*
|
||||
* @param hw : tpg hw instance
|
||||
* @param data : argument for tpg hw stop
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_3_stop(struct tpg_hw *hw, void *data);
|
||||
|
||||
/**
|
||||
* @brief process a command send from hw layer
|
||||
*
|
||||
* @param hw : tpg hw instance
|
||||
* @param cmd : command to process
|
||||
* @param arg : argument corresponding to command
|
||||
*
|
||||
* @return : 0 on success
|
||||
*/
|
||||
int tpg_hw_v_1_3_process_cmd(struct tpg_hw *hw,
|
||||
uint32_t cmd, void *arg);
|
||||
|
||||
/**
|
||||
* @brief dump hw status registers
|
||||
*
|
||||
* @param hw : tpg hw instance
|
||||
* @param data : argument for status dump
|
||||
*
|
||||
* @return : 0 on sucdess
|
||||
*/
|
||||
int tpg_hw_v_1_3_dump_status(struct tpg_hw *hw, void *data);
|
||||
|
||||
#endif
|
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TPG_HW_V_1_3_DATA_H__
|
||||
#define __TPG_HW_V_1_3_DATA_H__
|
||||
|
||||
#include "../tpg_hw.h"
|
||||
#include "tpg_hw_v_1_3.h"
|
||||
|
||||
struct tpg_hw_ops tpg_hw_v_1_3_ops = {
|
||||
.start = tpg_hw_v_1_3_start,
|
||||
.stop = tpg_hw_v_1_3_stop,
|
||||
.init = tpg_hw_v_1_3_init,
|
||||
.process_cmd = tpg_hw_v_1_3_process_cmd,
|
||||
.dump_status = tpg_hw_v_1_3_dump_status,
|
||||
};
|
||||
|
||||
struct tpg_hw_info tpg_v_1_3_hw_info = {
|
||||
.version = TPG_HW_VERSION_1_3,
|
||||
.max_vc_channels = 4,
|
||||
.max_dt_channels_per_vc = 4,
|
||||
.ops = &tpg_hw_v_1_3_ops,
|
||||
};
|
||||
|
||||
#endif
|
@@ -227,6 +227,9 @@ const char *cam_get_module_name(unsigned long long module_id)
|
||||
case CAM_PRESIL_CORE:
|
||||
name = "CAM-CORE-PRESIL";
|
||||
break;
|
||||
case CAM_TPG:
|
||||
name = "CAM-TPG";
|
||||
break;
|
||||
default:
|
||||
name = "CAM";
|
||||
break;
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#define CAM_SFE BIT_ULL(30)
|
||||
#define CAM_CRE BIT_ULL(31)
|
||||
#define CAM_PRESIL_CORE BIT_ULL(32)
|
||||
#define CAM_TPG BIT_ULL(33)
|
||||
|
||||
/* Log level types */
|
||||
#define CAM_TYPE_TRACE (1 << 0)
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "cam_csiphy_dev.h"
|
||||
#include "cam_eeprom_dev.h"
|
||||
#include "cam_ois_dev.h"
|
||||
#include "cam_tpg_dev.h"
|
||||
|
||||
#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \
|
||||
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
|
||||
@@ -105,6 +106,7 @@ static const struct camera_submodule_component camera_sensor[] = {
|
||||
{&cam_res_mgr_init, &cam_res_mgr_exit},
|
||||
{&cam_cci_init_module, &cam_cci_exit_module},
|
||||
{&cam_csiphy_init_module, &cam_csiphy_exit_module},
|
||||
{&cam_tpg_init_module, &cam_tpg_exit_module},
|
||||
{&cam_actuator_driver_init, &cam_actuator_driver_exit},
|
||||
{&cam_sensor_driver_init, &cam_sensor_driver_exit},
|
||||
{&cam_eeprom_driver_init, &cam_eeprom_driver_exit},
|
||||
|
@@ -34,6 +34,7 @@ extern struct platform_driver cam_actuator_platform_driver;
|
||||
extern struct platform_driver cam_sensor_platform_driver;
|
||||
extern struct platform_driver cam_eeprom_platform_driver;
|
||||
extern struct platform_driver cam_ois_platform_driver;
|
||||
extern struct platform_driver cam_tpg_driver;
|
||||
#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \
|
||||
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
|
||||
extern struct platform_driver cam_flash_platform_driver;
|
||||
@@ -104,6 +105,7 @@ static struct platform_driver *const cam_component_drivers[] = {
|
||||
&cam_sensor_platform_driver,
|
||||
&cam_eeprom_platform_driver,
|
||||
&cam_ois_platform_driver,
|
||||
&cam_tpg_driver,
|
||||
#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \
|
||||
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
|
||||
&cam_flash_platform_driver,
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#define CAM_OPE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 15)
|
||||
#define CAM_TFE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 16)
|
||||
#define CAM_CRE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 17)
|
||||
#define CAM_TPG_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 18)
|
||||
|
||||
/* cam_req_mgr hdl info */
|
||||
#define CAM_REQ_MGR_HDL_IDX_POS 8
|
||||
|
@@ -78,6 +78,13 @@ enum camera_sensor_wait_op_code {
|
||||
CAMERA_SENSOR_WAIT_OP_MAX,
|
||||
};
|
||||
|
||||
enum cam_tpg_packet_opcodes {
|
||||
CAM_TPG_PACKET_OPCODE_INVALID = 0,
|
||||
CAM_TPG_PACKET_OPCODE_INITIAL_CONFIG,
|
||||
CAM_TPG_PACKET_OPCODE_NOP,
|
||||
CAM_TPG_PACKET_OPCODE_MAX,
|
||||
};
|
||||
|
||||
enum cam_sensor_packet_opcodes {
|
||||
CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON,
|
||||
CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE,
|
||||
@@ -91,6 +98,78 @@ enum cam_sensor_packet_opcodes {
|
||||
CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127
|
||||
};
|
||||
|
||||
enum tpg_command_type_t {
|
||||
TPG_CMD_TYPE_INVALID = 0,
|
||||
TPG_CMD_TYPE_GLOBAL_CONFIG,
|
||||
TPG_CMD_TYPE_STREAM_CONFIG,
|
||||
TPG_CMD_TYPE_ILLUMINATION_CONFIG,
|
||||
TPG_CMD_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum tpg_pattern_t {
|
||||
TPG_PATTERN_INVALID = 0,
|
||||
TPG_PATTERN_REAL_IMAGE,
|
||||
TPG_PATTERN_RANDOM_PIXL,
|
||||
TPG_PATTERN_RANDOM_INCREMENTING_PIXEL,
|
||||
TPG_PATTERN_COLOR_BAR,
|
||||
TPG_PATTERN_ALTERNATING_55_AA,
|
||||
TPG_PATTERN_ALTERNATING_USER_DEFINED,
|
||||
TPG_PATTERN_MAX,
|
||||
};
|
||||
|
||||
enum tpg_color_bar_mode_t {
|
||||
TPG_COLOR_BAR_MODE_INVALID = 0,
|
||||
TPG_COLOR_BAR_MODE_NORMAL,
|
||||
TPG_COLOR_BAR_MODE_SPLIT,
|
||||
TPG_COLOR_BAR_MODE_ROTATING,
|
||||
TPG_COLOR_BAR_MODE_MAX,
|
||||
};
|
||||
|
||||
enum tpg_image_format_t {
|
||||
TPG_IMAGE_FORMAT_INVALID = 0,
|
||||
TPG_IMAGE_FORMAT_BAYER,
|
||||
TPG_IMAGE_FORMAT_QCFA,
|
||||
TPG_IMAGE_FORMAT_YUV,
|
||||
TPG_IMAGE_FORMAT_JPEG,
|
||||
TPG_IMAGE_FORMAT_MAX,
|
||||
};
|
||||
|
||||
enum tpg_phy_type_t {
|
||||
TPG_PHY_TYPE_INVALID = 0,
|
||||
TPG_PHY_TYPE_DPHY,
|
||||
TPG_PHY_TYPE_CPHY,
|
||||
TPG_PHY_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum tpg_interleaving_format_t {
|
||||
TPG_INTERLEAVING_FORMAT_INVALID = 0,
|
||||
TPG_INTERLEAVING_FORMAT_FRAME,
|
||||
TPG_INTERLEAVING_FORMAT_LINE,
|
||||
TPG_INTERLEAVING_FORMAT_SHDR,
|
||||
TPG_INTERLEAVING_FORMAT_SPARSE_PD,
|
||||
TPG_INTERLEAVING_FORMAT_MAX,
|
||||
};
|
||||
|
||||
enum tpg_shutter_t {
|
||||
TPG_SHUTTER_TYPE_INVALID = 0,
|
||||
TPG_SHUTTER_TYPE_ROLLING,
|
||||
TPG_SHUTTER_TYPE_GLOBAL,
|
||||
TPG_SHUTTER_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum tpg_stream_t {
|
||||
TPG_STREAM_TYPE_INVALID = 0,
|
||||
TPG_STREAM_TYPE_IMAGE,
|
||||
TPG_STREAM_TYPE_PDAF,
|
||||
TPG_STREAM_TYPE_META,
|
||||
TPG_STREAM_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum tpg_cfa_arrangement_t {
|
||||
TPG_CFA_ARRANGEMENT_TYPE_INVALID = 0,
|
||||
TPG_CFA_ARRANGEMENT_TYPE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_sensor_query_cap - capabilities info for sensor
|
||||
*
|
||||
@@ -168,6 +247,24 @@ struct cam_ois_query_cap_t {
|
||||
__u16 reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct cam_tpg_query_cap - capabilities info for tpg
|
||||
*
|
||||
* @slot_info : Indicates about the slotId or cell Index
|
||||
* @version : TPG version , in msb
|
||||
* @reserved : Reserved for future Use
|
||||
* @secure_camera : Camera is in secure/Non-secure mode
|
||||
* @csiphy_slot_id : CSIphy slot id which connected to sensor
|
||||
*/
|
||||
struct cam_tpg_query_cap {
|
||||
__u32 slot_info;
|
||||
__u32 version;
|
||||
__u32 secure_camera;
|
||||
__u32 csiphy_slot_id;
|
||||
__u32 reserved[2];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/**
|
||||
* struct cam_cmd_i2c_info - Contains slave I2C related info
|
||||
*
|
||||
@@ -486,6 +583,23 @@ struct cam_sensor_acquire_dev {
|
||||
__u64 info_handle;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* cam_tpg_acquire_dev : Updates tpg acuire cmd
|
||||
* @device_handle : Updates device handle
|
||||
* @session_handle : Session handle for acquiring device
|
||||
* @handle_type : Resource handle type
|
||||
* @reserved
|
||||
* @info_handle : Handle to additional info
|
||||
* needed for sensor sub modules
|
||||
*/
|
||||
struct cam_tpg_acquire_dev {
|
||||
__u32 session_handle;
|
||||
__u32 device_handle;
|
||||
__u32 handle_type;
|
||||
__u32 reserved;
|
||||
__u64 info_handle;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* cam_sensor_streamon_dev : StreamOn command for the sensor
|
||||
* @session_handle : Session handle for acquiring device
|
||||
@@ -503,6 +617,131 @@ struct cam_sensor_streamon_dev {
|
||||
__u64 info_handle;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/**
|
||||
* stream_dimension : Stream dimension
|
||||
*
|
||||
* @left : left pixel locaiton of stream
|
||||
* @top : top pixel location of stream
|
||||
* @width : width of the image stream
|
||||
* @height : Height of the image stream
|
||||
*/
|
||||
struct stream_dimension {
|
||||
uint32_t left;
|
||||
uint32_t top;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
/**
|
||||
* tpg_command_header_t : tpg command common header
|
||||
*
|
||||
* @cmd_type : command type
|
||||
* @size : size of the command including header
|
||||
* @cmd_version : version of the command associated
|
||||
*/
|
||||
struct tpg_command_header_t {
|
||||
__u32 cmd_type;
|
||||
ssize_t size;
|
||||
uint32_t cmd_version;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* tpg_global_config_t : global configuration command structure
|
||||
*
|
||||
* @header : common header
|
||||
* @phy_type : phy type , cpy , dphy
|
||||
* @lane_count : number of lanes used
|
||||
* @interleaving_format : interleaving format used
|
||||
* @phy_mode : phy mode of operation
|
||||
* @shutter_type : shutter type
|
||||
* @mode : if any specific mode needs to configured
|
||||
* @hbi : horizontal blanking intervel
|
||||
* @vbi : vertical blanking intervel
|
||||
* @skip_pattern : frame skip pattern
|
||||
* @tpg_clock : tpg clock
|
||||
* @reserved : reserved for future use
|
||||
*/
|
||||
struct tpg_global_config_t {
|
||||
struct tpg_command_header_t header;
|
||||
enum tpg_phy_type_t phy_type;
|
||||
uint8_t lane_count;
|
||||
enum tpg_interleaving_format_t interleaving_format;
|
||||
uint8_t phy_mode;
|
||||
enum tpg_shutter_t shutter_type;
|
||||
uint32_t mode;
|
||||
uint32_t hbi;
|
||||
uint32_t vbi;
|
||||
uint32_t skip_pattern;
|
||||
uint64_t tpg_clock;
|
||||
uint32_t reserved[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* tpg_stream_config_t : stream configuration command
|
||||
*
|
||||
* @header: common tpg command header
|
||||
* @pattern_type : tpg pattern type used in this stream
|
||||
* @cb_mode : tpg color bar mode used in this stream
|
||||
* @frame_count : frame count in case of trigger burst mode
|
||||
* @stream_type : type of stream like image pdaf etc
|
||||
* @stream_dimension : Dimension of the stream
|
||||
* @pixel_depth : bits per each pixel
|
||||
* @cfa_arrangement : color filter arragement
|
||||
* @output_format : output image format
|
||||
* @hbi : horizontal blanking intervel
|
||||
* @vbi : vertical blanking intervel
|
||||
* @vc : virtual channel of this stream
|
||||
* @dt : data type of this stream
|
||||
* @skip_pattern : skip pattern for this stream
|
||||
* @reserved : reserved for future use
|
||||
*/
|
||||
struct tpg_stream_config_t {
|
||||
struct tpg_command_header_t header;
|
||||
enum tpg_pattern_t pattern_type;
|
||||
enum tpg_color_bar_mode_t cb_mode;
|
||||
uint32_t frame_count;
|
||||
enum tpg_stream_t stream_type;
|
||||
struct stream_dimension stream_dimension;
|
||||
uint8_t pixel_depth;
|
||||
enum tpg_cfa_arrangement_t cfa_arrangement;
|
||||
enum tpg_image_format_t output_format;
|
||||
uint32_t hbi;
|
||||
uint32_t vbi;
|
||||
uint16_t vc;
|
||||
uint16_t dt;
|
||||
uint32_t skip_pattern;
|
||||
uint32_t rotate_period;
|
||||
uint32_t reserved[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* tpg_illumination_control : illumianation control command
|
||||
*
|
||||
* @header : common header for tpg command
|
||||
* @vc : virtual channel to identify the stream
|
||||
* @dt : dt to identify the stream
|
||||
* @exposure_short : short exposure time
|
||||
* @exposure_mid : mid exposure time
|
||||
* @exposure_long : long exposure time
|
||||
* @r_gain : r channel gain
|
||||
* @g_gain : g channel gain
|
||||
* @b_gain : b channel gain
|
||||
* @reserved : reserved for future use
|
||||
*/
|
||||
struct tpg_illumination_control {
|
||||
struct tpg_command_header_t header;
|
||||
uint16_t vc;
|
||||
uint16_t dt;
|
||||
uint32_t exposure_short;
|
||||
uint32_t exposure_mid;
|
||||
uint32_t exposure_long;
|
||||
uint16_t r_gain;
|
||||
uint16_t g_gain;
|
||||
uint16_t b_gain;
|
||||
uint32_t reserved[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct cam_flash_init : Init command for the flash
|
||||
* @flash_type : flash hw type
|
||||
|
Reference in New Issue
Block a user