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

Commit 437b6bc9 authored by Manoj Rao's avatar Manoj Rao Committed by Michael Bohan
Browse files

msm: mdss: compat ioctl for mdss overlay



Implement an entry point for compat ioctl in mdss overlay driver.
Overlay ioctls that require compat layer translation have been added here.
If the calling user process comes from a 32-bit world, then the compat
ioctl does an appropriate command conversion to keep the existing ioctl
implementation unchanged.  Add PP compat structures to include 32 bit
compatible versions of post-processing structures. This allows addition
of pp compat ioctl layer.

Change-Id: I732fcbc84151b813a02d3b4db20e858d4c51291e
Signed-off-by: default avatarManoj Rao <manojraj@codeaurora.org>
Signed-off-by: default avatarBenet Clark <benetc@codeaurora.org>
parent 3efa5521
Loading
Loading
Loading
Loading
+182 −40
Original line number Diff line number Diff line
@@ -21,23 +21,7 @@
#include <linux/uaccess.h>

#include "mdss_fb.h"

struct mdp_buf_sync32 {
	u32		flags;
	u32		acq_fen_fd_cnt;
	u32		session_id;
	compat_caddr_t	acq_fen_fd;
	compat_caddr_t	rel_fen_fd;
};

struct fb_cmap32 {
	u32		start;
	u32		len;
	compat_caddr_t	red;
	compat_caddr_t	green;
	compat_caddr_t	blue;
	compat_caddr_t	transp;
};
#include "mdss_compat_utils.h"

