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

Commit 0000c6e2 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Add support for encoder scaling"

parents c2403d18 3eb938d4
Loading
Loading
Loading
Loading
+35 −19
Original line number Diff line number Diff line
@@ -665,8 +665,8 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
		f->fmt.pix_mp.pixelformat = fmt->fourcc;
		f->fmt.pix_mp.num_planes = fmt->num_planes;
		if (inst->in_reconfig == true) {
			inst->prop.height = inst->reconfig_height;
			inst->prop.width = inst->reconfig_width;
			inst->prop.height[CAPTURE_PORT] = inst->reconfig_height;
			inst->prop.width[CAPTURE_PORT] = inst->reconfig_width;
			rc = msm_vidc_check_session_supported(inst);
			if (rc) {
				dprintk(VIDC_ERR,
@@ -674,13 +674,13 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
				goto exit;
			}
		}
		f->fmt.pix_mp.height = inst->prop.height;
		f->fmt.pix_mp.width = inst->prop.width;
		stride = inst->prop.width;
		scanlines = inst->prop.height;
		f->fmt.pix_mp.height = inst->prop.height[CAPTURE_PORT];
		f->fmt.pix_mp.width = inst->prop.width[CAPTURE_PORT];
		stride = inst->prop.width[CAPTURE_PORT];
		scanlines = inst->prop.height[CAPTURE_PORT];
		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
		frame_sz.width = inst->prop.width;
		frame_sz.height = inst->prop.height;
		frame_sz.width = inst->prop.width[CAPTURE_PORT];
		frame_sz.height = inst->prop.height[CAPTURE_PORT];
		dprintk(VIDC_DBG, "width = %d, height = %d\n",
				frame_sz.width, frame_sz.height);
		rc = msm_comm_try_get_bufreqs(inst);
@@ -704,7 +704,8 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			case V4L2_PIX_FMT_NV12:
				call_hfi_op(hdev, get_stride_scanline,
					COLOR_FMT_NV12,
					inst->prop.width, inst->prop.height,
					inst->prop.width[CAPTURE_PORT],
					inst->prop.height[CAPTURE_PORT],
					&stride, &scanlines);
				break;
			default:
@@ -744,9 +745,9 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
				(__u16)scanlines;
		} else {
			f->fmt.pix_mp.plane_fmt[0].bytesperline =
				(__u16)inst->prop.width;
				(__u16)inst->prop.width[CAPTURE_PORT];
			f->fmt.pix_mp.plane_fmt[0].reserved[0] =
				(__u16)inst->prop.height;
				(__u16)inst->prop.height[CAPTURE_PORT];
		}
	} else {
		dprintk(VIDC_ERR,
@@ -831,10 +832,14 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			rc = -EINVAL;
			goto err_invalid_fmt;
		}
		inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
		inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
		inst->fmts[fmt->type] = fmt;
		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
		frame_sz.width = inst->prop.width;
		frame_sz.height = inst->prop.height;
		frame_sz.width = inst->prop.width[CAPTURE_PORT];
		frame_sz.height = inst->prop.height[CAPTURE_PORT];
		dprintk(VIDC_DBG, "width = %d, height = %d\n",
				frame_sz.width, frame_sz.height);
		ret = msm_comm_try_set_prop(inst,
@@ -874,8 +879,10 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
				f->fmt.pix_mp.plane_fmt[i].sizeimage;
		}
	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		inst->prop.width = f->fmt.pix_mp.width;
		inst->prop.height = f->fmt.pix_mp.height;
		inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
		inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
		rc = msm_vidc_check_session_supported(inst);
		if (rc) {
			dprintk(VIDC_ERR,
@@ -900,8 +907,8 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			goto err_invalid_fmt;
		}
		frame_sz.buffer_type = HAL_BUFFER_INPUT;
		frame_sz.width = inst->prop.width;
		frame_sz.height = inst->prop.height;
		frame_sz.width = inst->prop.width[OUTPUT_PORT];
		frame_sz.height = inst->prop.height[OUTPUT_PORT];
		msm_comm_try_set_prop(inst, HAL_PARAM_FRAME_SIZE, &frame_sz);
		f->fmt.pix_mp.plane_fmt[0].sizeimage =
			fmt->get_frame_size(0, inst->capability.height.max,
@@ -1079,6 +1086,13 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
	struct vb2_buf_entry *temp;
	struct list_head *ptr, *next;
	inst->in_reconfig = false;
	if (inst->capability.pixelprocess_capabilities &
		HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY)
		rc = msm_vidc_check_scaling_supported(inst);
	if (rc) {
		dprintk(VIDC_ERR, "H/w scaling is not in valid range");
		return -EINVAL;
	}
	rc = msm_comm_set_scratch_buffers(inst);
	if (rc) {
		dprintk(VIDC_ERR,
@@ -1296,8 +1310,10 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
	}
	inst->fmts[OUTPUT_PORT] = &vdec_formats[1];
	inst->fmts[CAPTURE_PORT] = &vdec_formats[0];
	inst->prop.height = DEFAULT_HEIGHT;
	inst->prop.width = DEFAULT_WIDTH;
	inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT;
	inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH;
	inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT;
	inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH;
	inst->capability.height.min = MIN_SUPPORTED_HEIGHT;
	inst->capability.height.max = DEFAULT_HEIGHT;
	inst->capability.width.min = MIN_SUPPORTED_WIDTH;
+46 −23
Original line number Diff line number Diff line
@@ -872,7 +872,8 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
		inst->fmts[CAPTURE_PORT]->num_planes = *num_planes;
		for (i = 0; i < *num_planes; i++) {
			sizes[i] = inst->fmts[CAPTURE_PORT]->get_frame_size(
					i, inst->prop.height, inst->prop.width);
					i, inst->prop.height[CAPTURE_PORT],
					inst->prop.width[CAPTURE_PORT]);
		}
		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
		new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
@@ -892,6 +893,8 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
				"Failed to get buffer requirements: %d\n", rc);
			break;
		}
		inst->capability.pixelprocess_capabilities =
			call_hfi_op(hdev, get_core_capabilities);
		*num_planes = 1;
		mutex_lock(&inst->lock);
		*num_buffers = inst->buff_req.buffer[0].buffer_count_actual =
@@ -909,7 +912,8 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
				inst->buff_req.buffer[0].buffer_count_actual);
		for (i = 0; i < *num_planes; i++) {
			sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
					i, inst->prop.height, inst->prop.width);
					i, inst->prop.height[OUTPUT_PORT],
					inst->prop.width[OUTPUT_PORT]);
		}
		break;
	default:
@@ -925,7 +929,13 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
	int rc = 0;
	struct vb2_buf_entry *temp;
	struct list_head *ptr, *next;

	if (inst->capability.pixelprocess_capabilities &
		HAL_VIDEO_ENCODER_SCALING_CAPABILITY)
		rc = msm_vidc_check_scaling_supported(inst);
	if (rc) {
		dprintk(VIDC_ERR, "H/w scaling is not in valid range");
		return -EINVAL;
	}
	rc = msm_comm_try_get_bufreqs(inst);
	if (rc) {
		dprintk(VIDC_ERR,
@@ -2025,8 +2035,10 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
	}
	inst->fmts[CAPTURE_PORT] = &venc_formats[1];
	inst->fmts[OUTPUT_PORT] = &venc_formats[0];
	inst->prop.height = DEFAULT_HEIGHT;
	inst->prop.width = DEFAULT_WIDTH;
	inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT;
	inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH;
	inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT;
	inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH;
	inst->prop.fps = 15;
	inst->capability.pixelprocess_capabilities = 0;
	return rc;
@@ -2224,14 +2236,20 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			rc = -EINVAL;
			goto exit;
		}
		inst->prop.width = f->fmt.pix_mp.width;
		inst->prop.height = f->fmt.pix_mp.height;
		inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
		rc = msm_vidc_check_session_supported(inst);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s: session not supported\n", __func__);
			goto exit;
		}
	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		struct hal_uncompressed_format_select hal_fmt = {0};
		struct hal_frame_size frame_sz;

		inst->prop.width = f->fmt.pix_mp.width;
		inst->prop.height = f->fmt.pix_mp.height;
		inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
		inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
		rc = msm_vidc_check_session_supported(inst);
		if (rc) {
			dprintk(VIDC_ERR,
@@ -2239,8 +2257,8 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			goto exit;
		}
		frame_sz.buffer_type = HAL_BUFFER_INPUT;
		frame_sz.width = inst->prop.width;
		frame_sz.height = inst->prop.height;
		frame_sz.width = inst->prop.width[OUTPUT_PORT];
		frame_sz.height = inst->prop.height[OUTPUT_PORT];
		dprintk(VIDC_DBG, "width = %d, height = %d\n",
				frame_sz.width, frame_sz.height);
		rc = call_hfi_op(hdev, session_set_property, (void *)
@@ -2310,11 +2328,11 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
			}
			inst->capability.pixelprocess_capabilities =
				call_hfi_op(hdev, get_core_capabilities);
			frame_sz.width = inst->prop.width;
			frame_sz.height = inst->prop.height;
			frame_sz.width = inst->prop.width[CAPTURE_PORT];
			frame_sz.height = inst->prop.height[CAPTURE_PORT];
			frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
			rc = call_hfi_op(hdev, session_set_property,
				(void *)inst->session, HAL_PARAM_FRAME_SIZE,
			rc = call_hfi_op(hdev, session_set_property, (void *)
					inst->session, HAL_PARAM_FRAME_SIZE,
					&frame_sz);
			if (rc) {
				dprintk(VIDC_ERR,
@@ -2336,26 +2354,31 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
	const struct msm_vidc_format *fmt = NULL;
	int rc = 0;
	int i;
	u32 height, width;
	int extra_idx = 0;
	if (!inst || !f) {
		dprintk(VIDC_ERR,
			"Invalid input, inst = %p, format = %p\n", inst, f);
		return -EINVAL;
	}
	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		fmt = inst->fmts[CAPTURE_PORT];
	else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
		height = inst->prop.height[CAPTURE_PORT];
		width = inst->prop.width[CAPTURE_PORT];
	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		fmt = inst->fmts[OUTPUT_PORT];
		height = inst->prop.height[OUTPUT_PORT];
		width = inst->prop.width[OUTPUT_PORT];
	}

	if (fmt) {
		f->fmt.pix_mp.pixelformat = fmt->fourcc;
		f->fmt.pix_mp.height = inst->prop.height;
		f->fmt.pix_mp.width = inst->prop.width;
		f->fmt.pix_mp.height = height;
		f->fmt.pix_mp.width = width;
		f->fmt.pix_mp.num_planes = fmt->num_planes;
		for (i = 0; i < fmt->num_planes; ++i) {
			f->fmt.pix_mp.plane_fmt[i].sizeimage =
			fmt->get_frame_size(i, inst->prop.height,
					inst->prop.width);
			fmt->get_frame_size(i, height, width);
		}
		extra_idx = EXTRADATA_IDX(fmt->num_planes);
		if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+95 −13
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <asm/div64.h>
#include <mach/subsystem_restart.h>

@@ -81,6 +82,16 @@ static bool is_thumbnail_session(struct msm_vidc_inst *inst)
	return false;
}

static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
{
	int height, width;
	height = max(inst->prop.height[CAPTURE_PORT],
		inst->prop.height[OUTPUT_PORT]);
	width = max(inst->prop.width[CAPTURE_PORT],
		inst->prop.width[OUTPUT_PORT]);
	return NUM_MBS_PER_SEC(height, width, inst->prop.fps);
}

static int msm_comm_get_load(struct msm_vidc_core *core,
	enum session_type type)
{
@@ -96,9 +107,8 @@ static int msm_comm_get_load(struct msm_vidc_core *core,
			inst->state >= MSM_VIDC_OPEN_DONE &&
			inst->state < MSM_VIDC_STOP_DONE) {
			if (!is_thumbnail_session(inst))
				num_mbs_per_sec += NUM_MBS_PER_SEC(
					inst->prop.height,
					inst->prop.width, inst->prop.fps);
				num_mbs_per_sec +=
					msm_comm_get_mbs_per_sec(inst);
		}
		mutex_unlock(&inst->lock);
	}
@@ -429,6 +439,8 @@ static void handle_session_init_done(enum command_response cmd, void *data)
			inst->capability.height = session_init_done->height;
			inst->capability.frame_rate =
				session_init_done->frame_rate;
			inst->capability.scale_x = session_init_done->scale_x;
			inst->capability.scale_y = session_init_done->scale_y;
			inst->capability.capability_set = true;
			inst->capability.buffer_mode[CAPTURE_PORT] =
				session_init_done->alloc_mode_out;
@@ -479,8 +491,8 @@ static void handle_event_change(enum command_response cmd, void *data)
			inst->reconfig_width = event_notify->width;
			inst->in_reconfig = true;
		} else {
			inst->prop.height = event_notify->height;
			inst->prop.width = event_notify->width;
			inst->prop.height[CAPTURE_PORT] = event_notify->height;
			inst->prop.width[CAPTURE_PORT] = event_notify->width;
		}
		rc = msm_vidc_check_session_supported(inst);
		if (!rc) {
@@ -1406,8 +1418,8 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
				temp->state < MSM_VIDC_STOP_DONE) {
			dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d\n",
					temp->session_type,
					temp->prop.width,
					temp->prop.height,
					temp->prop.width[CAPTURE_PORT],
					temp->prop.height[CAPTURE_PORT],
					temp->prop.fps);
		}
		mutex_unlock(&temp->lock);
@@ -1421,6 +1433,7 @@ static int msm_vidc_load_resources(int flipped_state,
	u32 ocmem_sz = 0;
	struct hfi_device *hdev;
	int num_mbs_per_sec = 0;
	int height, width;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1454,9 +1467,13 @@ static int msm_vidc_load_resources(int flipped_state,
		goto exit;
	}
	if (inst->core->resources.has_ocmem) {
		ocmem_sz = get_ocmem_requirement(inst->prop.height,
						inst->prop.width);
		mutex_lock(&inst->core->sync_lock);
		height = max(inst->prop.height[CAPTURE_PORT],
			inst->prop.height[OUTPUT_PORT]);
		width = max(inst->prop.width[CAPTURE_PORT],
			inst->prop.width[OUTPUT_PORT]);
		ocmem_sz = get_ocmem_requirement(
			height, width);
		rc = msm_comm_scale_bus(inst->core, inst->session_type,
					OCMEM_MEM);
		mutex_unlock(&inst->core->sync_lock);
@@ -2623,6 +2640,70 @@ static int msm_vidc_load_supported(struct msm_vidc_inst *inst)
	return 0;
}

int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
{
	u32 x_min, x_max, y_min, y_max;
	u32 input_height, input_width, output_height, output_width;

	if (!inst->capability.scale_x.min || !inst->capability.scale_x.max ||
			!inst->capability.scale_y.min ||
			!inst->capability.scale_y.max) {
		dprintk(VIDC_ERR, "%s : Invalid scaling ratios",
				__func__);
		return -ENOTSUPP;
	}
	x_min = (1<<16)/inst->capability.scale_x.min;
	y_min = (1<<16)/inst->capability.scale_y.min;
	x_max = inst->capability.scale_x.max >> 16;
	y_max = inst->capability.scale_y.max >> 16;

	input_height = inst->prop.height[OUTPUT_PORT];
	input_width = inst->prop.width[OUTPUT_PORT];
	output_height = inst->prop.height[CAPTURE_PORT];
	output_width = inst->prop.width[CAPTURE_PORT];

	if (!input_height || !input_width || !output_height || !output_width) {
		dprintk(VIDC_ERR,
			"Invalid : Input Height = %d Width = %d"
			" Output Height = %d Width = %d",
			input_height, input_width, output_height,
			output_width);
		return -ENOTSUPP;
	}

	if (input_height > output_height) {
		if (input_height/output_height > x_min) {
			dprintk(VIDC_ERR,
				"Unsupported Height Downscale ratio %d Vs %d",
				input_height/output_height, x_min);
			return -ENOTSUPP;
		}
	} else {
		if (input_height/output_height > x_max) {
			dprintk(VIDC_ERR,
				"Unsupported Height Upscale ratio %d Vs %d",
				input_height/output_height, x_max);
			return -ENOTSUPP;
		}
	}
	if (input_width > output_width) {
		if (input_width/output_width > y_min) {
			dprintk(VIDC_ERR,
				"Unsupported Width Downscale ratio %d Vs %d",
				input_width/output_width, y_min);
			return -ENOTSUPP;
		}
	} else {
		if (input_width/output_width > y_max) {
			dprintk(VIDC_ERR,
				"Unsupported Width Upscale ratio %d Vs %d",
				input_width/output_width, y_max);
			return -ENOTSUPP;
		}
	}
	return 0;
}

int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
{
	struct msm_vidc_core_capability *capability;
@@ -2635,19 +2716,20 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
	}
	capability = &inst->capability;
	hdev = inst->core->device;

	rc = msm_vidc_load_supported(inst);
	if (!rc && inst->capability.capability_set) {
		rc = call_hfi_op(hdev, capability_check,
			inst->fmts[OUTPUT_PORT]->fourcc,
			inst->prop.width, &capability->width.max,
			inst->prop.width[CAPTURE_PORT], &capability->width.max,
			&capability->height.max);

		if (!rc && (inst->prop.height * inst->prop.width >
		if (!rc && (inst->prop.height[CAPTURE_PORT]
			* inst->prop.width[CAPTURE_PORT] >
			capability->width.max * capability->height.max)) {
			dprintk(VIDC_ERR,
			"Unsupported WxH = (%u)x(%u), Max supported is - (%u)x(%u)",
			inst->prop.width, inst->prop.height,
			inst->prop.width[CAPTURE_PORT],
			inst->prop.height[CAPTURE_PORT],
			capability->width.max, capability->height.max);
			rc = -ENOTSUPP;
		}
+5 −4
Original line number Diff line number Diff line
@@ -44,8 +44,6 @@
#define MAX_SUPPORTED_WIDTH 3820
#define MAX_SUPPORTED_HEIGHT 2160



#define V4L2_EVENT_VIDC_BASE  10

#define SYS_MSG_START VIDC_EVENT_CHANGE
@@ -126,8 +124,8 @@ struct msm_video_device {
};

struct session_prop {
	u32 width;
	u32 height;
	u32 width[MAX_PORT_NUM];
	u32 height[MAX_PORT_NUM];
	u32 fps;
	u32 bitrate;
};
@@ -178,6 +176,8 @@ struct msm_vidc_core_capability {
	struct hal_capability_supported height;
	struct hal_capability_supported frame_rate;
	u32 pixelprocess_capabilities;
	struct hal_capability_supported scale_x;
	struct hal_capability_supported scale_y;
	u32 capability_set;
	enum buffer_mode_type buffer_mode[MAX_PORT_NUM];
};
@@ -256,6 +256,7 @@ void handle_cmd_response(enum command_response cmd, void *data);
int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
	enum hal_ssr_trigger_type type);
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type);

#endif