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

Commit 26d678ce authored by Maheshwar Ajja's avatar Maheshwar Ajja
Browse files

msm: vidc: Computer Vision Program (CVP) driver implementation



Computer Vision Program algorithms are required to improve 
video usecases quality. Userspace clients will use the driver
to utilize the CVP features supported by video hardware.
The driver implementation contains below functionalities

- CVP Session initialization/de-initialization
- HFI (Host Firmware Interface) Queue implementation for DSP
- Scale clocks and vote buses
- Register / Unregister buffers

Change-Id: If851401724cf15e455e17ad8a44742a01e6a87e4
Signed-off-by: default avatarMaheshwar Ajja <majja@codeaurora.org>
parent f4bad6de
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ msm-vidc-objs := msm_v4l2_vidc.o \
                                msm_vidc.o \
                                msm_vdec.o \
                                msm_venc.o \
                                msm_cvp.o \
                                msm_smem.o \
                                msm_vidc_debug.o \
                                msm_vidc_res_parse.o \
+22 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -293,6 +293,26 @@ static unsigned long __calculate_vpe(struct vidc_bus_vote_data *d,
	return 0;
}

static unsigned long __calculate_cvp(struct vidc_bus_vote_data *d,
		enum governor_mode gm)
{
	unsigned long ret = 0;

	switch (gm) {
	case GOVERNOR_DDR:
		ret = d->ddr_bw;
		break;
	case GOVERNOR_LLCC:
		ret = d->sys_cache_bw;
		break;
	default:
		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
		break;
	}

	return ret;
}