#define MSMFB_SET_LUT32 _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap32)
#define MSMFB_HISTOGRAM32 _IOWR(MSMFB_IOCTL_MAGIC, 132,\
@@ -62,7 +46,6 @@ struct fb_cmap32 {
#define MSMFB_MDP_PP32 _IOWR(MSMFB_IOCTL_MAGIC, 156, struct msmfb_mdp_pp32)
#define MSMFB_BUFFER_SYNC32  _IOW(MSMFB_IOCTL_MAGIC, 162, struct mdp_buf_sync32)


static unsigned int __do_compat_ioctl_nr(unsigned int cmd32)
{
	unsigned int cmd;
@@ -83,9 +66,6 @@ static unsigned int __do_compat_ioctl_nr(unsigned int cmd32)
	case MSMFB_OVERLAY_SET32:
		cmd = MSMFB_OVERLAY_SET;
		break;
	case MSMFB_OVERLAY_PLAY32:
		cmd = MSMFB_OVERLAY_PLAY;
		break;
	case MSMFB_OVERLAY_GET32:
		cmd = MSMFB_OVERLAY_GET;
		break;
@@ -98,27 +78,12 @@ static unsigned int __do_compat_ioctl_nr(unsigned int cmd32)
	case MSMFB_MIXER_INFO32:
		cmd = MSMFB_MIXER_INFO;
		break;
	case MSMFB_OVERLAY_PLAY_WAIT32:
		cmd = MSMFB_OVERLAY_PLAY_WAIT;
		break;
	case MSMFB_WRITEBACK_QUEUE_BUFFER32:
		cmd = MSMFB_WRITEBACK_QUEUE_BUFFER;
		break;
	case MSMFB_WRITEBACK_DEQUEUE_BUFFER32:
		cmd = MSMFB_WRITEBACK_DEQUEUE_BUFFER;
		break;
	case MSMFB_MDP_PP32:
		cmd = MSMFB_MDP_PP;
		break;
	case MSMFB_BUFFER_SYNC32:
		cmd = MSMFB_BUFFER_SYNC;
		break;
	case MSMFB_METADATA_SET32:
		cmd = MSMFB_METADATA_SET;
		break;
	case MSMFB_METADATA_GET32:
		cmd = MSMFB_METADATA_GET;
		break;
	default:
		cmd = cmd32;
		break;
@@ -154,10 +119,12 @@ static int mdss_fb_compat_buf_sync(struct fb_info *info, unsigned int cmd,
		return ret;
	}

	if (copy_in_user(buf_sync32->rel_fen_fd, buf_sync->rel_fen_fd,
	if (copy_in_user(compat_ptr(buf_sync32->rel_fen_fd),
			buf_sync->rel_fen_fd,
			sizeof(int)))
		return -EFAULT;
	if (copy_in_user(buf_sync32->retire_fen_fd, buf_sync->retire_fen_fd,
	if (copy_in_user(compat_ptr(buf_sync32->retire_fen_fd),
			buf_sync->retire_fen_fd,
			sizeof(int)))
		return -EFAULT;

@@ -194,6 +161,168 @@ static int mdss_fb_compat_set_lut(struct fb_info *info, unsigned long arg)
	return ret;
}

static int __to_user_pp_params(struct mdp_overlay_pp_params32 *ppp32,
				   struct mdp_overlay_pp_params *ppp)
{
	return 0;
}

static int __from_user_pp_params32(struct mdp_overlay_pp_params *ppp,
				   struct mdp_overlay_pp_params32 *ppp32)
{
	__u32 data;

	if (get_user(data, &ppp32->config_ops) ||
	    put_user(data, &ppp->config_ops))
		return -EFAULT;

	return 0;
}

static int __to_user_mdp_overlay(struct mdp_overlay32 __user *ov32,
				 struct mdp_overlay __user *ov)
{
	int ret = 0;

	ret = copy_in_user(&ov32->src, &ov->src, sizeof(ov32->src)) ||
		copy_in_user(&ov32->src_rect,
			&ov->src_rect, sizeof(ov32->src_rect)) ||
		copy_in_user(&ov32->dst_rect,
			&ov->dst_rect, sizeof(ov32->dst_rect));
	if (ret)
		return -EFAULT;

	ret |= put_user(ov->z_order, &ov32->z_order);
	ret |= put_user(ov->is_fg, &ov32->is_fg);
	ret |= put_user(ov->alpha, &ov32->alpha);
	ret |= put_user(ov->blend_op, &ov32->blend_op);
	ret |= put_user(ov->transp_mask, &ov32->transp_mask);
	ret |= put_user(ov->flags, &ov32->flags);
	ret |= put_user(ov->id, &ov32->id);
	if (ret)
		return -EFAULT;

	ret = copy_in_user(&ov32->user_data, &ov->user_data,
		     sizeof(ov32->user_data));
	if (ret)
		return -EFAULT;

	ret |= put_user(ov->horz_deci, &ov32->horz_deci);
	ret |= put_user(ov->vert_deci, &ov32->vert_deci);
	if (ret)
		return -EFAULT;

	ret = __to_user_pp_params(&ov32->overlay_pp_cfg, &ov->overlay_pp_cfg);
	if (ret)
		return -EFAULT;

	ret = copy_in_user(&ov32->scale, &ov->scale,
			   sizeof(struct mdp_scale_data));
	if (ret)
		return -EFAULT;
	return 0;
}


static int __from_user_mdp_overlay(struct mdp_overlay *ov,
				   struct mdp_overlay32 *ov32)
{
	__u32 data;

	if (copy_in_user(&ov->src, &ov32->src,
			 sizeof(ov32->src)) ||
	    copy_in_user(&ov->src_rect, &ov32->src_rect,
			 sizeof(ov32->src_rect)) ||
	    copy_in_user(&ov->dst_rect, &ov32->dst_rect,
			 sizeof(ov32->dst_rect)))
		return -EFAULT;

	if (get_user(data, &ov32->z_order) ||
	    put_user(data, &ov->z_order) ||
	    get_user(data, &ov32->is_fg) ||
	    put_user(data, &ov->is_fg) ||
	    get_user(data, &ov32->alpha) ||
	    put_user(data, &ov->alpha) ||
	    get_user(data, &ov32->blend_op) ||
	    put_user(data, &ov->blend_op) ||
	    get_user(data, &ov32->transp_mask) ||
	    put_user(data, &ov->transp_mask) ||
	    get_user(data, &ov32->flags) ||
	    put_user(data, &ov->flags) ||
	    get_user(data, &ov32->id) ||
	    put_user(data, &ov->id))
		return -EFAULT;

	if (copy_in_user(&ov->user_data, &ov32->user_data,
			 sizeof(ov32->user_data)))
		return -EFAULT;

	if (get_user(data, &ov32->horz_deci) ||
	    put_user(data, &ov->horz_deci) ||
	    get_user(data, &ov32->vert_deci) ||
	    put_user(data, &ov->vert_deci))
		return -EFAULT;

	if (__from_user_pp_params32(&ov->overlay_pp_cfg,
				    &ov32->overlay_pp_cfg))
		return -EFAULT;

	if (copy_in_user(&ov->scale, &ov32->scale,
			 sizeof(struct mdp_scale_data)))
		return -EFAULT;

	return 0;
}

int mdss_compat_overlay_ioctl(struct fb_info *info, unsigned int cmd,
			 unsigned long arg)
{
	struct mdp_overlay *ov;
	struct mdp_overlay32 *ov32;
	int ret;

	if (!info || !info->par)
		return -EINVAL;

	ov = compat_alloc_user_space(sizeof(*ov));

	switch (cmd) {
	case MSMFB_OVERLAY_GET:
		ov32 = compat_ptr(arg);
		ret = __from_user_mdp_overlay(ov, ov32);
		if (ret)
			pr_err("%s: compat mdp overlay failed\n", __func__);
		else
			ret = mdss_fb_do_ioctl(info, cmd, (unsigned long) ov);
		ret = __to_user_mdp_overlay(ov32, ov);
		break;
	case MSMFB_OVERLAY_SET:
		ov32 = compat_ptr(arg);
		ret = __from_user_mdp_overlay(ov, ov32);
		if (ret) {
			pr_err("%s: compat mdp overlay failed\n", __func__);
		} else {
			ret = mdss_fb_do_ioctl(info, cmd, (unsigned long) ov);
			ret = __to_user_mdp_overlay(ov32, ov);
		}
		break;
	case MSMFB_OVERLAY_UNSET:
	case MSMFB_OVERLAY_PLAY_ENABLE:
	case MSMFB_OVERLAY_PLAY:
	case MSMFB_OVERLAY_PLAY_WAIT:
	case MSMFB_VSYNC_CTRL:
	case MSMFB_OVERLAY_VSYNC_CTRL:
	case MSMFB_OVERLAY_COMMIT:
	case MSMFB_METADATA_SET:
	case MSMFB_METADATA_GET:
	default:
		pr_debug("%s: overlay ioctl cmd=[%u]\n", __func__, cmd);
		ret = mdss_fb_do_ioctl(info, cmd, (unsigned long) arg);
		break;
	}
	return ret;
}

/*
 * mdss_fb_compat_ioctl() - MDSS Framebuffer compat ioctl function
 * @info:	pointer to framebuffer info
@@ -224,6 +353,19 @@ int mdss_fb_compat_ioctl(struct fb_info *info, unsigned int cmd,
	case MSMFB_BUFFER_SYNC:
		ret = mdss_fb_compat_buf_sync(info, cmd, arg);
		break;
	case MSMFB_OVERLAY_GET:
	case MSMFB_OVERLAY_SET:
	case MSMFB_OVERLAY_UNSET:
	case MSMFB_OVERLAY_PLAY_ENABLE:
	case MSMFB_OVERLAY_PLAY:
	case MSMFB_OVERLAY_PLAY_WAIT:
	case MSMFB_VSYNC_CTRL:
	case MSMFB_OVERLAY_VSYNC_CTRL:
	case MSMFB_OVERLAY_COMMIT:
	case MSMFB_METADATA_SET:
	case MSMFB_METADATA_GET:
		ret = mdss_compat_overlay_ioctl(info, cmd, arg);
		break;
	case MSMFB_NOTIFY_UPDATE:
	case MSMFB_DISPLAY_COMMIT:
	default:
+367 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef MDSS_COMPAT_UTILS_H
#define MDSS_COMPAT_UTILS_H

struct mdp_buf_sync32 {
	u32		flags;
	u32		acq_fen_fd_cnt;
	u32		session_id;
	compat_caddr_t	acq_fen_fd;
	compat_caddr_t	rel_fen_fd;
	compat_caddr_t  retire_fen_fd;
};

struct fb_cmap32 {
	u32		start;
	u32		len;
	compat_caddr_t	red;
	compat_caddr_t	green;
	compat_caddr_t	blue;
	compat_caddr_t	transp;
};

struct mdp_ccs32 {
};

struct msmfb_overlay_blt32 {
};

struct msmfb_overlay_3d32 {
};

struct msmfb_mixer_info_req32 {
};

struct msmfb_metadata32 {
	uint32_t op;
	uint32_t flags;
	union {
		struct mdp_misr misr_request;
		struct mdp_blend_cfg blend_cfg;
		struct mdp_mixer_cfg mixer_cfg;
		uint32_t panel_frame_rate;
		uint32_t video_info_code;
		struct mdss_hw_caps caps;
		uint8_t secure_en;
	} data;
};

struct mdp_histogram_start_req32 {
	uint32_t block;
	uint8_t frame_cnt;
	uint8_t bit_mask;
	uint16_t num_bins;
};

struct mdp_histogram_data32 {
	uint32_t block;
	uint32_t bin_cnt;
	compat_caddr_t c0;
	compat_caddr_t c1;
	compat_caddr_t c2;
	compat_caddr_t extra_info;
};

struct mdp_pcc_coeff32 {
	uint32_t c, r, g, b, rr, gg, bb, rg, gb, rb, rgb_0, rgb_1;
};

struct mdp_pcc_cfg_data32 {
	uint32_t block;
	uint32_t ops;
	struct mdp_pcc_coeff32 r, g, b;
};

struct mdp_csc_cfg32 {
	/* flags for enable CSC, toggling RGB,YUV input/output */
	uint32_t flags;
	uint32_t csc_mv[9];
	uint32_t csc_pre_bv[3];
	uint32_t csc_post_bv[3];
	uint32_t csc_pre_lv[6];
	uint32_t csc_post_lv[6];
};

struct mdp_csc_cfg_data32 {
	uint32_t block;
	struct mdp_csc_cfg32 csc_data;
};

struct mdp_bl_scale_data32 {
	uint32_t min_lvl;
	uint32_t scale;
};

struct mdp_pa_mem_col_cfg32 {
	uint32_t color_adjust_p0;
	uint32_t color_adjust_p1;
	uint32_t hue_region;
	uint32_t sat_region;
	uint32_t val_region;
};

struct mdp_pa_v2_data32 {
	/* Mask bits for PA features */
	uint32_t flags;
	uint32_t global_hue_adj;
	uint32_t global_sat_adj;
	uint32_t global_val_adj;
	uint32_t global_cont_adj;
	struct mdp_pa_mem_col_cfg32 skin_cfg;
	struct mdp_pa_mem_col_cfg32 sky_cfg;
	struct mdp_pa_mem_col_cfg32 fol_cfg;
	uint32_t six_zone_len;
	uint32_t six_zone_thresh;
	compat_caddr_t six_zone_curve_p0;
	compat_caddr_t six_zone_curve_p1;
};

struct mdp_pa_v2_cfg_data32 {
	uint32_t block;
	struct mdp_pa_v2_data32 pa_v2_data;
};

struct mdp_pa_cfg32 {
	uint32_t flags;
	uint32_t hue_adj;
	uint32_t sat_adj;
	uint32_t val_adj;
	uint32_t cont_adj;
};

struct mdp_pa_cfg_data32 {
	uint32_t block;
	struct mdp_pa_cfg32 pa_data;
};

struct mdp_igc_lut_data32 {
	uint32_t block;
	uint32_t len, ops;
	compat_caddr_t c0_c1_data;
	compat_caddr_t c2_data;
};

struct mdp_hist_lut_data32 {
	uint32_t block;
	uint32_t ops;
	uint32_t len;
	compat_caddr_t data;
};

struct mdp_ar_gc_lut_data32 {
	uint32_t x_start;
	uint32_t slope;
	uint32_t offset;
};

struct mdp_pgc_lut_data32 {
	uint32_t block;
	uint32_t flags;
	uint8_t num_r_stages;
	uint8_t num_g_stages;
	uint8_t num_b_stages;
	compat_caddr_t r_data;
	compat_caddr_t g_data;
	compat_caddr_t b_data;
};

struct mdp_lut_cfg_data32 {
	uint32_t lut_type;
	union {
		struct mdp_igc_lut_data32 igc_lut_data;
		struct mdp_pgc_lut_data32 pgc_lut_data;
		struct mdp_hist_lut_data32 hist_lut_data;
	} data;
};

struct mdp_qseed_cfg32 {
	uint32_t table_num;
	uint32_t ops;
	uint32_t len;
	compat_caddr_t data;
};

struct mdp_qseed_cfg_data32 {
	uint32_t block;
	struct mdp_qseed_cfg32 qseed_data;
};

struct mdp_dither_cfg_data32 {
	uint32_t block;
	uint32_t flags;
	uint32_t g_y_depth;
	uint32_t r_cr_depth;
	uint32_t b_cb_depth;
};

struct mdp_gamut_cfg_data32 {
	uint32_t block;
	uint32_t flags;
	uint32_t gamut_first;
	uint32_t tbl_size[MDP_GAMUT_TABLE_NUM];
	compat_caddr_t r_tbl[MDP_GAMUT_TABLE_NUM];
	compat_caddr_t g_tbl[MDP_GAMUT_TABLE_NUM];
	compat_caddr_t b_tbl[MDP_GAMUT_TABLE_NUM];
};

struct mdp_calib_config_data32 {
	uint32_t ops;
	uint32_t addr;
	uint32_t data;
};

struct mdp_calib_config_buffer32 {
	uint32_t ops;
	uint32_t size;
	compat_caddr_t buffer;
};

struct mdp_calib_dcm_state32 {
	uint32_t ops;
	uint32_t dcm_state;
};

struct mdss_ad_init32 {
	uint32_t asym_lut[33];
	uint32_t color_corr_lut[33];
	uint8_t i_control[2];
	uint16_t black_lvl;
	uint16_t white_lvl;
	uint8_t var;
	uint8_t limit_ampl;
	uint8_t i_dither;
	uint8_t slope_max;
	uint8_t slope_min;
	uint8_t dither_ctl;
	uint8_t format;
	uint8_t auto_size;
	uint16_t frame_w;
	uint16_t frame_h;
	uint8_t logo_v;
	uint8_t logo_h;
	uint32_t bl_lin_len;
	compat_caddr_t bl_lin;
	compat_caddr_t bl_lin_inv;
};

struct mdss_ad_cfg32 {
	uint32_t mode;
	uint32_t al_calib_lut[33];
	uint16_t backlight_min;
	uint16_t backlight_max;
	uint16_t backlight_scale;
	uint16_t amb_light_min;
	uint16_t filter[2];
	uint16_t calib[4];
	uint8_t strength_limit;
	uint8_t t_filter_recursion;
	uint16_t stab_itr;
	uint32_t bl_ctrl_mode;
};

/* ops uses standard MDP_PP_* flags */
struct mdss_ad_init_cfg32 {
	uint32_t ops;
	union {
		struct mdss_ad_init32 init;
		struct mdss_ad_cfg32 cfg;
	} params;
};

struct mdss_ad_input32 {
	uint32_t mode;
	union {
		uint32_t amb_light;
		uint32_t strength;
		uint32_t calib_bl;
	} in;
	uint32_t output;
};

struct mdss_calib_cfg32 {
	uint32_t ops;
	uint32_t calib_mask;
};

struct mdp_histogram_cfg32 {
	uint32_t ops;
	uint32_t block;
	uint8_t frame_cnt;
	uint8_t bit_mask;
	uint16_t num_bins;
};

struct mdp_sharp_cfg32 {
	uint32_t flags;
	uint32_t strength;
	uint32_t edge_thr;
	uint32_t smooth_thr;
	uint32_t noise_thr;
};

struct mdp_overlay_pp_params32 {
	uint32_t config_ops;
	struct mdp_csc_cfg32 csc_cfg;
	struct mdp_qseed_cfg32 qseed_cfg[2];
	struct mdp_pa_cfg32 pa_cfg;
	struct mdp_pa_v2_data32 pa_v2_cfg;
	struct mdp_igc_lut_data32 igc_cfg;
	struct mdp_sharp_cfg32 sharp_cfg;
	struct mdp_histogram_cfg32 hist_cfg;
	struct mdp_hist_lut_data32 hist_lut_cfg;
};

struct msmfb_mdp_pp32 {
	uint32_t op;
	union {
		struct mdp_pcc_cfg_data32 pcc_cfg_data;
		struct mdp_csc_cfg_data32 csc_cfg_data;
		struct mdp_lut_cfg_data32 lut_cfg_data;
		struct mdp_qseed_cfg_data32 qseed_cfg_data;
		struct mdp_bl_scale_data32 bl_scale_data;
		struct mdp_pa_cfg_data32 pa_cfg_data;
		struct mdp_pa_v2_cfg_data32 pa_v2_cfg_data;
		struct mdp_dither_cfg_data32 dither_cfg_data;
		struct mdp_gamut_cfg_data32 gamut_cfg_data;
		struct mdp_calib_config_data32 calib_cfg;
		struct mdss_ad_init_cfg32 ad_init_cfg;
		struct mdss_calib_cfg32 mdss_calib_cfg;
		struct mdss_ad_input32 ad_input;
		struct mdp_calib_config_buffer32 calib_buffer;
		struct mdp_calib_dcm_state32 calib_dcm;
	} data;
};

struct mdp_overlay32 {
	struct msmfb_img src;
	struct mdp_rect src_rect;
	struct mdp_rect dst_rect;
	uint32_t z_order;	/* stage number */
	uint32_t is_fg;	/* control alpha & transp */
	uint32_t alpha;
	uint32_t blend_op;
	uint32_t transp_mask;
	uint32_t flags;
	uint32_t id;
	uint32_t user_data[6];
	uint32_t bg_color;
	uint8_t horz_deci;
	uint8_t vert_deci;
	struct mdp_overlay_pp_params32 overlay_pp_cfg;
	struct mdp_scale_data scale;
};

#endif