| Index: drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
|
| diff --git a/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c b/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4ee2d9f5775c0f7ed5265c3679804b2862728772
|
| --- /dev/null
|
| +++ b/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
|
| @@ -0,0 +1,864 @@
|
| +/* linux/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
|
| +*
|
| +* Copyright (c) 2010 Samsung Electronics Co., Ltd.
|
| +* http://www.samsung.com/
|
| +*
|
| +* S5PV210 - Video Layer ftn. file for Samsung TVOut driver
|
| +*
|
| +* This program is free software; you can redistribute it and/or modify
|
| +* it under the terms of the GNU General Public License version 2 as
|
| +* published by the Free Software Foundation.
|
| +*/
|
| +
|
| +#include <linux/module.h>
|
| +#include <linux/kernel.h>
|
| +#include <linux/stddef.h>
|
| +#include <linux/delay.h>
|
| +#include <linux/ioctl.h>
|
| +#include <linux/clk.h>
|
| +
|
| +#include <linux/io.h>
|
| +#include <linux/uaccess.h>
|
| +
|
| +#include "s5p_tv.h"
|
| +
|
| +#ifdef CONFIG_TVOUT_DBG
|
| +#define S5P_VLAYER_DEBUG 1
|
| +#endif
|
| +
|
| +#ifdef S5P_VLAYER_DEBUG
|
| +#define VLAYERPRINTK(fmt, args...) \
|
| + printk(KERN_INFO "\t[VLAYER] %s: " fmt, __func__ , ## args)
|
| +#else
|
| +#define VLAYERPRINTK(fmt, args...)
|
| +#endif
|
| +
|
| +#define INTERLACED 0
|
| +#define PROGRESSIVE 1
|
| +
|
| +u8 check_input_mode(enum s5p_vp_src_color color)
|
| +{
|
| + u8 ret = PROGRESSIVE;
|
| +
|
| + /* check i_mode */
|
| + if (color == VPROC_SRC_COLOR_NV12IW ||
|
| + color == VPROC_SRC_COLOR_TILE_NV12IW)
|
| + ret = INTERLACED; /* interlaced */
|
| + else
|
| + ret = PROGRESSIVE; /* progressive */
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +u8 check_output_mode(enum s5p_tv_disp_mode display,
|
| + enum s5p_tv_o_mode out)
|
| +{
|
| + u8 ret = PROGRESSIVE;
|
| +
|
| + switch (out) {
|
| + case TVOUT_OUTPUT_COMPOSITE:
|
| + case TVOUT_OUTPUT_SVIDEO:
|
| + case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
|
| + ret = INTERLACED;
|
| + break;
|
| + case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
|
| + case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
|
| + case TVOUT_OUTPUT_HDMI_RGB:
|
| + case TVOUT_OUTPUT_HDMI:
|
| + case TVOUT_OUTPUT_DVI:
|
| + if (display == TVOUT_1080I_60 ||
|
| + display == TVOUT_1080I_59 ||
|
| + display == TVOUT_1080I_50)
|
| +
|
| + ret = INTERLACED;
|
| + else
|
| + ret = PROGRESSIVE;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + return ret;
|
| +
|
| +}
|
| +
|
| +static bool tv_vlayer_wait_previous_update(void)
|
| +{
|
| + tv_vp_get_update_status();
|
| + return false;
|
| +}
|
| +
|
| +static void tv_vlayer_calc_inner_values(void)
|
| +{
|
| + struct s5p_tv_status *st = &s5ptv_status;
|
| + struct s5p_vl_param *video = &(s5ptv_status.vl_basic_param);
|
| + u8 o_mode, i_mode;
|
| +
|
| + u32 t_y_addr = video->top_y_address;
|
| + u32 t_c_addr = video->top_c_address;
|
| + u32 img_w = video->img_width;
|
| + u32 s_ox = video->src_offset_x;
|
| + u32 s_oy = video->src_offset_y;
|
| + u32 d_ox = video->dest_offset_x;
|
| + u32 d_oy = video->dest_offset_y;
|
| + u32 s_w = video->src_width;
|
| + u32 s_h = video->src_height;
|
| + u32 d_w = video->dest_width;
|
| + u32 d_h = video->dest_height;
|
| +
|
| + i_mode = check_input_mode(st->src_color);
|
| + o_mode = check_output_mode(st->tvout_param.disp_mode,
|
| + st->tvout_param.out_mode);
|
| +
|
| + st->vl_top_y_address = t_y_addr;
|
| + st->vl_top_c_address = t_c_addr;
|
| +
|
| + if (st->src_color == VPROC_SRC_COLOR_NV12IW) {
|
| + st->vl_bottom_y_address = t_y_addr + img_w;
|
| + st->vl_bottom_c_address = t_c_addr + img_w;
|
| + } else if (st->src_color == VPROC_SRC_COLOR_TILE_NV12IW) {
|
| + st->vl_bottom_y_address = t_y_addr + 0x40;
|
| + st->vl_bottom_c_address = t_c_addr + 0x40;
|
| + }
|
| +
|
| + st->vl_src_offset_x = s_ox;
|
| + st->vl_src_offset_y = s_oy;
|
| + st->vl_src_width = s_w;
|
| + st->vl_src_height = s_h;
|
| + st->vl_dest_offset_x = d_ox;
|
| + st->vl_dest_offset_y = d_oy;
|
| + st->vl_dest_width = d_w;
|
| + st->vl_dest_height = d_h;
|
| +
|
| +
|
| + if (o_mode == INTERLACED) {
|
| + st->vl_src_height = s_h / 2;
|
| + st->vl_src_offset_y = s_oy / 2;
|
| + st->vl_dest_height = d_h / 2;
|
| + st->vl_dest_offset_y = d_oy / 2;
|
| + } else {
|
| + if (i_mode == INTERLACED) {
|
| + st->vl_src_height = s_h / 2;
|
| + st->vl_src_offset_y = s_oy / 2;
|
| + }
|
| + }
|
| +}
|
| +
|
| +bool tv_vlayer_start(void)
|
| +{
|
| + int i;
|
| +
|
| + enum s5p_tv_vp_err verr;
|
| + enum s5p_tv_vmx_err merr;
|
| + struct s5p_video_img_address temp_addr;
|
| + struct s5p_img_size img_size;
|
| +
|
| + struct s5p_vl_param param
|
| + = s5ptv_status.vl_basic_param;
|
| +
|
| + u8 contrast = s5ptv_status.vl_contrast;
|
| +
|
| + u32 ty_addr = s5ptv_status.vl_top_y_address;
|
| + u32 tc_addr = s5ptv_status.vl_top_c_address;
|
| + u32 by_addr = s5ptv_status.vl_bottom_y_address;
|
| + u32 bc_addr = s5ptv_status.vl_bottom_c_address;
|
| + u32 endian = param.src_img_endian;
|
| + u32 i_w = param.src_width;
|
| + u32 i_h = param.src_height;
|
| + u32 s_ox = s5ptv_status.vl_src_offset_x;
|
| + u32 s_xf = s5ptv_status.vl_src_x_fact_step;
|
| + u32 s_oy = s5ptv_status.vl_src_offset_y;
|
| + u32 s_w = s5ptv_status.vl_src_width;
|
| + u32 s_h = s5ptv_status.vl_src_height;
|
| + u32 d_ox = s5ptv_status.vl_dest_offset_x;
|
| + u32 d_oy = s5ptv_status.vl_dest_offset_y;
|
| + u32 d_w = s5ptv_status.vl_dest_width;
|
| + u32 d_h = s5ptv_status.vl_dest_height;
|
| + u32 noise = s5ptv_status.vl_sharpness.th_noise;
|
| + u32 saturation = s5ptv_status.vl_saturation;
|
| + u32 alpha = param.alpha;
|
| + u32 priority = param.priority;
|
| + u32 br_offset = s5ptv_status.vl_bright_offset;
|
| +
|
| + bool ipc = s5ptv_status.vl2d_ipc;
|
| + bool l_skip = s5ptv_status.vl_op_mode.line_skip;
|
| + bool bypass = s5ptv_status.vl_bypass_post_process;
|
| + bool po_def = s5ptv_status.vl_poly_filter_default;
|
| + bool bright = s5ptv_status.us_vl_brightness;
|
| + bool w_blend = param.win_blending;
|
| + bool csc_en = s5ptv_status.vl_csc_control.csc_en;
|
| + bool s_off_en = s5ptv_status.vl_csc_control.sub_y_offset_en;
|
| + bool csc_coef_def = s5ptv_status.vl_csc_coef_default;
|
| +
|
| + enum s5p_vp_field f_id = s5ptv_status.field_id;
|
| + enum s5p_vp_mem_mode m_mode = s5ptv_status.vl_op_mode.mem_mode;
|
| + enum s5p_vp_chroma_expansion cro_ex
|
| + = s5ptv_status.vl_op_mode.chroma_exp;
|
| + enum s5p_vp_filed_id_toggle f_id_tog
|
| + = s5ptv_status.vl_op_mode.toggle_id;
|
| + enum s5p_vp_pxl_rate p_rate = s5ptv_status.vl_rate;
|
| + enum s5p_vp_sharpness_control sharp
|
| + = s5ptv_status.vl_sharpness.sharpness;
|
| + enum s5p_vp_csc_type csc_type = s5ptv_status.vl_csc_type;
|
| +
|
| + tv_vp_sw_reset();
|
| + tv_vp_init_field_id(f_id);
|
| + tv_vp_init_op_mode(l_skip, m_mode, cro_ex, f_id_tog);
|
| + tv_vp_init_pixel_rate_control(p_rate);
|
| +
|
| + temp_addr.y_address = param.top_y_address;
|
| + temp_addr.c_address = param.top_c_address;
|
| + img_size.img_width = param.src_width;
|
| + img_size.img_height = param.src_height;
|
| +
|
| + tv_vlayer_set_top_address((unsigned long)&temp_addr);
|
| + tv_vlayer_set_img_size((unsigned long)&img_size);
|
| + tv_vlayer_set_src_size((unsigned long)&img_size);
|
| +
|
| + if (po_def)
|
| + verr = tv_vp_init_layer_def_poly_filter_coef(ty_addr,
|
| + tc_addr, by_addr, bc_addr, endian,
|
| + i_w, i_h, s_ox, s_xf, s_oy, s_w, s_h,
|
| + d_ox, d_oy, d_w, d_h, ipc);
|
| + else
|
| + verr = tv_vp_init_layer(ty_addr, tc_addr, by_addr,
|
| + bc_addr, endian, i_w, i_h, s_ox, s_xf,
|
| + s_oy, s_w, s_h, d_ox, d_oy, d_w, d_h, ipc);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + tv_vp_init_bypass_post_process(bypass);
|
| + tv_vp_init_sharpness(noise, sharp);
|
| + tv_vp_init_saturation(saturation);
|
| + tv_vp_init_brightness(bright);
|
| + tv_vp_init_contrast(contrast);
|
| +
|
| + for (i = VProc_LINE_EQ_0; i <= VProc_LINE_EQ_7; i++) {
|
| + if (s5ptv_status.vl_bc_control[i].eq_num == i)
|
| + verr = tv_vp_init_brightness_contrast_control(
|
| + s5ptv_status.vl_bc_control[i].eq_num,
|
| + s5ptv_status.vl_bc_control[i].intc,
|
| + s5ptv_status.vl_bc_control[i].slope);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| + }
|
| +
|
| + tv_vp_init_brightness_offset(br_offset);
|
| +
|
| + tv_vp_init_csc_control(s_off_en, csc_en);
|
| +
|
| + if (csc_en && csc_coef_def) {
|
| + verr = tv_vp_init_csc_coef_default(csc_type);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| + }
|
| +
|
| + verr = tv_vp_start();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + merr = tv_vm_init_layer(s5ptv_status.tvout_param.disp_mode,
|
| + VM_VIDEO_LAYER, true,
|
| + w_blend, alpha, priority,
|
| + VM_DIRECT_RGB565, false, false, false,
|
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
| + if (merr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + tv_vm_start();
|
| +
|
| + s5ptv_status.vp_layer_enable = true;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_stop(void)
|
| +{
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + tv_vm_set_layer_show(VM_VIDEO_LAYER, false);
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_stop();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + s5ptv_status.vp_layer_enable = false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool tv_vlayer_set_priority(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vmx_err merr;
|
| + u32 pri;
|
| +
|
| + s5ptv_status.vl_basic_param.priority = (unsigned int)(buf_in);
|
| +
|
| + pri = s5ptv_status.vl_basic_param.priority;
|
| +
|
| + merr = tv_vm_set_layer_priority(VM_VIDEO_LAYER, pri);
|
| +
|
| + if (merr != VMIXER_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_blending(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vmx_err merr;
|
| + bool blend;
|
| +
|
| + s5ptv_status.vl_basic_param.win_blending = (bool)(buf_in);
|
| + blend = s5ptv_status.vl_basic_param.win_blending;
|
| +
|
| + merr = tv_vm_set_win_blend(VM_VIDEO_LAYER, blend);
|
| +
|
| + if (merr != VMIXER_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_alpha(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vmx_err merr;
|
| + u32 alpha;
|
| +
|
| + s5ptv_status.vl_basic_param.alpha = (unsigned int)(buf_in);
|
| + alpha = s5ptv_status.vl_basic_param.alpha;
|
| +
|
| + merr = tv_vm_set_layer_alpha(VM_VIDEO_LAYER, alpha);
|
| +
|
| + if (merr != VMIXER_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_field_id(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.field_id = (enum s5p_vp_field)(buf_in);
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_field_id(s5ptv_status.field_id);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_top_address(unsigned long buf_in)
|
| +{
|
| + u32 t_y_addr = 0;
|
| + u32 t_c_addr = 0;
|
| + u32 b_y_addr = 0;
|
| + u32 b_c_addr = 0;
|
| +
|
| + struct s5p_video_img_address *addr =
|
| + (struct s5p_video_img_address *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.top_y_address = addr->y_address;
|
| + s5ptv_status.vl_basic_param.top_c_address = addr->c_address;
|
| +
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + t_y_addr = s5ptv_status.vl_top_y_address;
|
| + t_c_addr = s5ptv_status.vl_top_c_address;
|
| + b_y_addr = s5ptv_status.vl_bottom_y_address;
|
| + b_c_addr = s5ptv_status.vl_bottom_c_address;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_set_top_field_address(t_y_addr, t_c_addr);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + if (check_input_mode(s5ptv_status.src_color) == INTERLACED) {
|
| + tv_vp_set_field_id(s5ptv_status.field_id);
|
| + verr = tv_vp_set_bottom_field_address(b_y_addr, b_c_addr);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| + }
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_bottom_address(unsigned long buf_in)
|
| +{
|
| + u32 t_y_addr = 0;
|
| + u32 t_c_addr = 0;
|
| + u32 b_y_addr = 0;
|
| + u32 b_c_addr = 0;
|
| +
|
| + u32 img_width = s5ptv_status.vl_basic_param.img_width;
|
| +
|
| + struct s5p_video_img_address *addr =
|
| + (struct s5p_video_img_address *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| + enum s5p_vp_src_color s_color = s5ptv_status.src_color;
|
| +
|
| + if (s_color == VPROC_SRC_COLOR_NV12IW) {
|
| + s5ptv_status.vl_basic_param.top_y_address =
|
| + addr->y_address - img_width;
|
| + s5ptv_status.vl_basic_param.top_c_address =
|
| + addr->c_address - img_width;
|
| + }
|
| +
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + t_y_addr = s5ptv_status.vl_top_y_address;
|
| + t_c_addr = s5ptv_status.vl_top_c_address;
|
| + b_y_addr = s5ptv_status.vl_bottom_y_address;
|
| + b_c_addr = s5ptv_status.vl_bottom_c_address;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_set_bottom_field_address(b_y_addr, b_c_addr);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + if (s5ptv_status.src_color == VPROC_SRC_COLOR_NV12IW) {
|
| + verr = tv_vp_set_top_field_address(t_y_addr, t_c_addr);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| + }
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_img_size(unsigned long buf_in)
|
| +{
|
| + struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.img_width = size->img_width;
|
| + s5ptv_status.vl_basic_param.img_height = size->img_height;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_set_img_size(size->img_width, size->img_height);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + VLAYERPRINTK("()\n\r");
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_src_position(unsigned long buf_in)
|
| +{
|
| + struct s5p_img_offset *offset = (struct s5p_img_offset *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.src_offset_x = offset->offset_x;
|
| + s5ptv_status.vl_basic_param.src_offset_y = offset->offset_y;
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_src_position(s5ptv_status.vl_src_offset_x,
|
| + s5ptv_status.vl_src_x_fact_step,
|
| + s5ptv_status.vl_src_offset_y);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_dest_position(unsigned long buf_in)
|
| +{
|
| + u32 d_ox = 0;
|
| + u32 d_oy = 0;
|
| + struct s5p_img_offset *offset = (struct s5p_img_offset *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.dest_offset_x = offset->offset_x;
|
| + s5ptv_status.vl_basic_param.dest_offset_y = offset->offset_y;
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + d_ox = s5ptv_status.vl_dest_offset_x;
|
| + d_oy = s5ptv_status.vl_dest_offset_y;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_dest_position(d_ox, d_oy);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_src_size(unsigned long buf_in)
|
| +{
|
| + u32 s_w = 0;
|
| + u32 s_h = 0;
|
| + u32 d_w = 0;
|
| + u32 d_h = 0;
|
| + bool ipc = false;
|
| +
|
| + struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.src_width = size->img_width;
|
| + s5ptv_status.vl_basic_param.src_height = size->img_height;
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + s_w = s5ptv_status.vl_src_width;
|
| + s_h = s5ptv_status.vl_src_height;
|
| + d_w = s5ptv_status.vl_dest_width;
|
| + d_h = s5ptv_status.vl_dest_height;
|
| + ipc = s5ptv_status.vl2d_ipc;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_src_dest_size(s_w, s_h, d_w, d_h, ipc);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_dest_size(unsigned long buf_in)
|
| +{
|
| + u32 s_w = 0;
|
| + u32 s_h = 0;
|
| + u32 d_w = 0;
|
| + u32 d_h = 0;
|
| + bool ipc = false;
|
| +
|
| + struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_basic_param.dest_width = size->img_width;
|
| + s5ptv_status.vl_basic_param.dest_height = size->img_height;
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + s_w = s5ptv_status.vl_src_width;
|
| + s_h = s5ptv_status.vl_src_height;
|
| + d_w = s5ptv_status.vl_dest_width;
|
| + d_h = s5ptv_status.vl_dest_height;
|
| + ipc = s5ptv_status.vl2d_ipc;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_src_dest_size(s_w, s_h, d_w, d_h, ipc);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_brightness(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.us_vl_brightness = (unsigned short)buf_in;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_brightness(s5ptv_status.us_vl_brightness);
|
| +
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_contrast(unsigned long buf_in)
|
| +{
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + s5ptv_status.vl_contrast = (unsigned char)buf_in;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + tv_vp_set_contrast(s5ptv_status.vl_contrast);
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void tv_vlayer_get_priority(unsigned long buf_out)
|
| +{
|
| + unsigned int *id = (unsigned int *)buf_out;
|
| +
|
| + *id = s5ptv_status.vl_basic_param.priority;
|
| +}
|
| +
|
| +bool tv_vlayer_set_brightness_contrast_control(unsigned long buf_in)
|
| +{
|
| + u32 intc;
|
| + u32 slope;
|
| +
|
| + enum s5p_vp_line_eq eq_num;
|
| + enum s5p_tv_vp_err verr;
|
| + struct s5p_vl_bright_contrast_ctrl *ctrl =
|
| + (struct s5p_vl_bright_contrast_ctrl *)buf_in;
|
| +
|
| + if (ctrl->eq_num > VProc_LINE_EQ_7 ||
|
| + ctrl->eq_num < VProc_LINE_EQ_0) {
|
| + VLAYERPRINTK("(ERR) : invalid eq_num(%d)\n\r", ctrl->eq_num);
|
| + return false;
|
| + }
|
| +
|
| + memcpy((void *)&(s5ptv_status.vl_bc_control[ctrl->eq_num]),
|
| + (const void *)ctrl, sizeof(struct s5p_vl_csc_ctrl));
|
| +
|
| + eq_num = s5ptv_status.vl_bc_control[ctrl->eq_num].eq_num;
|
| + intc = s5ptv_status.vl_bc_control[ctrl->eq_num].intc;
|
| + slope = s5ptv_status.vl_bc_control[ctrl->eq_num].slope;
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_set_brightness_contrast_control(eq_num, intc, slope);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_poly_filter_coef(unsigned long buf_in)
|
| +{
|
| + struct s5p_video_poly_filter_coef *coef =
|
| + (struct s5p_video_poly_filter_coef *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + if (coef->poly_coeff < VPROC_POLY8_Y0_LL ||
|
| + (coef->poly_coeff > VPROC_POLY8_Y3_HH &&
|
| + coef->poly_coeff < VPROC_POLY4_Y0_LL) ||
|
| + coef->poly_coeff > VPROC_POLY4_C1_HH) {
|
| + VLAYERPRINTK("(ERR) : invalid poly_coeff(%d)\n\r",
|
| + coef->poly_coeff);
|
| + return false;
|
| + }
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_init_poly_filter_coef(coef->poly_coeff,
|
| + coef->ch0, coef->ch1,
|
| + coef->ch2, coef->ch3);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + s5ptv_status.vl_poly_filter_default = false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_set_csc_coef(unsigned long buf_in)
|
| +{
|
| + struct s5p_video_csc_coef *coef = (struct s5p_video_csc_coef *)buf_in;
|
| + enum s5p_tv_vp_err verr;
|
| +
|
| + if (coef->csc_coeff < VPROC_CSC_Y2Y_COEF ||
|
| + coef->csc_coeff > VPROC_CSC_CR2CR_COEF) {
|
| + VLAYERPRINTK("(ERR) : invalid csc_coeff(%d)\n\r",
|
| + coef->csc_coeff);
|
| + return false;
|
| + }
|
| +
|
| + if (tv_vlayer_wait_previous_update())
|
| + return false;
|
| +
|
| + verr = tv_vp_init_csc_coef(coef->csc_coeff, coef->coeff);
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + verr = tv_vp_update();
|
| +
|
| + if (verr != VPROC_NO_ERROR)
|
| + return false;
|
| +
|
| + s5ptv_status.vl_csc_coef_default = false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool tv_vlayer_init_param(unsigned long buf_in)
|
| +{
|
| + struct s5p_tv_status *st = &s5ptv_status;
|
| +
|
| + bool i_mode, o_mode; /* 0 for interlaced, 1 for progressive */
|
| +
|
| + switch (st->tvout_param.disp_mode) {
|
| +
|
| + case TVOUT_480P_60_16_9:
|
| + case TVOUT_480P_60_4_3:
|
| + case TVOUT_576P_50_16_9:
|
| + case TVOUT_576P_50_4_3:
|
| + case TVOUT_480P_59:
|
| + st->vl_csc_type = VPROC_CSC_SD_HD;
|
| + break;
|
| +
|
| + case TVOUT_1080I_50:
|
| + case TVOUT_1080I_60:
|
| + case TVOUT_1080P_50:
|
| + case TVOUT_1080P_30:
|
| + case TVOUT_1080P_60:
|
| + case TVOUT_720P_59:
|
| + case TVOUT_1080I_59:
|
| + case TVOUT_1080P_59:
|
| + case TVOUT_720P_50:
|
| + case TVOUT_720P_60:
|
| + st->vl_csc_type = VPROC_CSC_HD_SD;
|
| + break;
|
| +
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + st->vl_csc_control.csc_en = false;
|
| +
|
| +
|
| + i_mode = check_input_mode(st->src_color);
|
| + o_mode = check_output_mode(st->tvout_param.disp_mode,
|
| + st->tvout_param.out_mode);
|
| +
|
| + /* check o_mode */
|
| + if (i_mode == INTERLACED) {
|
| + /* i to i : line skip 1, ipc 0, auto toggle 0 */
|
| + if (o_mode == INTERLACED) {
|
| + st->vl_op_mode.line_skip = true;
|
| + st->vl2d_ipc = false;
|
| + st->vl_op_mode.toggle_id = false;
|
| + } else {
|
| + /* i to p : line skip 1, ipc 1, auto toggle 0 */
|
| + st->vl_op_mode.line_skip = true;
|
| + st->vl2d_ipc = true;
|
| + st->vl_op_mode.toggle_id = false;
|
| + }
|
| + } else {
|
| + /* p to i : line skip 1, ipc 0, auto toggle 0 */
|
| + if (o_mode == INTERLACED) {
|
| + st->vl_op_mode.line_skip = true;
|
| + st->vl2d_ipc = false;
|
| + st->vl_op_mode.toggle_id = false;
|
| + } else {
|
| + /* p to p : line skip 0, ipc 0, auto toggle 0 */
|
| + st->vl_op_mode.line_skip = false;
|
| + st->vl2d_ipc = false;
|
| + st->vl_op_mode.toggle_id = false;
|
| + }
|
| + }
|
| +
|
| + st->vl_op_mode.mem_mode = ((st->src_color == VPROC_SRC_COLOR_NV12) ||
|
| + st->src_color == VPROC_SRC_COLOR_NV12IW) ?
|
| + VPROC_LINEAR_MODE : VPROC_2D_TILE_MODE;
|
| +
|
| + st->vl_op_mode.chroma_exp = 0; /* use only top y addr */
|
| +
|
| + tv_vlayer_calc_inner_values();
|
| +
|
| + if (st->vl_mode) {
|
| + VLAYERPRINTK("(ERR) : Default values are already updated\n\r");
|
| + return true;
|
| + }
|
| +
|
| + /* Initialize Video Layer Parameters to Default Values */
|
| + st->vl_src_x_fact_step = 0;
|
| + st->field_id = VPROC_TOP_FIELD;
|
| + st->vl_rate = VPROC_PIXEL_PER_RATE_1_1;
|
| + st->vl_poly_filter_default = true;
|
| + st->vl_bypass_post_process = false;
|
| + st->vl_saturation = 0x80;
|
| + st->vl_sharpness.th_noise = 0;
|
| + st->vl_sharpness.sharpness = VPROC_SHARPNESS_NO;
|
| + st->us_vl_brightness = 0x00;
|
| + st->vl_contrast = 0x80;
|
| + st->vl_bright_offset = 0x00;
|
| + st->vl_csc_control.sub_y_offset_en = false;
|
| + st->vl_csc_coef_default = true;
|
| + st->vl_bc_control[0].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[1].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[2].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[3].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[4].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[5].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[6].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_bc_control[7].eq_num = VProc_LINE_EQ_7 + 1;
|
| + st->vl_mode = true;
|
| +
|
| + return true;
|
| +}
|
| +
|
|
|