static bool __ubwc(enum hal_uncompressed_format f)
{
	switch (f) {
@@ -861,6 +881,7 @@ static unsigned long __calculate(struct vidc_bus_vote_data *d,
		[HAL_VIDEO_DOMAIN_VPE] = __calculate_vpe,
		[HAL_VIDEO_DOMAIN_ENCODER] = __calculate_encoder,
		[HAL_VIDEO_DOMAIN_DECODER] = __calculate_decoder,
		[HAL_VIDEO_DOMAIN_CVP] = __calculate_cvp,
	};

	if (d->domain >= ARRAY_SIZE(calc)) {
+80 −0
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@ enum hal_domain vidc_get_hal_domain(u32 hfi_domain)
	case HFI_VIDEO_DOMAIN_DECODER:
		hal_domain = HAL_VIDEO_DOMAIN_DECODER;
		break;
	case HFI_VIDEO_DOMAIN_CVP:
		hal_domain = HAL_VIDEO_DOMAIN_CVP;
		break;
	default:
		dprintk(VIDC_ERR, "%s: invalid domain %x\n",
			__func__, hfi_domain);
@@ -148,6 +151,9 @@ enum hal_video_codec vidc_get_hal_codec(u32 hfi_codec)
	case HFI_VIDEO_CODEC_TME:
		hal_codec = HAL_VIDEO_CODEC_TME;
		break;
	case HFI_VIDEO_CODEC_CVP:
		hal_codec = HAL_VIDEO_CODEC_CVP;
		break;
	default:
		dprintk(VIDC_INFO, "%s: invalid codec 0x%x\n",
			__func__, hfi_codec);
@@ -172,6 +178,9 @@ u32 vidc_get_hfi_domain(enum hal_domain hal_domain)
	case HAL_VIDEO_DOMAIN_DECODER:
		hfi_domain = HFI_VIDEO_DOMAIN_DECODER;
		break;
	case HAL_VIDEO_DOMAIN_CVP:
		hfi_domain = HFI_VIDEO_DOMAIN_CVP;
		break;
	default:
		dprintk(VIDC_ERR, "%s: invalid domain 0x%x\n",
			__func__, hal_domain);
@@ -207,6 +216,9 @@ u32 vidc_get_hfi_codec(enum hal_video_codec hal_codec)
	case HAL_VIDEO_CODEC_TME:
		hfi_codec = HFI_VIDEO_CODEC_TME;
		break;
	case HAL_VIDEO_CODEC_CVP:
		hfi_codec = HFI_VIDEO_CODEC_CVP;
		break;
	default:
		dprintk(VIDC_INFO, "%s: invalid codec 0x%x\n",
			__func__, hal_codec);
@@ -744,6 +756,72 @@ int create_pkt_cmd_session_release_buffers(
	return rc;
}

int create_pkt_cmd_session_register_buffer(
		struct hfi_cmd_session_register_buffers_packet *pkt,
		struct hal_session *session,
		struct vidc_register_buffer *buffer)
{
	int rc = 0, i;
	struct hfi_buffer_mapping_type *buf;

	if (!pkt || !session) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}

	pkt->packet_type = HFI_CMD_SESSION_REGISTER_BUFFERS;
	pkt->session_id = hash32_ptr(session);
	pkt->client_data = buffer->client_data;
	pkt->response_req = buffer->response_required;
	pkt->num_buffers = 1;
	pkt->size = sizeof(struct hfi_cmd_session_register_buffers_packet) -
			sizeof(u32) + (pkt->num_buffers *
			sizeof(struct hfi_buffer_mapping_type));

	buf = (struct hfi_buffer_mapping_type *)pkt->buffer;
	for (i = 0; i < pkt->num_buffers; i++) {
		buf->index = buffer->index;
		buf->device_addr = buffer->device_addr;
		buf->size = buffer->size;
		buf++;
	}

	return rc;
}

int create_pkt_cmd_session_unregister_buffer(
		struct hfi_cmd_session_unregister_buffers_packet *pkt,
		struct hal_session *session,
		struct vidc_unregister_buffer *buffer)
{
	int rc = 0, i;
	struct hfi_buffer_mapping_type *buf;

	if (!pkt || !session) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}

	pkt->packet_type = HFI_CMD_SESSION_UNREGISTER_BUFFERS;
	pkt->session_id = hash32_ptr(session);
	pkt->client_data = buffer->client_data;
	pkt->response_req = buffer->response_required;
	pkt->num_buffers = 1;
	pkt->size = sizeof(struct hfi_cmd_session_unregister_buffers_packet) -
			sizeof(u32) + (pkt->num_buffers *
			sizeof(struct hfi_buffer_mapping_type));

	buf = (struct hfi_buffer_mapping_type *)pkt->buffer;
	for (i = 0; i < pkt->num_buffers; i++) {
		buf->index = buffer->index;
		buf->device_addr = buffer->device_addr;
		buf->size = buffer->size;
		buf++;
	}

	return rc;
}

int create_pkt_cmd_session_etb_decoder(
	struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
	struct hal_session *session, struct vidc_frame_data *input_frame)
@@ -1962,6 +2040,8 @@ static struct hfi_packetization_ops hfi_default = {
	.session_cmd = create_pkt_cmd_session_cmd,
	.session_set_buffers = create_pkt_cmd_session_set_buffers,
	.session_release_buffers = create_pkt_cmd_session_release_buffers,
	.session_register_buffer = create_pkt_cmd_session_register_buffer,
	.session_unregister_buffer = create_pkt_cmd_session_unregister_buffer,
	.session_etb_decoder = create_pkt_cmd_session_etb_decoder,
	.session_etb_encoder = create_pkt_cmd_session_etb_encoder,
	.session_ftb = create_pkt_cmd_session_ftb,
+9 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -62,6 +62,14 @@ struct hfi_packetization_ops {
		struct hfi_cmd_session_release_buffer_packet *pkt,
		struct hal_session *session,
		struct vidc_buffer_addr_info *buffer_info);
	int (*session_register_buffer)(
		struct hfi_cmd_session_register_buffers_packet *pkt,
		struct hal_session *session,
		struct vidc_register_buffer *buffer);
	int (*session_unregister_buffer)(
		struct hfi_cmd_session_unregister_buffers_packet *pkt,
		struct hal_session *session,
		struct vidc_unregister_buffer *buffer);
	int (*session_etb_decoder)(
		struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
		struct hal_session *session,
+62 −0
Original line number Diff line number Diff line
@@ -1628,6 +1628,60 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
	return 0;
}

static int hfi_process_session_register_buffer_done(u32 device_id,
		struct hfi_msg_session_register_buffers_done_packet *pkt,
		struct msm_vidc_cb_info *info)
{
	struct msm_vidc_cb_cmd_done cmd_done = {0};

	if (!pkt || pkt->size <
		sizeof(struct hfi_msg_session_register_buffers_done_packet)) {
		dprintk(VIDC_ERR, "%s: bad packet/packet size %d\n",
			__func__, pkt ? pkt->size : 0);
		return -E2BIG;
	}
	dprintk(VIDC_DBG, "RECEIVED: SESSION_REGISTER_BUFFERS_DONE[%#x]\n",
			pkt->session_id);

	cmd_done.device_id = device_id;
	cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
	cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
	cmd_done.status = hfi_map_err_status(pkt->error_type);
	cmd_done.data.regbuf.client_data = pkt->client_data;

	info->response_type = HAL_SESSION_REGISTER_BUFFER_DONE;
	info->response.cmd = cmd_done;

	return 0;
}

static int hfi_process_session_unregister_buffer_done(u32 device_id,
		struct hfi_msg_session_unregister_buffers_done_packet *pkt,
		struct msm_vidc_cb_info *info)
{
	struct msm_vidc_cb_cmd_done cmd_done = {0};

	if (!pkt || pkt->size <
		sizeof(struct hfi_msg_session_unregister_buffers_done_packet)) {
		dprintk(VIDC_ERR, "%s: bad packet/packet size %d\n",
			__func__, pkt ? pkt->size : 0);
		return -E2BIG;
	}
	dprintk(VIDC_DBG, "RECEIVED: SESSION_UNREGISTER_BUFFERS_DONE[%#x]\n",
			pkt->session_id);

	cmd_done.device_id = device_id;
	cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
	cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
	cmd_done.status = hfi_map_err_status(pkt->error_type);
	cmd_done.data.unregbuf.client_data = pkt->client_data;

	info->response_type = HAL_SESSION_UNREGISTER_BUFFER_DONE;
	info->response.cmd = cmd_done;

	return 0;
}

static int hfi_process_session_end_done(u32 device_id,
		struct hfi_msg_sys_session_end_done_packet *pkt,
		struct msm_vidc_cb_info *info)
@@ -1825,6 +1879,14 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
	case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
		pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
		break;
	case HFI_MSG_SESSION_REGISTER_BUFFERS_DONE:
		pkt_func = (pkt_func_def)
			hfi_process_session_register_buffer_done;
		break;
	case HFI_MSG_SESSION_UNREGISTER_BUFFERS_DONE:
		pkt_func = (pkt_func_def)
			hfi_process_session_unregister_buffer_done;
		break;
	case HFI_MSG_SYS_SESSION_ABORT_DONE:
		pkt_func = (pkt_func_def)hfi_process_session_abort_done;
		break;
Loading