| Index: drivers/media/video/samsung/tv20/vprocessor_s5pv210.c
|
| diff --git a/drivers/media/video/samsung/tv20/vprocessor_s5pv210.c b/drivers/media/video/samsung/tv20/vprocessor_s5pv210.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f90ed3bec63e6aff91962809eb373af1fab57a61
|
| --- /dev/null
|
| +++ b/drivers/media/video/samsung/tv20/vprocessor_s5pv210.c
|
| @@ -0,0 +1,804 @@
|
| +/* linux/drivers/media/video/samsung/tv20/vprocessor_s5pv210.c
|
| +*
|
| +* Copyright (c) 2010 Samsung Electronics Co., Ltd.
|
| +* http://www.samsung.com/
|
| +*
|
| +* S5PV210 - Video Processor raw 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/errno.h>
|
| +#include <linux/string.h>
|
| +#include <linux/delay.h>
|
| +#include <linux/platform_device.h>
|
| +#include <linux/clk.h>
|
| +
|
| +#include <plat/clock.h>
|
| +#include <linux/io.h>
|
| +
|
| +#include "tv_out_s5pv210.h"
|
| +
|
| +#include <mach/regs-vprocessor.h>
|
| +#include "vp_coeff_s5pv210.h"
|
| +
|
| +#ifdef CONFIG_TVOUT_RAW_DBG
|
| +#define S5P_VP_DEBUG 1
|
| +#endif
|
| +
|
| +#ifdef S5P_VP_DEBUG
|
| +#define VPPRINTK(fmt, args...) \
|
| + printk(KERN_INFO "\t\t[VP] %s: " fmt, __func__ , ## args)
|
| +#else
|
| +#define VPPRINTK(fmt, args...)
|
| +#endif
|
| +
|
| +static struct resource *vp_mem;
|
| +void __iomem *vp_base;
|
| +
|
| +/*
|
| +* set
|
| +* - set functions are only called under running video processor
|
| +* - after running set functions,
|
| +* it is need to run tv_vp_update() function
|
| +* for update shadow registers
|
| +*/
|
| +void tv_vp_set_field_id(enum s5p_vp_field mode)
|
| +{
|
| + VPPRINTK("%d\n\r", mode);
|
| +
|
| + writel((mode == VPROC_TOP_FIELD) ?
|
| + vp_base + S5P_VP_FIELD_ID_TOP :
|
| + vp_base + S5P_VP_FIELD_ID_BOTTOM,
|
| + vp_base + S5P_VP_FIELD_ID);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_FIELD_ID));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_set_top_field_address(u32 top_y_addr, u32 top_c_addr)
|
| +{
|
| + VPPRINTK("0x%x,0x%x\n\r", top_y_addr, top_c_addr);
|
| +
|
| + if (VP_PTR_ILLEGAL(top_y_addr) || VP_PTR_ILLEGAL(top_c_addr)) {
|
| + VPPRINTK(" address is not double word align = 0x%x,0x%x\n\r",
|
| + top_y_addr, top_c_addr);
|
| + return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
|
| + }
|
| +
|
| + writel(top_y_addr, vp_base + S5P_VP_TOP_Y_PTR);
|
| +
|
| + writel(top_c_addr, vp_base + S5P_VP_TOP_C_PTR);
|
| +
|
| + VPPRINTK("0x%x,0x%x\n\r", readl(vp_base + S5P_VP_TOP_Y_PTR),
|
| + readl(vp_base + S5P_VP_TOP_C_PTR));
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_set_bottom_field_address(
|
| + u32 bottom_y_addr, u32 bottom_c_addr)
|
| +{
|
| + VPPRINTK("0x%x,0x%x\n\r", bottom_y_addr, bottom_c_addr);
|
| +
|
| + if (VP_PTR_ILLEGAL(bottom_y_addr) || VP_PTR_ILLEGAL(bottom_c_addr)) {
|
| + VPPRINTK(" address is not double word align = 0x%x,0x%x\n\r",
|
| + bottom_y_addr, bottom_c_addr);
|
| + return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
|
| + }
|
| +
|
| + writel(bottom_y_addr, vp_base + S5P_VP_BOT_Y_PTR);
|
| +
|
| + writel(bottom_c_addr, vp_base + S5P_VP_BOT_C_PTR);
|
| +
|
| + VPPRINTK("0x%x,0x%x\n\r", readl(vp_base + S5P_VP_BOT_Y_PTR),
|
| + readl(vp_base + S5P_VP_BOT_C_PTR));
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +/* TO-DO :: VP_TILE_SIZE_Y, vp_base+S5P_VP_IMG_SIZE_Y --> what is diff.? */
|
| +enum s5p_tv_vp_err tv_vp_set_img_size(u32 img_width, u32 img_height)
|
| +{
|
| + VPPRINTK("%d,%d\n\r", img_width, img_height);
|
| +
|
| + if (VP_IMG_SIZE_ILLEGAL(img_width) ||
|
| + VP_IMG_SIZE_ILLEGAL(img_height)) {
|
| + VPPRINTK("image full size is not double word align = %d,%d\n\r",
|
| + img_width, img_height);
|
| + return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
|
| + }
|
| +
|
| + writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height),
|
| + vp_base + S5P_VP_IMG_SIZE_Y);
|
| +
|
| + writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height / 2),
|
| + vp_base + S5P_VP_IMG_SIZE_C);
|
| +
|
| + VPPRINTK("0x%x,0x%x\n\r", readl(vp_base + S5P_VP_IMG_SIZE_Y),
|
| + readl(vp_base + S5P_VP_IMG_SIZE_C));
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +void tv_vp_set_src_position(u32 src_off_x,
|
| + u32 src_x_fract_step,
|
| + u32 src_off_y)
|
| +{
|
| + VPPRINTK("%d,%d,%d)\n\r", src_off_x, src_x_fract_step, src_off_y);
|
| +
|
| + writel(VP_SRC_H_POSITION(src_off_x) |
|
| + VP_SRC_X_FRACT_STEP(src_x_fract_step),
|
| + vp_base + S5P_VP_SRC_H_POSITION);
|
| + writel(VP_SRC_V_POSITION(src_off_y), vp_base + S5P_VP_SRC_V_POSITION);
|
| +
|
| + VPPRINTK("0x%x,0x%x\n\r", readl(vp_base + S5P_VP_SRC_H_POSITION),
|
| + readl(vp_base + S5P_VP_SRC_V_POSITION));
|
| +}
|
| +
|
| +void tv_vp_set_dest_position(u32 dst_off_x,
|
| + u32 dst_off_y)
|
| +{
|
| + VPPRINTK("%d,%d)\n\r", dst_off_x, dst_off_y);
|
| +
|
| +
|
| + writel(VP_DST_H_POSITION(dst_off_x), vp_base + S5P_VP_DST_H_POSITION);
|
| + writel(VP_DST_V_POSITION(dst_off_y), vp_base + S5P_VP_DST_V_POSITION);
|
| +
|
| + VPPRINTK("0x%x,0x%x\n\r", readl(vp_base + S5P_VP_DST_H_POSITION),
|
| + readl(vp_base + S5P_VP_DST_V_POSITION));
|
| +}
|
| +
|
| +void tv_vp_set_src_dest_size(u32 src_width,
|
| + u32 src_height,
|
| + u32 dst_width,
|
| + u32 dst_height,
|
| + bool ipc_2d)
|
| +{
|
| + u32 h_ratio = (src_width << 16) / dst_width;
|
| + u32 v_ratio = (ipc_2d) ?
|
| + ((src_height << 17) / dst_height) :
|
| + ((src_height << 16) / dst_height);
|
| +
|
| + VPPRINTK("(%d,%d,%d,%d)++\n\r", src_width, src_height,
|
| + dst_width, dst_height);
|
| +
|
| + writel(VP_SRC_WIDTH(src_width), vp_base + S5P_VP_SRC_WIDTH);
|
| + writel(VP_SRC_HEIGHT(src_height), vp_base + S5P_VP_SRC_HEIGHT);
|
| + writel(VP_DST_WIDTH(dst_width), vp_base + S5P_VP_DST_WIDTH);
|
| + writel(VP_DST_HEIGHT(dst_height), vp_base + S5P_VP_DST_HEIGHT) ;
|
| + writel(VP_H_RATIO(h_ratio), vp_base + S5P_VP_H_RATIO);
|
| + writel(VP_V_RATIO(v_ratio), vp_base + S5P_VP_V_RATIO);
|
| +
|
| + writel((ipc_2d) ? (readl(vp_base + S5P_VP_MODE) | VP_2D_IPC_ON) :
|
| + (readl(vp_base + S5P_VP_MODE) & ~VP_2D_IPC_ON),
|
| + vp_base + S5P_VP_MODE);
|
| +
|
| + VPPRINTK("%d,%d,%d,%d,0x%x,0x%x\n\r", readl(vp_base + S5P_VP_SRC_WIDTH),
|
| + readl(vp_base + S5P_VP_SRC_HEIGHT),
|
| + readl(vp_base + S5P_VP_DST_WIDTH),
|
| + readl(vp_base + S5P_VP_DST_HEIGHT),
|
| + readl(vp_base + S5P_VP_H_RATIO),
|
| + readl(vp_base + S5P_VP_V_RATIO));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_set_poly_filter_coef(enum s5p_vp_poly_coeff poly_coeff,
|
| + signed char ch0,
|
| + signed char ch1,
|
| + signed char ch2,
|
| + signed char ch3)
|
| +{
|
| + VPPRINTK("%d,%d,%d,%d,%d)\n\r", poly_coeff, ch0, ch1, ch2, ch3);
|
| +
|
| + if (poly_coeff > VPROC_POLY4_C1_HH || poly_coeff < VPROC_POLY8_Y0_LL ||
|
| + (poly_coeff > VPROC_POLY8_Y3_HH &&
|
| + poly_coeff < VPROC_POLY4_Y0_LL)) {
|
| +
|
| + VPPRINTK("invaild poly_coeff parameter \n\r");
|
| + return S5P_TV_VP_ERR_INVALID_PARAM;
|
| + }
|
| +
|
| + writel((((0xff&ch0) << 24) | ((0xff&ch1) << 16) |
|
| + ((0xff&ch2) << 8) | (0xff&ch3)),
|
| + vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
|
| +
|
| + VPPRINTK("0x%08x, 0x%08x\n\r",
|
| + readl(vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4),
|
| + vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +void tv_vp_set_poly_filter_coef_default(u32 h_ratio, u32 v_ratio)
|
| +{
|
| + enum s5p_tv_vp_filter_h_pp e_h_filter;
|
| + enum s5p_tv_vp_filter_v_pp e_v_filter;
|
| + u8 *poly_flt_coeff;
|
| + int i, j;
|
| +
|
| + VPPRINTK("%d,%d\n\r", h_ratio, v_ratio);
|
| +
|
| + /*
|
| + * For the real interlace mode,
|
| + * the vertical ratio should be used after divided by 2.
|
| + * Because in the interlace mode,
|
| + * all the VP output is used for SDOUT display
|
| + * and it should be the same as one field of the progressive mode.
|
| + * Therefore the same filter coefficients should be used
|
| + * for the same the final output video.
|
| + * When half of the interlace V_RATIO is
|
| + * same as the progressive V_RATIO,
|
| + * the final output video scale is same. (20051104,ishan)
|
| + */
|
| +
|
| + /*Horizontal Y 8tap */
|
| + /*Horizontal C 4tap */
|
| + /* if (h_ratio <= 0x200) */ /* 720->720 or zoom in */
|
| +
|
| + if (h_ratio <= (0x1 << 16)) { /* 720->720 or zoom in */
|
| + e_h_filter = VPROC_PP_H_NORMAL;
|
| + }
|
| +
|
| + /* else if (h_ratio <= 0x240) */ /* 720->640 */ /* ?? */
|
| + else if (h_ratio <= (0x9 << 13)) /* 720->640 */ /* ?? */
|
| + e_h_filter = VPROC_PP_H_8_9 ;
|
| +
|
| + /* else if(h_ratio <= 0x400) */ /* 2->1 */ /* 2 */
|
| + else if (h_ratio <= (0x1 << 17)) /* 2->1 */ /* 2 */
|
| + e_h_filter = VPROC_PP_H_1_2;
|
| +
|
| + /* else if (h_ratio <= 0x600) */ /* 3->1 */ /* 3 */
|
| + else if (h_ratio <= (0x3 << 16)) /* 2->1 */ /* 2 */
|
| + e_h_filter = VPROC_PP_H_1_3;
|
| + else /* 0x800 */
|
| + e_h_filter = VPROC_PP_H_1_4; /* 4->1 */ /* 4 */
|
| +
|
| + /* Vertical Y 4tap */
|
| + /* if (v_ratio <= 0x100) */ /* 720->720 or zoom in*/
|
| + if (v_ratio <= (0x1 << 16)) /* 720->720 or zoom in*/
|
| + e_v_filter = VPROC_PP_V_NORMAL;
|
| + else if (v_ratio <= (0x5 << 14)) /* 4->3*/
|
| + e_v_filter = VPROC_PP_V_3_4;
|
| + else if (v_ratio <= (0x3 << 15)) /*6->5*/
|
| + e_v_filter = VPROC_PP_V_5_6;
|
| + else if (v_ratio <= (0x1 << 17)) /* 2->1*/
|
| + e_v_filter = VPROC_PP_V_1_2;
|
| + else if (v_ratio <= (0x3 << 16)) /* 3->1*/
|
| + e_v_filter = VPROC_PP_V_1_3;
|
| + else /* 0x400 */ /* 4->1*/
|
| + e_v_filter = VPROC_PP_V_1_4;
|
| +
|
| + poly_flt_coeff = (u8 *)(g_s_vp8tap_coef_y_h + e_h_filter * 16 * 8);
|
| +
|
| + for (i = 0; i < 4; i++) {
|
| + for (j = 0; j < 4; j++) {
|
| + tv_vp_set_poly_filter_coef(
|
| + VPROC_POLY8_Y0_LL + (i*4) + j,
|
| + *(poly_flt_coeff + 4*j*8 + (7 - i)),
|
| + *(poly_flt_coeff + (4*j + 1)*8 + (7 - i)),
|
| + *(poly_flt_coeff + (4*j + 2)*8 + (7 - i)),
|
| + *(poly_flt_coeff + (4*j + 3)*8 + (7 - i)));
|
| + }
|
| + }
|
| +
|
| + poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_c_h + e_h_filter * 16 * 4);
|
| +
|
| + for (i = 0; i < 2; i++) {
|
| + for (j = 0; j < 4; j++) {
|
| + tv_vp_set_poly_filter_coef(
|
| + VPROC_POLY4_C0_LL + (i*4) + j,
|
| + *(poly_flt_coeff + 4*j*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
|
| + }
|
| + }
|
| +
|
| + poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_y_v + e_v_filter * 16 * 4);
|
| +
|
| + for (i = 0; i < 4; i++) {
|
| + for (j = 0; j < 4; j++) {
|
| + tv_vp_set_poly_filter_coef(
|
| + VPROC_POLY4_Y0_LL + (i*4) + j,
|
| + *(poly_flt_coeff + 4*j*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
|
| + *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
|
| + }
|
| + }
|
| +
|
| + VPPRINTK("%d,%d\n\r", e_h_filter, e_v_filter);
|
| +}
|
| +
|
| +void tv_vp_set_src_dest_size_with_default_poly_filter_coef(u32 src_width,
|
| + u32 src_height,
|
| + u32 dst_width,
|
| + u32 dst_height,
|
| + bool ipc_2d)
|
| +{
|
| + u32 h_ratio = (src_width << 16) / dst_width;
|
| + u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
|
| + ((src_height << 16) / dst_height);
|
| +
|
| + tv_vp_set_src_dest_size(src_width, src_height,
|
| + dst_width, dst_height, ipc_2d);
|
| + tv_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_set_brightness_contrast_control(
|
| + enum s5p_vp_line_eq eq_num,
|
| + u32 intc,
|
| + u32 slope)
|
| +{
|
| + VPPRINTK("%d,%d,%d\n\r", eq_num, intc, slope);
|
| +
|
| + if (eq_num > VProc_LINE_EQ_7 || eq_num < VProc_LINE_EQ_0) {
|
| + VPPRINTK("invaild eq_num parameter \n\r");
|
| + return S5P_TV_VP_ERR_INVALID_PARAM;
|
| + }
|
| +
|
| + writel(VP_LINE_INTC(intc) | VP_LINE_SLOPE(slope),
|
| +
|
| + vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
|
| +
|
| + VPPRINTK("0x%08x, 0x%08x\n\r",
|
| + readl(vp_base + S5P_PP_LINE_EQ0 + eq_num*4),
|
| + vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +void tv_vp_set_brightness(bool brightness)
|
| +{
|
| + unsigned short i;
|
| +
|
| + VPPRINTK("%d\n\r", brightness);
|
| +
|
| + g_vp_contrast_brightness =
|
| + VP_LINE_INTC_CLEAR(g_vp_contrast_brightness) |
|
| + VP_LINE_INTC(brightness);
|
| +
|
| + for (i = 0; i < 8; i++) {
|
| + writel(g_vp_contrast_brightness,
|
| + vp_base + S5P_PP_LINE_EQ0 + i*4);
|
| + }
|
| +
|
| + VPPRINTK("%d\n\r", g_vp_contrast_brightness);
|
| +}
|
| +
|
| +void tv_vp_set_contrast(u8 contrast)
|
| +{
|
| + unsigned short i;
|
| +
|
| + VPPRINTK("%d\n\r", contrast);
|
| +
|
| + g_vp_contrast_brightness =
|
| + VP_LINE_SLOPE_CLEAR(g_vp_contrast_brightness) |
|
| + VP_LINE_SLOPE(contrast);
|
| +
|
| + for (i = 0; i < 8; i++) {
|
| + writel(g_vp_contrast_brightness,
|
| + vp_base + S5P_PP_LINE_EQ0 + i*4);
|
| + }
|
| +
|
| + VPPRINTK("%d\n\r", g_vp_contrast_brightness);
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_update(void)
|
| +{
|
| + VPPRINTK("()\n\r");
|
| +
|
| + writel(readl(vp_base + S5P_VP_SHADOW_UPDATE) |
|
| + S5P_VP_SHADOW_UPDATE_ENABLE,
|
| + vp_base + S5P_VP_SHADOW_UPDATE);
|
| +
|
| + VPPRINTK("()\n\r");
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +enum s5p_vp_field tv_vp_get_field_id(void)
|
| +{
|
| + VPPRINTK("()\n\r");
|
| + return ((readl(vp_base + S5P_VP_FIELD_ID) == S5P_VP_FIELD_ID_BOTTOM) ?
|
| + VPROC_BOTTOM_FIELD : VPROC_TOP_FIELD);
|
| +}
|
| +
|
| +unsigned short tv_vp_get_update_status(void)
|
| +{
|
| + VPPRINTK("()\n\r");
|
| + return readl(vp_base + S5P_VP_SHADOW_UPDATE) &
|
| + S5P_VP_SHADOW_UPDATE_ENABLE;
|
| +}
|
| +
|
| +/*
|
| +* initialization - iniization functions are
|
| + only called under stopping video processor
|
| +*/
|
| +void tv_vp_init_field_id(enum s5p_vp_field mode)
|
| +{
|
| + tv_vp_set_field_id(mode);
|
| +}
|
| +
|
| +void tv_vp_init_op_mode(bool line_skip,
|
| + enum s5p_vp_mem_mode mem_mode,
|
| + enum s5p_vp_chroma_expansion chroma_exp,
|
| + enum s5p_vp_filed_id_toggle toggle_id)
|
| +{
|
| + u32 temp_reg;
|
| + VPPRINTK("%d,%d,%d,%d\n\r", line_skip, mem_mode, chroma_exp, toggle_id);
|
| +
|
| + temp_reg = (line_skip) ? VP_LINE_SKIP_ON : VP_LINE_SKIP_OFF;
|
| + temp_reg |= (mem_mode == VPROC_2D_TILE_MODE) ?
|
| + VP_MEM_2D_MODE : VP_MEM_LINEAR_MODE;
|
| + temp_reg |= (chroma_exp == VPROC_USING_C_TOP_BOTTOM) ?
|
| + VP_CHROMA_USE_TOP_BOTTOM : VP_CHROMA_USE_TOP;
|
| + temp_reg |= (toggle_id == S5P_TV_VP_FILED_ID_TOGGLE_VSYNC) ?
|
| + VP_FIELD_ID_TOGGLE_VSYNC : VP_FIELD_ID_TOGGLE_USER;
|
| +
|
| + writel(temp_reg, vp_base + S5P_VP_MODE);
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_MODE));
|
| +}
|
| +
|
| +void tv_vp_init_pixel_rate_control(enum s5p_vp_pxl_rate rate)
|
| +{
|
| + VPPRINTK("%d\n\r", rate);
|
| +
|
| + writel(VP_PEL_RATE_CTRL(rate), vp_base + S5P_VP_PER_RATE_CTRL);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_PER_RATE_CTRL));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_layer(u32 top_y_addr,
|
| + u32 top_c_addr,
|
| + u32 bottom_y_addr,
|
| + u32 bottom_c_addr,
|
| + enum s5p_endian_type src_img_endian,
|
| + u32 img_width,
|
| + u32 img_height,
|
| + u32 src_off_x,
|
| + u32 src_x_fract_step,
|
| + u32 src_off_y,
|
| + u32 src_width,
|
| + u32 src_height,
|
| + u32 dst_off_x,
|
| + u32 dst_off_y,
|
| + u32 dst_width,
|
| + u32 dst_height,
|
| + bool ipc_2d)
|
| +{
|
| + enum s5p_tv_vp_err error = VPROC_NO_ERROR;
|
| +
|
| + VPPRINTK("%d\n\r", src_img_endian);
|
| +
|
| + writel(1, vp_base + S5P_VP_ENDIAN_MODE);
|
| +
|
| + error = tv_vp_set_top_field_address(top_y_addr, top_c_addr);
|
| +
|
| + if (error != VPROC_NO_ERROR)
|
| + return error;
|
| +
|
| + error = tv_vp_set_bottom_field_address(bottom_y_addr, bottom_c_addr);
|
| +
|
| + if (error != VPROC_NO_ERROR)
|
| + return error;
|
| +
|
| + error = tv_vp_set_img_size(img_width, img_height);
|
| +
|
| + if (error != VPROC_NO_ERROR)
|
| + return error;
|
| +
|
| + tv_vp_set_src_position(src_off_x, src_x_fract_step, src_off_y);
|
| +
|
| + tv_vp_set_dest_position(dst_off_x, dst_off_y);
|
| +
|
| + tv_vp_set_src_dest_size(
|
| + src_width, src_height, dst_width, dst_height, ipc_2d);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_ENDIAN_MODE));
|
| +
|
| + return error;
|
| +
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_layer_def_poly_filter_coef(
|
| + u32 top_y_addr,
|
| + u32 top_c_addr,
|
| + u32 bottom_y_addr,
|
| + u32 bottom_c_addr,
|
| + enum s5p_endian_type src_img_endian,
|
| + u32 img_width,
|
| + u32 img_height,
|
| + u32 src_off_x,
|
| + u32 src_x_fract_step,
|
| + u32 src_off_y,
|
| + u32 src_width,
|
| + u32 src_height,
|
| + u32 dst_off_x,
|
| + u32 dst_off_y,
|
| + u32 dst_width,
|
| + u32 dst_height,
|
| + bool ipc_2d)
|
| +{
|
| + enum s5p_tv_vp_err error = VPROC_NO_ERROR;
|
| +
|
| + u32 h_ratio = (src_width << 16) / dst_width;
|
| + u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
|
| + ((src_height << 16) / dst_height);
|
| +
|
| + tv_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
|
| + error = tv_vp_init_layer(top_y_addr, top_c_addr,
|
| + bottom_y_addr, bottom_c_addr,
|
| + src_img_endian,
|
| + img_width, img_height,
|
| + src_off_x, src_x_fract_step, src_off_y,
|
| + src_width, src_height,
|
| + dst_off_x, dst_off_y,
|
| + dst_width, dst_height,
|
| + ipc_2d);
|
| + return error;
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_poly_filter_coef(
|
| + enum s5p_vp_poly_coeff poly_coeff,
|
| + signed char ch0,
|
| + signed char ch1,
|
| + signed char ch2,
|
| + signed char ch3)
|
| +{
|
| + return tv_vp_set_poly_filter_coef(poly_coeff, ch0, ch1, ch2, ch3);
|
| +}
|
| +
|
| +void tv_vp_init_bypass_post_process(bool bypass)
|
| +{
|
| + VPPRINTK("%d\n\r", bypass);
|
| +
|
| + writel((bypass) ? VP_BY_PASS_ENABLE : VP_BY_PASS_DISABLE,
|
| + vp_base + S5P_PP_BYPASS);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BYPASS));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_csc_coef(
|
| + enum s5p_vp_csc_coeff csc_coeff, u32 coeff)
|
| +{
|
| + VPPRINTK("%d,%d\n\r", csc_coeff, coeff);
|
| +
|
| + if (csc_coeff > VPROC_CSC_CR2CR_COEF ||
|
| + csc_coeff < VPROC_CSC_Y2Y_COEF) {
|
| + VPPRINTK("invaild csc_coeff parameter \n\r");
|
| + return S5P_TV_VP_ERR_INVALID_PARAM;
|
| + }
|
| +
|
| + writel(VP_CSC_COEF(coeff),
|
| + vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4);
|
| +
|
| + VPPRINTK("0x%08x\n\r",
|
| + readl(vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4));
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +void tv_vp_init_saturation(u32 sat)
|
| +{
|
| + VPPRINTK("%d\n\r", sat);
|
| +
|
| + writel(VP_SATURATION(sat), vp_base + S5P_PP_SATURATION);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SATURATION));
|
| +}
|
| +
|
| +void tv_vp_init_sharpness(u32 th_h_noise,
|
| + enum s5p_vp_sharpness_control sharpness)
|
| +{
|
| + VPPRINTK("%d,%d\n\r", th_h_noise, sharpness);
|
| +
|
| + writel(VP_TH_HNOISE(th_h_noise) | VP_SHARPNESS(sharpness),
|
| + vp_base + S5P_PP_SHARPNESS);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SHARPNESS));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_brightness_contrast_control(
|
| + enum s5p_vp_line_eq eq_num,
|
| + u32 intc,
|
| + u32 slope)
|
| +{
|
| + return tv_vp_set_brightness_contrast_control(eq_num, intc, slope);
|
| +}
|
| +
|
| +void tv_vp_init_brightness(bool brightness)
|
| +{
|
| + tv_vp_set_brightness(brightness);
|
| +}
|
| +
|
| +
|
| +void tv_vp_init_contrast(u8 contrast)
|
| +{
|
| + tv_vp_set_contrast(contrast);
|
| +}
|
| +
|
| +void tv_vp_init_brightness_offset(u32 offset)
|
| +{
|
| + VPPRINTK("%d\n\r", offset);
|
| +
|
| + writel(VP_BRIGHT_OFFSET(offset), vp_base + S5P_PP_BRIGHT_OFFSET);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BRIGHT_OFFSET));
|
| +}
|
| +
|
| +void tv_vp_init_csc_control(bool sub_y_offset_en, bool csc_en)
|
| +{
|
| + u32 temp_reg;
|
| + VPPRINTK("%d,%d\n\r", sub_y_offset_en, csc_en);
|
| +
|
| + temp_reg = (sub_y_offset_en) ? VP_SUB_Y_OFFSET_ENABLE :
|
| + VP_SUB_Y_OFFSET_DISABLE;
|
| + temp_reg |= (csc_en) ? VP_CSC_ENABLE : VP_CSC_DISABLE;
|
| + writel(temp_reg, vp_base + S5P_PP_CSC_EN);
|
| +
|
| + VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_CSC_EN));
|
| +}
|
| +
|
| +enum s5p_tv_vp_err tv_vp_init_csc_coef_default(enum s5p_vp_csc_type csc_type)
|
| +{
|
| + VPPRINTK("%d\n\r", csc_type);
|
| +
|
| + switch (csc_type) {
|
| +
|
| + case VPROC_CSC_SD_HD:
|
| + writel(Y2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2Y_COEF);
|
| + writel(CB2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2Y_COEF);
|
| + writel(CR2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2Y_COEF);
|
| + writel(Y2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CB_COEF);
|
| + writel(CB2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CB_COEF);
|
| + writel(CR2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CB_COEF);
|
| + writel(Y2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CR_COEF);
|
| + writel(CB2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CR_COEF);
|
| + writel(CR2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CR_COEF);
|
| + break;
|
| +
|
| + case VPROC_CSC_HD_SD:
|
| + writel(Y2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2Y_COEF);
|
| + writel(CB2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2Y_COEF);
|
| + writel(CR2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2Y_COEF);
|
| + writel(Y2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CB_COEF);
|
| + writel(CB2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CB_COEF);
|
| + writel(CR2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CB_COEF);
|
| + writel(Y2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CR_COEF);
|
| + writel(CB2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CR_COEF);
|
| + writel(CR2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CR_COEF);
|
| + break;
|
| +
|
| + default:
|
| + VPPRINTK("invalid csc_type parameter = %d\n\r", csc_type);
|
| + return S5P_TV_VP_ERR_INVALID_PARAM;
|
| + }
|
| +
|
| + VPPRINTK("0x%08x,0x%08x,0x%08x,0x%08x,0x%08x, \
|
| + 0x%08x,0x%08x,0x%08x,0x%08x)\n\r",
|
| + readl(vp_base + S5P_PP_CSC_Y2Y_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CB2Y_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CR2Y_COEF),
|
| + readl(vp_base + S5P_PP_CSC_Y2CB_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CB2CB_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CR2CB_COEF),
|
| + readl(vp_base + S5P_PP_CSC_Y2CR_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CB2CR_COEF),
|
| + readl(vp_base + S5P_PP_CSC_CR2CR_COEF));
|
| +
|
| + return VPROC_NO_ERROR;
|
| +}
|
| +
|
| +/*
|
| +* start - start functions are only called under stopping video processor
|
| +*/
|
| +enum s5p_tv_vp_err tv_vp_start(void)
|
| +{
|
| + enum s5p_tv_vp_err error = VPROC_NO_ERROR;
|
| +
|
| + VPPRINTK("()\n\r");
|
| +
|
| + writel(VP_ON_ENABLE, vp_base + S5P_VP_ENABLE);
|
| +
|
| + error = tv_vp_update();
|
| +
|
| + VPPRINTK("()\n\r");
|
| + return error;
|
| +}
|
| +
|
| +/*
|
| +* stop - stop functions are only called under running video processor
|
| +*/
|
| +enum s5p_tv_vp_err tv_vp_stop(void)
|
| +{
|
| + enum s5p_tv_vp_err error = VPROC_NO_ERROR;
|
| +
|
| + VPPRINTK("()\n\r");
|
| +
|
| + writel((readl(vp_base + S5P_VP_ENABLE) & ~VP_ON_ENABLE),
|
| + vp_base + S5P_VP_ENABLE);
|
| +
|
| + error = tv_vp_update();
|
| +
|
| + while (!(readl(vp_base + S5P_VP_ENABLE) & VP_POWER_DOWN_RDY))
|
| + msleep(1);
|
| +
|
| + return error;
|
| +}
|
| +
|
| +void tv_vp_sw_reset(void)
|
| +{
|
| + VPPRINTK("()\n\r");
|
| +
|
| + writel((readl(vp_base + S5P_VP_SRESET) | VP_SOFT_RESET),
|
| + vp_base + S5P_VP_SRESET);
|
| +
|
| + while (readl(vp_base + S5P_VP_SRESET) & VP_SOFT_RESET)
|
| + msleep(10);
|
| +
|
| + VPPRINTK("()\n\r");
|
| +}
|
| +
|
| +int __init tv_vp_probe(struct platform_device *pdev, u32 res_num)
|
| +{
|
| + struct resource *res;
|
| + size_t size;
|
| +
|
| + res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
|
| +
|
| + if (res == NULL) {
|
| + dev_err(&pdev->dev,
|
| + "failed to get memory region resource\n");
|
| + goto error;
|
| +
|
| + }
|
| +
|
| + size = (res->end - res->start) + 1;
|
| +
|
| + vp_mem = request_mem_region(res->start, size, pdev->name);
|
| +
|
| + if (vp_mem == NULL) {
|
| + dev_err(&pdev->dev,
|
| + "failed to get memory region\n");
|
| + goto error;
|
| +
|
| + }
|
| +
|
| + vp_base = ioremap(res->start, size);
|
| +
|
| + if (vp_base == NULL) {
|
| + dev_err(&pdev->dev,
|
| + "failed to ioremap address region\n");
|
| + goto error;
|
| +
|
| +
|
| + }
|
| +
|
| + return 0;
|
| +error:
|
| + return -ENOENT;
|
| +
|
| +}
|
| +
|
| +int __init tv_vp_release(struct platform_device *pdev)
|
| +{
|
| + iounmap(vp_base);
|
| +
|
| + /* remove memory region */
|
| + if (vp_mem != NULL) {
|
| + if (release_resource(vp_mem))
|
| + dev_err(&pdev->dev,
|
| + "Can't remove tvout drv !!\n");
|
| +
|
| + kfree(vp_mem);
|
| +
|
| + vp_mem = NULL;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
|
|