media: add osd & ge2d driver

PD#138714: add osd & ge2d driver

Change-Id: I70c0e1e2b5e29a158b8a41e27bbc4db2fd49bb9a
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
This commit is contained in:
Pengcheng Chen
2017-01-24 13:06:19 +08:00
committed by Jianxin Pan
parent 384fc38e44
commit 4dafe9905e
70 changed files with 18063 additions and 185 deletions

View File

@@ -13540,3 +13540,22 @@ AMLOGIC driver for vout
M: Evoke Zhang <evoke.zhang@amlogic.com>
F: drivers/amlogic/dispaly/*
AMLOGIC ION device
M: Simon Zheng <simon.zheng@amlogic.com>
F: drivers/amlogic/media/common/ion_dev/*
AMLOGIC multimedia osd & ge2d
M: Pengcheng Chen <pengcheng.chen@amlogic.com>
F: drivers/amlogic/media/osd/*
F: drivers/amlogic/media/osd_ext/*
F: drivers/amlogic/media/logo/*
F: drivers/amlogic/media/common/ge2d/*
F: include/linux/amlogic/media/ge2d/*
F: arch/arm64/configs/meson64_defconfig
F: drivers/amlogic/media/Kconfig
F: drivers/amlogic/media/Makefile
F: arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
F: arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts
F: drivers/amlogic/clk/clk_media.c
F: include/linux/amlogic/media/vout/vout_notify.h

View File

@@ -306,8 +306,46 @@
"mailbox_1",
"mailbox_2";
};
};
meson-fb {
compatible = "amlogic, meson-fb";
memory-region = <&fb_reserved>;
dev_name = "meson-fb";
status = "okay";
interrupts = <0 3 1
0 89 1>;
interrupt-names = "viu-vsync", "rdma";
mem_size = <0x01851000 0x00100000>; /* fb0/fb1 memory size */
display_mode_default = "1080p60hz";
scale_mode = <1>;
/** 0:VPU free scale 1:OSD free scale 2:OSD super scale */
display_size_default = <1920 1080 1920 3240 32>;
/*1920*1080*4*3 = 0x17BB000*/
logo_addr = "0x3d851000";
/*ion base + fb0 memory size for uboot logo osd1*/
};
ge2d {
compatible = "amlogic, ge2d";
dev_name = "ge2d";
status = "okay";
interrupts = <0 150 1>;
interrupt-names = "ge2d";
clocks = <&clkc CLKID_VAPB_MUX>,
<&clkc CLKID_GE2D_GATE>,
<&clkc CLKID_G2D>;
clock-names = "clk_vapb_0",
"clk_ge2d",
"clk_ge2d_gate";
};
rdma{
compatible = "amlogic, meson, rdma";
dev_name = "amlogic-rdma";
status = "ok";
interrupts = <0 89 1>;
interrupt-names = "rdma";
};
};
&efuse {
status = "ok";
};

View File

@@ -307,8 +307,45 @@
/*all channels use the default clock source XTAL_CLK*/
/*and you can shoose it in file dt-bindings/pwm/meson.h*/
};
};
meson-fb {
compatible = "amlogic, meson-fb";
memory-region = <&fb_reserved>;
dev_name = "meson-fb";
status = "okay";
interrupts = <0 3 1
0 89 1>;
interrupt-names = "viu-vsync", "rdma";
mem_size = <0x01851000 0x00100000>; /* fb0/fb1 memory size */
display_mode_default = "1080p60hz";
scale_mode = <1>;
/** 0:VPU free scale 1:OSD free scale 2:OSD super scale */
display_size_default = <1920 1080 1920 3240 32>;
/*1920*1080*4*3 = 0x17BB000*/
logo_addr = "0x3d851000";
/*ion base + fb0 memory size for uboot logo osd1*/
};
ge2d {
compatible = "amlogic, ge2d";
dev_name = "ge2d";
status = "okay";
interrupts = <0 150 1>;
interrupt-names = "ge2d";
clocks = <&clkc CLKID_VAPB_MUX>,
<&clkc CLKID_GE2D_GATE>,
<&clkc CLKID_G2D>;
clock-names = "clk_vapb_0",
"clk_ge2d",
"clk_ge2d_gate";
};
rdma{
compatible = "amlogic, meson, rdma";
dev_name = "amlogic-rdma";
status = "ok";
interrupts = <0 89 1>;
interrupt-names = "rdma";
};
};
&efuse {
status = "ok";
};

View File

@@ -61,6 +61,11 @@
reg = <0x0 0x07300000 0x0 0x100000>;
no-map;
};
fb_reserved:linux,meson-fb {
compatible = "amlogic, fb-memory";
size = <0x0 0x2000000>;
no-map;
};
di_reserved:linux,di {
compatible = "amlogic, di-mem";
@@ -301,8 +306,45 @@
/*all channels use the default clock source XTAL_CLK*/
/*and you can shoose it in file dt-bindings/pwm/meson.h*/
};
};
meson-fb {
compatible = "amlogic, meson-fb";
memory-region = <&fb_reserved>;
dev_name = "meson-fb";
status = "okay";
interrupts = <0 3 1
0 89 1>;
interrupt-names = "viu-vsync", "rdma";
mem_size = <0x01851000 0x00100000>; /* fb0/fb1 memory size */
display_mode_default = "1080p60hz";
scale_mode = <1>;
/** 0:VPU free scale 1:OSD free scale 2:OSD super scale */
display_size_default = <1920 1080 1920 3240 32>;
/*1920*1080*4*3 = 0x17BB000*/
logo_addr = "0x3d851000";
/*ion base + fb0 memory size for uboot logo osd1*/
};
ge2d {
compatible = "amlogic, ge2d";
dev_name = "ge2d";
status = "okay";
interrupts = <0 150 1>;
interrupt-names = "ge2d";
clocks = <&clkc CLKID_VAPB_MUX>,
<&clkc CLKID_GE2D_GATE>,
<&clkc CLKID_G2D>;
clock-names = "clk_vapb_0",
"clk_ge2d",
"clk_ge2d_gate";
};
rdma{
compatible = "amlogic, meson, rdma";
dev_name = "amlogic-rdma";
status = "ok";
interrupts = <0 89 1>;
interrupt-names = "rdma";
};
};
&efuse {
status = "ok";
};

View File

@@ -207,6 +207,44 @@
dev_name = "cvbsout";
status = "okay";
};
meson-fb {
compatible = "amlogic, meson-fb";
/* memory-region = <&fb_reserved>; */
dev_name = "meson-fb";
status = "okay";
interrupts = <0 3 1
0 89 1>;
interrupt-names = "viu-vsync", "rdma";
mem_size = <0x01851000 0x00100000>; /* fb0/fb1 memory size */
display_mode_default = "1080p60hz";
scale_mode = <1>;
/** 0:VPU free scale 1:OSD free scale 2:OSD super scale */
display_size_default = <1920 1080 1920 3240 32>;
/*1920*1080*4*3 = 0x17BB000*/
logo_addr = "0x3d851000";
/*ion base + fb0 memory size for uboot logo osd1*/
};
ge2d {
compatible = "amlogic, ge2d";
dev_name = "ge2d";
status = "okay";
interrupts = <0 150 1>;
interrupt-names = "ge2d";
clocks = <&clkc CLKID_VAPB_MUX>,
<&clkc CLKID_GE2D_GATE>,
<&clkc CLKID_G2D>;
clock-names = "clk_vapb_0",
"clk_ge2d",
"clk_ge2d_gate";
};
rdma{
compatible = "amlogic, meson, rdma";
dev_name = "amlogic-rdma";
status = "ok";
interrupts = <0 89 1>;
interrupt-names = "rdma";
};
};
&efuse {

View File

@@ -192,7 +192,9 @@ CONFIG_AMLOGIC_MEDIA_COMMON=y
CONFIG_AMLOGIC_MEDIA_DRIVERS=y
CONFIG_AMLOGIC_MEDIA_CODEC_MM=y
CONFIG_AMLOGIC_MEDIA_CANVAS=y
CONFIG_AMLOGIC_MEDIA_GE2D=y
CONFIG_AMLOGIC_ION=y
CONFIG_AMLOGIC_MEDIA_RDMA=y
CONFIG_AMLOGIC_MEDIA_VFM=y
CONFIG_AMLOGIC_VPU=y
CONFIG_AMLOGIC_VOUT=y
@@ -200,6 +202,10 @@ CONFIG_AMLOGIC_VOUT_SERVE=y
CONFIG_AMLOGIC_CVBS_OUTPUT=y
CONFIG_AMLOGIC_WSS=y
CONFIG_AMLOGIC_VDAC=y
CONFIG_AMLOGIC_MEDIA_FB=y
CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA=y
CONFIG_AMLOGIC_MEDIA_FB_OSD2_ENABLE=y
CONFIG_AMLOGIC_MEDIA_FB_OSD2_CURSOR=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
@@ -263,6 +269,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_FB=y
CONFIG_UHID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_XHCI_HCD=y

View File

@@ -763,6 +763,7 @@ void amlogic_init_media(void)
clks[CLKID_VPU_MUX] = clk_register(NULL,
vpu_clk_hws[CLKID_VPU_MUX - CLKID_VPU_P0_MUX]);
WARN_ON(IS_ERR(clks[CLKID_VPU_MUX]));
clk_prepare_enable(clks[CLKID_VPU_MUX]);
/* cts_vapb_clk */
clks[CLKID_VAPB_P0_COMP] = clk_register_composite(NULL,
@@ -794,6 +795,7 @@ void amlogic_init_media(void)
clks[CLKID_VAPB_MUX] = clk_register(NULL,
vapb_clk_hws[CLKID_VAPB_MUX - CLKID_VAPB_P0_MUX]);
WARN_ON(IS_ERR(clks[CLKID_VAPB_MUX]));
clk_prepare_enable(clks[CLKID_VAPB_MUX]);
clks[CLKID_GE2D_GATE] = clk_register(NULL,
&ge2d_gate.hw);

View File

@@ -42,6 +42,9 @@ endif
if AMLOGIC_MEDIA_DRIVERS
source "drivers/amlogic/media/video_sink/Kconfig"
source "drivers/amlogic/media/vout/Kconfig"
source "drivers/amlogic/media/osd/Kconfig"
source "drivers/amlogic/media/osd_ext/Kconfig"
source "drivers/amlogic/media/logo/Kconfig"
endif
endmenu

View File

@@ -2,3 +2,6 @@ obj-$(CONFIG_AMLOGIC_MEDIA_COMMON) += common/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += frame_sync/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += video_sink/
obj-$(CONFIG_AMLOGIC_VOUT) += vout/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += osd/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += osd_ext/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += logo/

View File

@@ -1,9 +1,8 @@
#Ascending by module name's ASCII
source "drivers/amlogic/media/common/codec_mm/Kconfig"
source "drivers/amlogic/media/common/canvas/Kconfig"
source "drivers/amlogic/media/common/ge2d/Kconfig"
source "drivers/amlogic/media/common/ion_dev/Kconfig"
source "drivers/amlogic/media/common/rdma/Kconfig"
source "drivers/amlogic/media/common/vfm/Kconfig"
source "drivers/amlogic/media/common/ge2d/Kconfig"
source "drivers/amlogic/media/common/ion_dev/Kconfig"
source "drivers/amlogic/media/common/vpu/Kconfig"

View File

@@ -2,7 +2,7 @@
obj-y += arch/
obj-$(CONFIG_AMLOGIC_MEDIA_CANVAS) += canvas/
obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += codec_mm/
obj-$(CONFIG_AMLOGIC_GE2D) += ge2d/
obj-$(CONFIG_AMLOGIC_MEDIA_GE2D) += ge2d/
obj-$(CONFIG_AMLOGIC_ION) += ion_dev/
obj-$(CONFIG_AMLOGIC_MEDIA_RDMA) += rdma/
obj-$(CONFIG_AMLOGIC_MEDIA_VFM) += vfm/

View File

@@ -1,7 +1,7 @@
#
# GE2D Module
#
config AMLOGIC_GE2D
config AMLOGIC_MEDIA_GE2D
bool "Amlogic GE2D Module"
default n
help

View File

@@ -7,5 +7,6 @@ ge2d-objs = bitblt.o \
ge2d_main.o \
blend.o
obj-$(CONFIG_AMLOGIC_GE2D) += ge2d.o
obj-$(CONFIG_AMLOGIC_MEDIA_GE2D) += ge2d.o
ccflags-y += -Iinclude/linux/media/ge2d/
ccflags-y += -Idrivers/amlogic/media/osd/

View File

@@ -143,3 +143,119 @@ void blend_noblk(struct ge2d_context_s *wq,
ge2d_wq_add_work(wq);
}
EXPORT_SYMBOL(blend_noblk);
void blend_noalpha(struct ge2d_context_s *wq,
int src_x, int src_y, int src_w, int src_h,
int src2_x, int src2_y, int src2_w, int src2_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int op)
{
struct ge2d_cmd_s *ge2d_cmd_cfg = ge2d_wq_get_cmd(wq);
ge2d_cmd_cfg->src1_x_start = src_x;
ge2d_cmd_cfg->src1_x_end = src_x + src_w - 1;
ge2d_cmd_cfg->src1_y_start = src_y;
ge2d_cmd_cfg->src1_y_end = src_y + src_h - 1;
ge2d_cmd_cfg->src2_x_start = src2_x;
ge2d_cmd_cfg->src2_x_end = src2_x + src2_w - 1;
ge2d_cmd_cfg->src2_y_start = src2_y;
ge2d_cmd_cfg->src2_y_end = src2_y + src2_h - 1;
ge2d_cmd_cfg->dst_x_start = dst_x;
ge2d_cmd_cfg->dst_x_end = dst_x + dst_w - 1;
ge2d_cmd_cfg->dst_y_start = dst_y;
ge2d_cmd_cfg->dst_y_end = dst_y + dst_h - 1;
/* if ((dst_w != src_w) || (dst_h != src_h)) { */
if (1) {
ge2d_cmd_cfg->sc_hsc_en = 1;
ge2d_cmd_cfg->sc_vsc_en = 1;
ge2d_cmd_cfg->hsc_rpt_p0_num = 1;
ge2d_cmd_cfg->vsc_rpt_l0_num = 1;
ge2d_cmd_cfg->hsc_div_en = 1;
} else {
ge2d_cmd_cfg->sc_hsc_en = 0;
ge2d_cmd_cfg->sc_vsc_en = 0;
ge2d_cmd_cfg->hsc_rpt_p0_num = 0;
ge2d_cmd_cfg->vsc_rpt_l0_num = 0;
ge2d_cmd_cfg->hsc_div_en = 0;
}
ge2d_cmd_cfg->color_blend_mode = (op >> 24) & 0xff;
ge2d_cmd_cfg->color_src_blend_factor = (op >> 20) & 0xf;
ge2d_cmd_cfg->color_dst_blend_factor = (op >> 16) & 0xf;
ge2d_cmd_cfg->alpha_src_blend_factor = (op >> 4) & 0xf;
ge2d_cmd_cfg->alpha_dst_blend_factor = (op >> 0) & 0xf;
if (ge2d_cmd_cfg->color_blend_mode >= BLENDOP_LOGIC) {
ge2d_cmd_cfg->color_logic_op =
ge2d_cmd_cfg->color_blend_mode - BLENDOP_LOGIC;
ge2d_cmd_cfg->color_blend_mode = OPERATION_LOGIC;
}
ge2d_cmd_cfg->alpha_blend_mode = OPERATION_LOGIC;
ge2d_cmd_cfg->alpha_logic_op = LOGIC_OPERATION_SET;
ge2d_cmd_cfg->wait_done_flag = 1;
ge2d_wq_add_work(wq);
}
EXPORT_SYMBOL(blend_noalpha);
void blend_noalpha_noblk(struct ge2d_context_s *wq,
int src_x, int src_y, int src_w, int src_h,
int src2_x, int src2_y, int src2_w, int src2_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int op)
{
struct ge2d_cmd_s *ge2d_cmd_cfg = ge2d_wq_get_cmd(wq);
ge2d_cmd_cfg->src1_x_start = src_x;
ge2d_cmd_cfg->src1_x_end = src_x + src_w - 1;
ge2d_cmd_cfg->src1_y_start = src_y;
ge2d_cmd_cfg->src1_y_end = src_y + src_h - 1;
ge2d_cmd_cfg->src2_x_start = src2_x;
ge2d_cmd_cfg->src2_x_end = src2_x + src2_w - 1;
ge2d_cmd_cfg->src2_y_start = src2_y;
ge2d_cmd_cfg->src2_y_end = src2_y + src2_h - 1;
ge2d_cmd_cfg->dst_x_start = dst_x;
ge2d_cmd_cfg->dst_x_end = dst_x + dst_w - 1;
ge2d_cmd_cfg->dst_y_start = dst_y;
ge2d_cmd_cfg->dst_y_end = dst_y + dst_h - 1;
/* if ((dst_w != src_w) || (dst_h != src_h)) { */
if (1) {
ge2d_cmd_cfg->sc_hsc_en = 1;
ge2d_cmd_cfg->sc_vsc_en = 1;
ge2d_cmd_cfg->hsc_rpt_p0_num = 1;
ge2d_cmd_cfg->vsc_rpt_l0_num = 1;
ge2d_cmd_cfg->hsc_div_en = 1;
} else {
ge2d_cmd_cfg->sc_hsc_en = 0;
ge2d_cmd_cfg->sc_vsc_en = 0;
ge2d_cmd_cfg->hsc_rpt_p0_num = 0;
ge2d_cmd_cfg->vsc_rpt_l0_num = 0;
ge2d_cmd_cfg->hsc_div_en = 0;
}
ge2d_cmd_cfg->color_blend_mode = (op >> 24) & 0xff;
ge2d_cmd_cfg->color_src_blend_factor = (op >> 20) & 0xf;
ge2d_cmd_cfg->color_dst_blend_factor = (op >> 16) & 0xf;
ge2d_cmd_cfg->alpha_src_blend_factor = (op >> 4) & 0xf;
ge2d_cmd_cfg->alpha_dst_blend_factor = (op >> 0) & 0xf;
if (ge2d_cmd_cfg->color_blend_mode >= BLENDOP_LOGIC) {
ge2d_cmd_cfg->color_logic_op =
ge2d_cmd_cfg->color_blend_mode - BLENDOP_LOGIC;
ge2d_cmd_cfg->color_blend_mode = OPERATION_LOGIC;
}
ge2d_cmd_cfg->alpha_blend_mode = OPERATION_LOGIC;
ge2d_cmd_cfg->alpha_logic_op = LOGIC_OPERATION_SET;
ge2d_cmd_cfg->wait_done_flag = 0;
ge2d_wq_add_work(wq);
}
EXPORT_SYMBOL(blend_noalpha_noblk);

View File

@@ -19,7 +19,7 @@
#include <linux/types.h>
/* Amlogic Headers */
#include <linux/amlogic/media/old_cpu_version.h>
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/ge2d/ge2d.h>
/* Local Headers */
@@ -633,6 +633,22 @@ void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg)
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0x3;
} else if (cfg->use_matrix_default == MATRIX_RGB_TO_FULL_RANGE_YCC) {
cfg->matrix_coef[0] = 0x132;
cfg->matrix_coef[1] = 0x259;
cfg->matrix_coef[2] = 0x75;
cfg->matrix_coef[3] = 0x1f53;
cfg->matrix_coef[4] = 0x1ead;
cfg->matrix_coef[5] = 0x200;
cfg->matrix_coef[6] = 0x200;
cfg->matrix_coef[7] = 0x1e53;
cfg->matrix_coef[8] = 0x1fad;
cfg->matrix_offset[0] = 0;
cfg->matrix_offset[1] = 128;
cfg->matrix_offset[2] = 128;
cfg->matrix_sat_in_en = 0;
cfg->matrix_minus_16_ctrl = 0;
cfg->matrix_sign_ctrl = 0;
}
if (cfg->matrix_minus_16_ctrl)
@@ -726,32 +742,6 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg)
x_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 11, 1);
y_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 10, 1);
/* #if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 */
if (get_cpu_type() == MESON_CPU_MAJOR_ID_M6) {
if (x_yc_ratio) {
if (cfg->src1_x_rev) {
x_extra_bit_start = 0;
x_extra_bit_end = 3;
x_chr_phase = 0x80;
} else {
x_extra_bit_start = 3;
x_extra_bit_end = 0;
x_chr_phase = 0x08;
}
}
if (y_yc_ratio) {
if (cfg->src1_y_rev) {
y_extra_bit_start = 2;
y_extra_bit_end = 3;
y_chr_phase = 0xc4;
} else {
y_extra_bit_start = 3;
y_extra_bit_end = 2;
y_chr_phase = 0x4c;
}
}
} else {
/* #else */
if (x_yc_ratio) {
if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) {
x_extra_bit_start = 3;
@@ -774,9 +764,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg)
y_extra_bit_end = 3;
y_chr_phase = 0x4c;
}
}
}
/* #endif */
ge2d_reg_write(GE2D_SRC1_X_START_END,
(x_extra_bit_start << 30) | /* x start extra */

View File

@@ -20,11 +20,13 @@
#include <linux/io.h>
#include <linux/amlogic/iomap.h>
#include <linux/amlogic/media/old_cpu_version.h>
#include <linux/amlogic/cpu_version.h>
#include "ge2d_log.h"
#define GE2DBUS_REG_ADDR(reg) (((reg - 0x1800) << 2))
extern unsigned int ge2d_dump_reg_cnt;
extern unsigned int ge2d_dump_reg_enable;
struct reg_map_s {
unsigned int phy_addr;
@@ -40,18 +42,21 @@ static struct reg_map_s reg_map = {
static int check_map_flag(unsigned int addr)
{
int ret = 0;
if (reg_map.flag)
return 1;
reg_map.vir_addr = ioremap(reg_map.phy_addr, reg_map.size);
if (!reg_map.vir_addr) {
pr_info("failed map phy: 0x%x\n", addr);
return 0;
ret = 0;
} else {
reg_map.flag = 1;
pr_info("mapped phy: 0x%x\n", reg_map.phy_addr);
ret = 1;
}
reg_map.flag = 1;
pr_info("mapped phy: 0x%x\n", reg_map.phy_addr);
return 1;
return ret;
}
static uint32_t ge2d_reg_read(unsigned int reg)
@@ -74,7 +79,6 @@ static uint32_t ge2d_reg_read(unsigned int reg)
static void ge2d_reg_write(unsigned int reg, unsigned int val)
{
unsigned int ret = 0;
unsigned int addr = 0;
if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)
@@ -88,8 +92,11 @@ static void ge2d_reg_write(unsigned int reg, unsigned int val)
writel(val, reg_map.vir_addr + addr);
/* ret = readl(reg_map.vir_addr + addr); */
}
ge2d_log_dbg2("write(0x%x, 0x%x)=0x%x\n",
reg_map.phy_addr + addr, val, ret);
if (ge2d_dump_reg_enable && (ge2d_dump_reg_cnt > 0)) {
ge2d_log_info("write(0x%x) = 0x%x\n",
reg, val);
ge2d_dump_reg_cnt--;
}
}
static inline uint32_t ge2d_vcbus_read(uint32_t reg)

View File

@@ -16,9 +16,7 @@
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
@@ -39,7 +37,7 @@
/* Amlogic Headers */
#include <linux/amlogic/media/ge2d/ge2d.h>
#include <linux/amlogic/media/ge2d/ge2d_cmd.h>
#include <linux/amlogic/media/old_cpu_version.h>
#include <linux/amlogic/cpu_version.h>
/* Local Headers */
#include "ge2dgen.h"
@@ -60,6 +58,8 @@ struct ge2d_device_s {
static struct ge2d_device_s ge2d_device;
static DEFINE_MUTEX(ge2d_mutex);
unsigned int ge2d_log_level;
unsigned int ge2d_dump_reg_enable;
unsigned int ge2d_dump_reg_cnt;
static int ge2d_open(struct inode *inode, struct file *file);
static long ge2d_ioctl(struct file *filp, unsigned int cmd,
@@ -75,6 +75,19 @@ static ssize_t log_level_show(struct class *cla,
static ssize_t log_level_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count);
static ssize_t dump_reg_enable_show(struct class *cla,
struct class_attribute *attr,
char *buf);
static ssize_t dump_reg_enable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count);
static ssize_t dump_reg_cnt_show(struct class *cla,
struct class_attribute *attr,
char *buf);
static ssize_t dump_reg_cnt_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count);
static const struct file_operations ge2d_fops = {
.owner = THIS_MODULE,
@@ -93,6 +106,10 @@ static struct class_attribute ge2d_class_attrs[] = {
free_queue_status_show, NULL),
__ATTR(log_level, 0644,
log_level_show, log_level_store),
__ATTR(dump_reg_enable, 0644,
dump_reg_enable_show, dump_reg_enable_store),
__ATTR(dump_reg_cnt, 0644,
dump_reg_cnt_show, dump_reg_cnt_store),
__ATTR_NULL
};
@@ -101,6 +118,47 @@ static struct class ge2d_class = {
.class_attrs = ge2d_class_attrs,
};
static ssize_t dump_reg_enable_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "%d\n", ge2d_dump_reg_enable);
}
static ssize_t dump_reg_enable_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
ge2d_log_info("ge2d dump_reg_enbale: %d->%d\n",
ge2d_dump_reg_enable, res);
ge2d_dump_reg_enable = res;
return count;
}
static ssize_t dump_reg_cnt_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "%d\n", ge2d_dump_reg_cnt);
}
static ssize_t dump_reg_cnt_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
ge2d_log_info("ge2d dump_reg: %d->%d\n", ge2d_dump_reg_cnt, res);
ge2d_dump_reg_cnt = res;
return count;
}
static ssize_t log_level_show(struct class *cla,
struct class_attribute *attr,
@@ -123,19 +181,6 @@ static ssize_t log_level_store(struct class *cla,
return count;
}
static bool command_valid(unsigned int cmd)
{
bool ret = false;
#ifdef CONFIG_COMPAT
ret = (cmd <= GE2D_CONFIG_EX32 &&
cmd >= GE2D_ANTIFLICKER_ENABLE);
#else
ret = (cmd <= GE2D_CONFIG_EX &&
cmd >= GE2D_ANTIFLICKER_ENABLE);
#endif
return ret;
}
static int ge2d_open(struct inode *inode, struct file *file)
{
struct ge2d_context_s *context = NULL;
@@ -161,22 +206,53 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
int ret = 0;
#ifdef CONFIG_COMPAT
struct compat_config_para_s __user *uf;
struct compat_config_para_ex_s __user *uf_ex;
int r = 0;
int i, j;
#endif
void __user *argp = (void __user *)args;
if (!command_valid(cmd))
return -1;
context = (struct ge2d_context_s *)filp->private_data;
memset(&ge2d_config, 0, sizeof(struct config_para_s));
memset(&ge2d_config_ex, 0, sizeof(struct config_para_ex_s));
switch (cmd) {
case GE2D_CONFIG:
case GE2D_SRCCOLORKEY:
ret = copy_from_user(&ge2d_config,
argp, sizeof(struct config_para_s));
break;
#ifdef CONFIG_COMPAT
case GE2D_SRCCOLORKEY32:
uf = (struct compat_config_para_s *)argp;
r = get_user(ge2d_config.src_dst_type, &uf->src_dst_type);
r |= get_user(ge2d_config.alu_const_color,
&uf->alu_const_color);
r |= get_user(ge2d_config.src_format, &uf->src_format);
r |= get_user(ge2d_config.dst_format, &uf->dst_format);
for (i = 0; i < 4; i++) {
r |= get_user(ge2d_config.src_planes[i].addr,
&uf->src_planes[i].addr);
r |= get_user(ge2d_config.src_planes[i].w,
&uf->src_planes[i].w);
r |= get_user(ge2d_config.src_planes[i].h,
&uf->src_planes[i].h);
}
for (j = 0; j < 4; j++) {
r |= get_user(ge2d_config.dst_planes[j].addr,
&uf->dst_planes[j].addr);
r |= get_user(ge2d_config.dst_planes[j].w,
&uf->dst_planes[j].w);
r |= get_user(ge2d_config.dst_planes[j].h,
&uf->dst_planes[j].h);
}
r |= copy_from_user(&ge2d_config.src_key, &uf->src_key,
sizeof(struct src_key_ctrl_s));
if (r) {
pr_err("GE2D_SRCCOLORKEY32 get parameter failed .\n");
return -EFAULT;
}
break;
#endif
#ifdef CONFIG_COMPAT
case GE2D_CONFIG32:
uf = (struct compat_config_para_s *)argp;
@@ -214,9 +290,96 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
ret = copy_from_user(&ge2d_config_ex, argp,
sizeof(struct config_para_ex_s));
break;
#ifdef CONFIG_COMPAT
case GE2D_CONFIG_EX32:
uf_ex = (struct compat_config_para_ex_s *)argp;
r = copy_from_user(&ge2d_config_ex.src_para, &uf_ex->src_para,
sizeof(struct src_dst_para_ex_s));
r |= copy_from_user(&ge2d_config_ex.src2_para,
&uf_ex->src2_para,
sizeof(struct src_dst_para_ex_s));
r |= copy_from_user(&ge2d_config_ex.dst_para, &uf_ex->dst_para,
sizeof(struct src_dst_para_ex_s));
r |= copy_from_user(&ge2d_config_ex.src_key, &uf_ex->src_key,
sizeof(struct src_key_ctrl_s));
r |= copy_from_user(&ge2d_config_ex.src2_key, &uf_ex->src2_key,
sizeof(struct src_key_ctrl_s));
r |= get_user(ge2d_config_ex.alu_const_color,
&uf_ex->alu_const_color);
r |= get_user(ge2d_config_ex.src1_gb_alpha,
&uf_ex->src1_gb_alpha);
r |= get_user(ge2d_config_ex.op_mode, &uf_ex->op_mode);
r |= get_user(ge2d_config_ex.bitmask_en, &uf_ex->bitmask_en);
r |= get_user(ge2d_config_ex.bytemask_only,
&uf_ex->bytemask_only);
r |= get_user(ge2d_config_ex.bitmask, &uf_ex->bitmask);
r |= get_user(ge2d_config_ex.dst_xy_swap, &uf_ex->dst_xy_swap);
r |= get_user(ge2d_config_ex.hf_init_phase,
&uf_ex->hf_init_phase);
r |= get_user(ge2d_config_ex.hf_rpt_num, &uf_ex->hf_rpt_num);
r |= get_user(ge2d_config_ex.hsc_start_phase_step,
&uf_ex->hsc_start_phase_step);
r |= get_user(ge2d_config_ex.hsc_phase_slope,
&uf_ex->hsc_phase_slope);
r |= get_user(ge2d_config_ex.vf_init_phase,
&uf_ex->vf_init_phase);
r |= get_user(ge2d_config_ex.vf_rpt_num, &uf_ex->vf_rpt_num);
r |= get_user(ge2d_config_ex.vsc_start_phase_step,
&uf_ex->vsc_start_phase_step);
r |= get_user(ge2d_config_ex.vsc_phase_slope,
&uf_ex->vsc_phase_slope);
r |= get_user(ge2d_config_ex.src1_vsc_phase0_always_en,
&uf_ex->src1_vsc_phase0_always_en);
r |= get_user(ge2d_config_ex.src1_hsc_phase0_always_en,
&uf_ex->src1_hsc_phase0_always_en);
r |= get_user(ge2d_config_ex.src1_hsc_rpt_ctrl,
&uf_ex->src1_hsc_rpt_ctrl);
r |= get_user(ge2d_config_ex.src1_vsc_rpt_ctrl,
&uf_ex->src1_vsc_rpt_ctrl);
for (i = 0; i < 4; i++) {
r |= get_user(ge2d_config_ex.src_planes[i].addr,
&uf_ex->src_planes[i].addr);
r |= get_user(ge2d_config_ex.src_planes[i].w,
&uf_ex->src_planes[i].w);
r |= get_user(ge2d_config_ex.src_planes[i].h,
&uf_ex->src_planes[i].h);
}
for (i = 0; i < 4; i++) {
r |= get_user(ge2d_config_ex.src2_planes[i].addr,
&uf_ex->src2_planes[i].addr);
r |= get_user(ge2d_config_ex.src2_planes[i].w,
&uf_ex->src2_planes[i].w);
r |= get_user(ge2d_config_ex.src2_planes[i].h,
&uf_ex->src2_planes[i].h);
}
for (j = 0; j < 4; j++) {
r |= get_user(ge2d_config_ex.dst_planes[j].addr,
&uf_ex->dst_planes[j].addr);
r |= get_user(ge2d_config_ex.dst_planes[j].w,
&uf_ex->dst_planes[j].w);
r |= get_user(ge2d_config_ex.dst_planes[j].h,
&uf_ex->dst_planes[j].h);
}
if (r) {
pr_err("GE2D_CONFIG_EX32 get parameter failed .\n");
return -EFAULT;
}
break;
#endif
case GE2D_SET_COEF:
case GE2D_ANTIFLICKER_ENABLE:
break;
case GE2D_CONFIG_OLD:
case GE2D_CONFIG_EX_OLD:
case GE2D_SRCCOLORKEY_OLD:
pr_err("ioctl not support yed.\n");
return -EINVAL;
default:
ret = copy_from_user(&para, argp, sizeof(struct ge2d_para_s));
break;
@@ -231,6 +394,9 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
ret = ge2d_context_config(context, &ge2d_config);
break;
case GE2D_CONFIG_EX:
#ifdef CONFIG_COMPAT
case GE2D_CONFIG_EX32:
#endif
ret = ge2d_context_config_ex(context, &ge2d_config_ex);
break;
case GE2D_SET_COEF:
@@ -240,6 +406,15 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
ge2d_antiflicker_enable(context, args);
break;
case GE2D_SRCCOLORKEY:
#ifdef CONFIG_COMPAT
case GE2D_SRCCOLORKEY32:
#endif
ge2d_log_dbg("src colorkey...,key_enable=0x%x,key_color=0x%x,key_mask=0x%x,key_mode=0x%x\n",
ge2d_config.src_key.key_enable,
ge2d_config.src_key.key_color,
ge2d_config.src_key.key_mask,
ge2d_config.src_key.key_mode);
ge2dgen_src_key(context, ge2d_config.src_key.key_enable,
ge2d_config.src_key.key_color,
ge2d_config.src_key.key_mask,
@@ -334,6 +509,28 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
para.dst_rect.w, para.dst_rect.h,
para.op);
break;
case GE2D_BLEND_NOALPHA:
ge2d_log_dbg("blend_noalpha ...\n");
blend_noalpha(context,
para.src1_rect.x, para.src1_rect.y,
para.src1_rect.w, para.src1_rect.h,
para.src2_rect.x, para.src2_rect.y,
para.src2_rect.w, para.src2_rect.h,
para.dst_rect.x, para.dst_rect.y,
para.dst_rect.w, para.dst_rect.h,
para.op);
break;
case GE2D_BLEND_NOALPHA_NOBLOCK:
ge2d_log_dbg("blend_noalpha ...,noblk\n");
blend_noalpha_noblk(context,
para.src1_rect.x, para.src1_rect.y,
para.src1_rect.w, para.src1_rect.h,
para.src2_rect.x, para.src2_rect.y,
para.src2_rect.w, para.src2_rect.h,
para.dst_rect.x, para.dst_rect.y,
para.dst_rect.w, para.dst_rect.h,
para.op);
break;
case GE2D_BLIT_NOALPHA:
/* bitblt_noalpha */
ge2d_log_dbg("blit_noalpha...\n");
@@ -413,6 +610,7 @@ static int ge2d_probe(struct platform_device *pdev)
int ret = 0;
int irq = 0;
struct reset_control *rstc = NULL;
struct clk *clk_gate;
struct clk *clk;
/* get interrupt resource */
irq = platform_get_irq_byname(pdev, "ge2d");
@@ -422,35 +620,42 @@ static int ge2d_probe(struct platform_device *pdev)
goto failed1;
}
rstc = devm_reset_control_get(&pdev->dev, "ge2d");
if (IS_ERR(rstc)) {
ge2d_log_err("get ge2d rstc error: %lx\n", PTR_ERR(rstc));
rstc = NULL;
clk_gate = devm_clk_get(&pdev->dev, "clk_ge2d_gate");
if (IS_ERR(clk_gate)) {
ge2d_log_err("cannot get clock\n");
clk_gate = NULL;
ret = -ENOENT;
goto failed1;
}
ge2d_log_info("clock source clk_ge2d_gate %p\n", clk_gate);
clk_prepare_enable(clk_gate);
reset_control_assert(rstc);
clk = clk_get(&pdev->dev, "clk_ge2d");
clk = devm_clk_get(&pdev->dev, "clk_ge2d");
if (IS_ERR(clk)) {
ge2d_log_err("cannot get clock\n");
clk = NULL;
ret = -ENOENT;
goto failed1;
}
ge2d_log_info("clock clk_ge2d source %p\n", clk);
clk_prepare_enable(clk);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
struct clk *clk_vapb0;
int vapb_rate;
clk_vapb0 = clk_get(&pdev->dev, "clk_vapb_0");
clk_vapb0 = devm_clk_get(&pdev->dev, "clk_vapb_0");
ge2d_log_info("clock source clk_vapb_0 %p\n", clk_vapb0);
clk_prepare_enable(clk_vapb0);
if (!IS_ERR(clk_vapb0)) {
vapb_rate = clk_get_rate(clk_vapb0);
clk_put(clk_vapb0);
clk_set_rate(clk_vapb0, vapb_rate);
ge2d_log_info("ge2d clock is %d MHZ\n",
vapb_rate/1000000);
}
}
ret = ge2d_wq_init(pdev, irq, rstc, clk);
ret = ge2d_wq_init(pdev, irq, rstc, clk_gate);
failed1:
return ret;
}

View File

@@ -28,7 +28,6 @@
#include <linux/clk.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/color.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#include <linux/amlogic/media/ge2d/ge2d.h>
@@ -41,6 +40,7 @@
#include "ge2d_reg.h"
#include "ge2d_wq.h"
#include "osd_io.h"
#define OSD1_CANVAS_INDEX 0x40
#define OSD2_CANVAS_INDEX 0x43
#define OSD3_CANVAS_INDEX 0x41
@@ -52,6 +52,39 @@ static int ge2d_irq = -ENXIO;
static struct reset_control *ge2d_rstc;
static struct clk *ge2d_clk;
enum color_index_e {
COLOR_INDEX_02_PAL4 = 2,
COLOR_INDEX_04_PAL16 = 4,
COLOR_INDEX_08_PAL256 = 8,
COLOR_INDEX_16_655 = 9,
COLOR_INDEX_16_844 = 10,
COLOR_INDEX_16_6442 = 11,
COLOR_INDEX_16_4444_R = 12,
COLOR_INDEX_16_4642_R = 13,
COLOR_INDEX_16_1555_A = 14,
COLOR_INDEX_16_4444_A = 15,
COLOR_INDEX_16_565 = 16,
COLOR_INDEX_24_6666_A = 19,
COLOR_INDEX_24_6666_R = 20,
COLOR_INDEX_24_8565 = 21,
COLOR_INDEX_24_5658 = 22,
COLOR_INDEX_24_888_B = 23,
COLOR_INDEX_24_RGB = 24,
COLOR_INDEX_32_BGRX = 25,
COLOR_INDEX_32_XBGR = 26,
COLOR_INDEX_32_RGBX = 27,
COLOR_INDEX_32_XRGB = 28,
COLOR_INDEX_32_BGRA = 29,
COLOR_INDEX_32_ABGR = 30,
COLOR_INDEX_32_RGBA = 31,
COLOR_INDEX_32_ARGB = 32,
COLOR_INDEX_YUV_422 = 33,
};
static const int bpp_type_lut[] = {
/* 16bit */
COLOR_INDEX_16_655, /* 0 */
@@ -115,28 +148,14 @@ static const int default_ge2d_color_lut[] = {
GE2D_FORMAT_S32_ARGB,/* BPP_TYPE_32_ARGB=32, */
};
static long ge2d_sleep_on(wait_queue_head_t *q, long timeout)
{
DEFINE_WAIT(wait);
prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
timeout = schedule_timeout(timeout);
finish_wait(q, &wait);
return timeout;
}
static int ge2d_clk_config(bool enable)
{
if (ge2d_clk == NULL)
return -1;
if (enable) {
if (ge2d_rstc != NULL)
reset_control_deassert(ge2d_rstc);
clk_prepare_enable(ge2d_clk);
} else {
clk_disable_unprepare(ge2d_clk);
if (ge2d_rstc != NULL)
reset_control_assert(ge2d_rstc);
}
return 0;
}
@@ -183,6 +202,75 @@ static inline int work_queue_no_space(struct ge2d_context_s *queue)
return list_empty(&queue->free_queue);
}
static void ge2d_dump_cmd(struct ge2d_cmd_s *cfg)
{
ge2d_log_dbg("src1_x_start=%d,src1_y_start=%d\n",
cfg->src1_x_start, cfg->src1_y_start);
ge2d_log_dbg("src1_x_end=%d,src1_y_end=%d\n",
cfg->src1_x_end, cfg->src1_y_end);
ge2d_log_dbg("src1_x_rev=%d,src1_y_rev=%d\n",
cfg->src1_x_rev, cfg->src1_y_rev);
ge2d_log_dbg("src1_fill_color_en=%d\n",
cfg->src1_fill_color_en);
ge2d_log_dbg("src2_x_start=%d,src2_y_start=%d\n",
cfg->src2_x_start, cfg->src2_y_start);
ge2d_log_dbg("src2_x_end=%d,src2_y_end=%d\n",
cfg->src2_x_end, cfg->src2_y_end);
ge2d_log_dbg("src2_x_rev=%d,src2_y_rev=%d\n",
cfg->src2_x_rev, cfg->src2_y_rev);
ge2d_log_dbg("src2_fill_color_en=%d\n",
cfg->src2_fill_color_en);
ge2d_log_dbg("dst_x_start=%d,dst_y_start=%d\n",
cfg->dst_x_start, cfg->dst_y_start);
ge2d_log_dbg("dst_x_end=%d,dst_y_end=%d\n",
cfg->dst_x_end, cfg->dst_y_end);
ge2d_log_dbg("dst_x_rev=%d,dst_y_rev=%d\n",
cfg->dst_x_rev, cfg->dst_y_rev);
ge2d_log_dbg("dst_xy_swap=%d\n",
cfg->dst_xy_swap);
ge2d_log_dbg("color_blend_mode=0x%x\n",
cfg->color_blend_mode);
ge2d_log_dbg("color_src_blend_factor=0x%x\n",
cfg->color_src_blend_factor);
ge2d_log_dbg("color_dst_blend_factor=0x%x\n",
cfg->color_dst_blend_factor);
ge2d_log_dbg("color_logic_op=0x%x\n",
cfg->color_logic_op);
ge2d_log_dbg("alpha_blend_mode=0x%x\n",
cfg->alpha_blend_mode);
ge2d_log_dbg("alpha_src_blend_factor=0x%x\n",
cfg->alpha_src_blend_factor);
ge2d_log_dbg("alpha_src_blend_factor=0x%x\n",
cfg->alpha_dst_blend_factor);
ge2d_log_dbg("alpha_logic_op=0x%x\n",
cfg->alpha_logic_op);
ge2d_log_dbg("sc_prehsc_en=%d\n", cfg->sc_prehsc_en);
ge2d_log_dbg("sc_prevsc_en=%d\n", cfg->sc_prevsc_en);
ge2d_log_dbg("sc_hsc_en=%d\n", cfg->sc_hsc_en);
ge2d_log_dbg("sc_vsc_en=%d\n", cfg->sc_vsc_en);
ge2d_log_dbg("vsc_phase_step=%d\n", cfg->vsc_phase_step);
ge2d_log_dbg("vsc_phase_slope=%d\n", cfg->vsc_phase_slope);
ge2d_log_dbg("vsc_rpt_l0_num=%d\n", cfg->vsc_rpt_l0_num);
ge2d_log_dbg("vsc_ini_phase=%d\n", cfg->vsc_ini_phase);
ge2d_log_dbg("hsc_phase_step=%d\n", cfg->hsc_phase_step);
ge2d_log_dbg("hsc_phase_slope=%d\n", cfg->hsc_phase_slope);
ge2d_log_dbg("hsc_rpt_p0_num=%d\n", cfg->hsc_rpt_p0_num);
ge2d_log_dbg("hsc_ini_phase=%d\n", cfg->hsc_ini_phase);
ge2d_log_dbg("hsc_div_en=%d\n", cfg->hsc_div_en);
ge2d_log_dbg("hsc_div_length=%d\n", cfg->hsc_div_length);
ge2d_log_dbg("hsc_adv_num=%d\n", cfg->hsc_adv_num);
ge2d_log_dbg("hsc_adv_phase=%d\n", cfg->hsc_adv_phase);
ge2d_log_dbg("src1_cmult_asel=%d\n", cfg->src1_cmult_asel);
ge2d_log_dbg("src2_cmult_asel=%d\n", cfg->src2_cmult_asel);
ge2d_log_dbg("GE2D_STATUS0=0x%x\n", ge2d_reg_read(GE2D_STATUS0));
ge2d_log_dbg("GE2D_STATUS1=0x%x\n", ge2d_reg_read(GE2D_STATUS1));
}
static int ge2d_process_work_queue(struct ge2d_context_s *wq)
{
struct ge2d_config_s *cfg;
@@ -191,6 +279,7 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
struct list_head *head = &wq->work_queue, *pos;
int ret = 0;
unsigned int block_mode;
int timeout = 0;
ge2d_manager.ge2d_state = GE2D_STATE_RUNNING;
pos = head->next;
@@ -253,14 +342,18 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
/* list_move_tail(&pitem->list,&wq->free_queue); */
/* spin_unlock(&wq->lock); */
/*
* while (ge2d_is_busy())
* interruptible_sleep_on_timeout(
* &ge2d_manager.event.cmd_complete, 1);
*/
while (ge2d_is_busy())
ge2d_sleep_on(&ge2d_manager.event.cmd_complete, 1);
while (ge2d_is_busy()) {
timeout = wait_event_interruptible_timeout(
ge2d_manager.event.cmd_complete,
!ge2d_is_busy(),
100);
if (timeout == 0) {
ge2d_log_err("ge2d timeout!!!\n");
ge2d_dump_cmd(&pitem->cmd);
ge2d_soft_rst();
break;
}
}
/* if block mode (cmd) */
if (block_mode) {
pitem->cmd.wait_done_flag = 0;
@@ -338,15 +431,12 @@ int ge2d_wq_add_work(struct ge2d_context_s *wq)
if (work_queue_no_space(wq)) {
ge2d_log_dbg("work queue no space\n");
/* we should wait for queue empty at this point. */
/*
* while (work_queue_no_space(wq))
* interruptible_sleep_on_timeout(
* &ge2d_manager.event.cmd_complete, 3);
*/
#if 0
while (work_queue_no_space(wq))
ge2d_sleep_on(&ge2d_manager.event.cmd_complete, 3);
ge2d_log_dbg("got free space\n");
interruptible_sleep_on_timeout(
&ge2d_manager.event.cmd_complete, 3);
#endif
return -1;
}
pitem = list_entry(wq->free_queue.next, struct ge2d_queue_item_s, list);
@@ -406,7 +496,8 @@ static int ge2d_monitor_thread(void *data)
while ((manager->current_wq =
get_next_work_queue(manager)) != NULL)
ge2d_process_work_queue(manager->current_wq);
ge2d_clk_config(false);
if (!ge2d_dump_reg_enable)
ge2d_clk_config(false);
}
ge2d_log_info("exit ge2d_monitor_thread\n");
return 0;
@@ -448,6 +539,9 @@ static inline int bpp(unsigned int format)
case GE2D_BPP_16BIT:
return 16;
case GE2D_BPP_24BIT:
if ((GE2D_COLOR_MAP_NV21 == (format & GE2D_COLOR_MAP_NV21)) ||
(GE2D_COLOR_MAP_NV12 == (format & GE2D_COLOR_MAP_NV12)))
return 8;
return 24;
case GE2D_BPP_32BIT:
default:
@@ -565,8 +659,14 @@ static int setup_display_property(struct src_dst_para_s *src_dst, int index)
index = (index == OSD1_CANVAS_INDEX ? 0 : 1);
ge2d_log_dbg("osd%d ", index);
data32 = ge2d_vcbus_read(VIU_OSD1_BLK0_CFG_W0 + REG_OFFSET * index);
#ifdef CONFIG_AMLOGIC_MEDIA_FB
data32 = VSYNCOSD_RD_MPEG_REG(
VIU_OSD1_BLK0_CFG_W0 + REG_OFFSET * index);
src_dst->canvas_index = (data32 >> 16) & 0xff;
canvas_read(src_dst->canvas_index, &canvas);
#else
data32 = 0;
#endif
index = (data32 >> 8) & 0xf;
bpp = block_mode[index]; /* OSD_BLK_MODE[8..11] */
ge2d_log_dbg("%d bpp\n", bpp);
@@ -787,6 +887,8 @@ int ge2d_context_config_ex(struct ge2d_context_s *context,
ge2d_log_dbg("ge2d src error: out of range\n");
return -1;
}
ge2d_config->src_para.width = tmp.xres;
ge2d_config->src_para.height = tmp.yres;
break;
case CANVAS_ALLOC:
top = ge2d_config->src_para.top;
@@ -835,6 +937,8 @@ int ge2d_context_config_ex(struct ge2d_context_s *context,
ge2d_config->src2_para.mem_type - CANVAS_OSD0);
return -1;
}
ge2d_config->src2_para.width = tmp.xres;
ge2d_config->src2_para.height = tmp.yres;
break;
case CANVAS_ALLOC:
top = ge2d_config->src2_para.top;
@@ -886,6 +990,8 @@ int ge2d_context_config_ex(struct ge2d_context_s *context,
ge2d_config->dst_para.mem_type - CANVAS_OSD0);
return -1;
}
ge2d_config->dst_para.width = tmp.xres;
ge2d_config->dst_para.height = tmp.yres;
break;
case CANVAS_ALLOC:
top = ge2d_config->dst_para.top;
@@ -1162,7 +1268,7 @@ int ge2d_wq_deinit(void)
}
ge2d_irq = -1;
ge2d_rstc = NULL;
clk_put(ge2d_clk);
clk_disable_unprepare(ge2d_clk);
ge2d_manager.pdev = NULL;
return 0;
}

View File

@@ -54,7 +54,9 @@ static inline void _set_src1_format(struct ge2d_src1_data_s *src1_data_cfg,
dp_gen_cfg->conv_matrix_en = 1;
} else if (((format_src & GE2D_FORMAT_YUV) == 0) &&
(format_dst & GE2D_FORMAT_YUV)) {
dp_gen_cfg->use_matrix_default = MATRIX_RGB_TO_YCC;
dp_gen_cfg->use_matrix_default =
(format_dst & GE2D_FORMAT_COMP_RANGE) ?
MATRIX_RGB_TO_YCC : MATRIX_RGB_TO_FULL_RANGE_YCC;
dp_gen_cfg->conv_matrix_en = 1;
} else
dp_gen_cfg->conv_matrix_en = 0;
@@ -103,7 +105,9 @@ static inline void _set_dst_format(
dp_gen_cfg->conv_matrix_en = 1;
} else if (((format_src & GE2D_FORMAT_YUV) == 0) &&
(format_dst & GE2D_FORMAT_YUV)) {
dp_gen_cfg->use_matrix_default = MATRIX_RGB_TO_YCC;
dp_gen_cfg->use_matrix_default =
(format_dst & GE2D_FORMAT_COMP_RANGE) ?
MATRIX_RGB_TO_YCC : MATRIX_RGB_TO_FULL_RANGE_YCC;
dp_gen_cfg->conv_matrix_en = 1;
} else
dp_gen_cfg->conv_matrix_en = 0;

View File

@@ -99,6 +99,7 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle,
}
return 0;
}
EXPORT_SYMBOL(ion_phys);
int meson_ion_share_fd_to_phys(struct ion_client *client,
int share_fd, ion_phys_addr_t *addr, size_t *len)

View File

@@ -53,4 +53,9 @@ struct ion_client *meson_ion_client_create(unsigned int heap_mask,
int meson_ion_share_fd_to_phys(struct ion_client *client,
int share_fd, ion_phys_addr_t *addr, size_t *len);
int ion_phys(struct ion_client *client, struct ion_handle *handle,
ion_phys_addr_t *addr, size_t *len);
#endif

View File

@@ -10,7 +10,7 @@ config AMLOGIC_MEDIA_RDMA
help
Select to enable RDMA management driver.
config CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
config AMLOGIC_MEDIA_VSYNC_RDMA
bool "Amlogic RDMA VSYNC"
depends on AMLOGIC_MEDIA_RDMA
default n

View File

@@ -326,6 +326,7 @@ int rdma_config(int handle, int trigger_type)
unsigned long flags;
struct rdma_device_info *info = &rdma_info;
struct rdma_instance_s *ins = &info->rdma_ins[handle];
bool auto_start = false;
if (handle == 0)
pr_info("%s error, rdma_config(handle == 0) not allowed\n",
@@ -339,7 +340,34 @@ int rdma_config(int handle, int trigger_type)
return -1;
}
if (ins->rdma_item_count <= 0 || trigger_type == 0) {
if (trigger_type & RDMA_AUTO_START_MASK)
auto_start = true;
trigger_type &= ~RDMA_AUTO_START_MASK;
if (auto_start) {
WRITE_VCBUS_REG_BITS(
ins->rdma_regadr->trigger_mask_reg,
0,
ins->rdma_regadr->trigger_mask_reg_bitpos,
8);
WRITE_VCBUS_REG_BITS(
ins->rdma_regadr->addr_inc_reg,
0,
ins->rdma_regadr->addr_inc_reg_bitpos,
1);
WRITE_VCBUS_REG_BITS(
ins->rdma_regadr->rw_flag_reg,
1,
ins->rdma_regadr->rw_flag_reg_bitpos,
1);
WRITE_VCBUS_REG_BITS(
ins->rdma_regadr->trigger_mask_reg,
trigger_type,
ins->rdma_regadr->trigger_mask_reg_bitpos,
8);
ret = 1;
} else if (ins->rdma_item_count <= 0 || trigger_type == 0) {
if (trigger_type == RDMA_TRIGGER_MANUAL)
WRITE_VCBUS_REG(RDMA_ACCESS_MAN,
READ_VCBUS_REG(RDMA_ACCESS_MAN) & (~1));

View File

@@ -0,0 +1,10 @@
#
# Amlogic Logo configuration
#
config AMLOGIC_MEDIA_LOGO
bool "Amlogic Logo Module"
default n
depends on AMLOGIC_MEDIA_FB
depends on AMLOGIC_VOUT
help
Select to enable Logo module

View File

@@ -0,0 +1,4 @@
obj-$(CONFIG_AMLOGIC_MEDIA_LOGO) += logo.o
ccflags-y += -Idrivers/amlogic/display/
ccflags-y += -Idrivers/amlogic/media/

View File

@@ -0,0 +1,307 @@
/*
* drivers/amlogic/media/logo/logo.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ctype.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/hdmi_tx/hdmi_tx_module.h>
/* Local Headers */
#include <osd/osd_hw.h>
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define LOGO_DEV_OSD0 0x0
#define LOGO_DEV_OSD1 0x1
#define LOGO_DEBUG 0x1001
#define LOGO_LOADED 0x1002
static enum vmode_e hdmimode = VMODE_MAX;
static enum vmode_e cvbsmode = VMODE_MAX;
static enum vmode_e last_mode = VMODE_MAX;
static u32 vout_init_vmode = VMODE_INIT_NULL;
struct delayed_work logo_work;
static DEFINE_MUTEX(logo_lock);
struct para_pair_s {
char *name;
int value;
};
static struct para_pair_s logo_args[] = {
{"osd0", LOGO_DEV_OSD0},
{"osd1", LOGO_DEV_OSD1},
{"debug", LOGO_DEBUG},
{"loaded", LOGO_LOADED},
};
struct logo_info_s {
int index;
u32 vmode;
u32 debug;
u32 loaded;
} logo_info = {
.index = -1,
.vmode = VMODE_MAX,
.debug = 0,
.loaded = 0,
};
static int get_value_by_name(char *name, struct para_pair_s *pair, u32 cnt)
{
u32 i = 0;
int found = -1;
for (i = 0; i < cnt; i++, pair++) {
if (strcmp(pair->name, name) == 0) {
found = pair->value;
break;
}
}
return found;
}
int set_osd_freescaler(int index, enum vmode_e new_mode)
{
const struct vinfo_s *vinfo;
osd_set_free_scale_mode_hw(index, 1);
osd_set_free_scale_enable_hw(index, 0);
osd_set_free_scale_axis_hw(index, 0, 0, 1919, 1079);
osd_update_disp_axis_hw(index, 0, 1919, 0, 1079, 0, 0, 0);
vinfo = get_current_vinfo();
if (vinfo) {
pr_info("outputmode changed to %s, reset osd%d scaler\n",
vinfo->name, index);
osd_set_window_axis_hw(index, 0, 0,
(vinfo->width - 1), (vinfo->height - 1));
} else {
osd_set_window_axis_hw(index, 0, 0, 1919, 1079);
pr_info("error: vinfo is NULL\n");
}
if (osd_get_logo_index() != logo_info.index) {
pr_info("logo changed, return");
return -1;
}
osd_set_free_scale_enable_hw(index, 0x10001);
osd_enable_hw(index, 1);
pr_info("finish");
return 0;
}
enum vmode_e get_logo_vmode(void)
{
return vout_init_vmode;
}
static int set_logo_vmode(enum vmode_e mode)
{
int ret = 0;
if (mode == VMODE_INIT_NULL)
return -1;
vout_init_vmode = mode;
set_current_vmode(mode);
return ret;
}
static int refresh_mode_and_logo(bool first)
{
enum vmode_e cur_mode = VMODE_MAX;
int hdp_state = 0;
#ifdef AMLOGIC_HDMI_TX
hdp_state = get_hpd_state();
#endif
if (!first && osd_get_logo_index() != logo_info.index)
return -1;
if (hdp_state)
cur_mode = hdmimode;
else
cur_mode = cvbsmode;
if (first) {
last_mode = get_logo_vmode();
if (logo_info.index >= 0) {
osd_set_logo_index(logo_info.index);
/* osd_init_hw(logo_info.loaded); */
}
}
if (cur_mode >= VMODE_MAX) /* not box platform */
return -1;
if (cur_mode != last_mode) {
pr_info("mode chang\n");
if (logo_info.index >= 0)
osd_enable_hw(logo_info.index, 0);
set_logo_vmode(cur_mode);
pr_info("set vmode: %s\n",
get_current_vinfo()->name);
last_mode = cur_mode;
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &cur_mode);
if (logo_info.index >= 0)
set_osd_freescaler(logo_info.index, cur_mode);
}
return 0;
}
void aml_logo_work(struct work_struct *work)
{
mutex_lock(&logo_lock);
refresh_mode_and_logo(false);
mutex_unlock(&logo_lock);
if (osd_get_logo_index() == logo_info.index)
schedule_delayed_work(&logo_work, 1*HZ/2);
}
static int logo_info_init(char *para)
{
u32 count = 0;
int value = -1;
count = ARRAY_SIZE(logo_args) / sizeof(logo_args[0]);
value = get_value_by_name(para, logo_args, count);
if (value >= 0) {
switch (value) {
case LOGO_DEV_OSD0:
logo_info.index = LOGO_DEV_OSD0;
break;
case LOGO_DEV_OSD1:
logo_info.index = LOGO_DEV_OSD1;
break;
case LOGO_DEBUG:
logo_info.debug = 1;
break;
case LOGO_LOADED:
logo_info.loaded = 1;
break;
default:
break;
}
return 0;
}
return 0;
}
static int str2lower(char *str)
{
while (*str != '\0') {
*str = tolower(*str);
str++;
}
return 0;
}
static int __init logo_setup(char *str)
{
char *ptr = str;
char sep[2];
char *option;
int count = 5;
char find = 0;
if (str == NULL)
return -EINVAL;
do {
if (!isalpha(*ptr) && !isdigit(*ptr)) {
find = 1;
break;
}
} while (*++ptr != '\0');
if (!find)
return -EINVAL;
logo_info.index = -1;
logo_info.debug = 0;
logo_info.loaded = 0;
logo_info.vmode = VMODE_MAX;
sep[0] = *ptr;
sep[1] = '\0';
while ((count--) && (option = strsep(&str, sep))) {
pr_info("%s\n", option);
str2lower(option);
logo_info_init(option);
}
return 0;
}
__setup("logo=", logo_setup);
static int __init get_hdmi_mode(char *str)
{
hdmimode = get_current_vmode();
/* hdmimode = vmode_name_to_mode(str); */
pr_info("get hdmimode: %s\n", str);
return 1;
}
__setup("hdmimode=", get_hdmi_mode);
static int __init get_cvbs_mode(char *str)
{
if (strncmp("480", str, 3) == 0)
cvbsmode = VMODE_480CVBS;
else if (strncmp("576", str, 3) == 0)
cvbsmode = VMODE_576CVBS;
else if (strncmp("nocvbs", str, 6) == 0)
cvbsmode = hdmimode;
pr_info("get cvbsmode: %s\n", str);
return 1;
}
__setup("cvbsmode=", get_cvbs_mode);
static int __init logo_init(void)
{
int ret = 0;
pr_info("%s\n", __func__);
if (logo_info.loaded == 0)
return 0;
refresh_mode_and_logo(true);
INIT_DELAYED_WORK(&logo_work, aml_logo_work);
schedule_delayed_work(&logo_work, 1*HZ/2);
return ret;
}
subsys_initcall(logo_init);

View File

@@ -0,0 +1,70 @@
#
# Frame buffer configuration
#
menu "Amlogic OSD Module"
config AMLOGIC_MEDIA_FB
bool "Amlogic OSD Support"
depends on FB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
depends on AMLOGIC_MEDIA_CANVAS
# depends on AMLOGIC_VOUT_SERVE
default n
help
This is the frame buffer device driver.
It provide basic frame buffer device driver.
It need enable canvas.
It need enable vout.
config AMLOGIC_MEDIAFB_OSD_SYNC_FENCE
bool "OSD SYNC FENCE"
default n
depends on AMLOGIC_MEDIA_FB
depends on STAGING
depends on ANDROID
depends on SYNC
depends on SW_SYNC
help
Select to enable OSD SYNC FENCE.
This is the frame buffer device driver.
It provide basic frame buffer device driver.
This module is used in android system.
It used sync fence.
config AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
bool "OSD VSYNC RDMA"
default n
depends on AMLOGIC_MEDIA_FB
depends on AMLOGIC_MEDIA_RDMA
help
This is the frame buffer device driver.
Select to enable OSD VSYNC RDMA.
This module used VSYNC RDMA.
It used rdma.
config AMLOGIC_MEDIA_FB_OSD2_ENABLE
bool "OSD2 Layer Support"
default n
depends on AMLOGIC_MEDIA_FB
help
This is the frame buffer device driver.
Select to enable OSD2 Layer.
This module enable OSD2 layer,
otherwise we used OSD1 only.
config AMLOGIC_MEDIA_FB_OSD2_CURSOR
bool "OSD2 Cursor Support"
depends on AMLOGIC_MEDIA_FB_OSD2_ENABLE
default n
help
This is the frame buffer device driver.
Select to enable OSD2 cursor.
This module used2 OSD2 as cursor.
endmenu

View File

@@ -0,0 +1,10 @@
obj-$(CONFIG_AMLOGIC_MEDIA_FB) += fb.o
fb-objs = osd_hw.o osd_fb.o osd_debug.o osd_backup.o
fb-objs += osd_antiflicker.o osd_clone.o
obj-$(CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA) += osd_rdma.o
obj-$(CONFIG_INSTABOOT) += osd_progressbar.o
ccflags-y += -Idrivers/amlogic/media/common/ion_dev/
ccflags-y += -Idrivers/staging/android/

View File

@@ -0,0 +1,339 @@
/*
* drivers/amlogic/media/osd/osd.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_H_
#define _OSD_H_
enum color_index_e {
COLOR_INDEX_02_PAL4 = 2, /* 0 */
COLOR_INDEX_04_PAL16 = 4, /* 0 */
COLOR_INDEX_08_PAL256 = 8,
COLOR_INDEX_16_655 = 9,
COLOR_INDEX_16_844 = 10,
COLOR_INDEX_16_6442 = 11,
COLOR_INDEX_16_4444_R = 12,
COLOR_INDEX_16_4642_R = 13,
COLOR_INDEX_16_1555_A = 14,
COLOR_INDEX_16_4444_A = 15,
COLOR_INDEX_16_565 = 16,
COLOR_INDEX_24_6666_A = 19,
COLOR_INDEX_24_6666_R = 20,
COLOR_INDEX_24_8565 = 21,
COLOR_INDEX_24_5658 = 22,
COLOR_INDEX_24_888_B = 23,
COLOR_INDEX_24_RGB = 24,
COLOR_INDEX_32_BGRX = 25,
COLOR_INDEX_32_XBGR = 26,
COLOR_INDEX_32_RGBX = 27,
COLOR_INDEX_32_XRGB = 28,
COLOR_INDEX_32_BGRA = 29,
COLOR_INDEX_32_ABGR = 30,
COLOR_INDEX_32_RGBA = 31,
COLOR_INDEX_32_ARGB = 32,
COLOR_INDEX_YUV_422 = 33,
};
#define VPP_OSD2_PREBLEND (1 << 17)
#define VPP_OSD1_PREBLEND (1 << 16)
#define VPP_VD2_PREBLEND (1 << 15)
#define VPP_VD1_PREBLEND (1 << 14)
#define VPP_OSD2_POSTBLEND (1 << 13)
#define VPP_OSD1_POSTBLEND (1 << 12)
#define VPP_VD2_POSTBLEND (1 << 11)
#define VPP_VD1_POSTBLEND (1 << 10)
#define VPP_POSTBLEND_EN (1 << 7)
#define VPP_PRE_FG_OSD2 (1 << 5)
#define VPP_PREBLEND_EN (1 << 6)
#define VPP_POST_FG_OSD2 (1 << 4)
/* OSD device ioctl definition */
#define FBIOPUT_OSD_SRCKEY_ENABLE 0x46fa
#define FBIOPUT_OSD_SRCCOLORKEY 0x46fb
#define FBIOGET_OSD_DMABUF 0x46fc
#define FBIOPUT_OSD_SET_GBL_ALPHA 0x4500
#define FBIOGET_OSD_GET_GBL_ALPHA 0x4501
#define FBIOPUT_OSD_2X_SCALE 0x4502
#define FBIOPUT_OSD_ENABLE_3D_MODE 0x4503
#define FBIOPUT_OSD_FREE_SCALE_ENABLE 0x4504
#define FBIOPUT_OSD_FREE_SCALE_WIDTH 0x4505
#define FBIOPUT_OSD_FREE_SCALE_HEIGHT 0x4506
#define FBIOPUT_OSD_ORDER 0x4507
#define FBIOGET_OSD_ORDER 0x4508
#define FBIOGET_OSD_SCALE_AXIS 0x4509
#define FBIOPUT_OSD_SCALE_AXIS 0x450a
#define FBIOGET_OSD_BLOCK_WINDOWS 0x450b
#define FBIOPUT_OSD_BLOCK_WINDOWS 0x450c
#define FBIOGET_OSD_BLOCK_MODE 0x450d
#define FBIOPUT_OSD_BLOCK_MODE 0x450e
#define FBIOGET_OSD_FREE_SCALE_AXIS 0x450f
#define FBIOPUT_OSD_FREE_SCALE_AXIS 0x4510
#define FBIOPUT_OSD_FREE_SCALE_MODE 0x4511
#define FBIOGET_OSD_WINDOW_AXIS 0x4512
#define FBIOPUT_OSD_WINDOW_AXIS 0x4513
#define FBIOGET_OSD_FLUSH_RATE 0x4514
#define FBIOPUT_OSD_REVERSE 0x4515
#define FBIOPUT_OSD_ROTATE_ON 0x4516
#define FBIOPUT_OSD_ROTATE_ANGLE 0x4517
#define FBIOPUT_OSD_SYNC_ADD 0x4518
/* OSD color definition */
#define KEYCOLOR_FLAG_TARGET 1
#define KEYCOLOR_FLAG_ONHOLD 2
#define KEYCOLOR_FLAG_CURRENT 4
#define HW_OSD_COUNT 2
/* OSD block definition */
#define HW_OSD_BLOCK_COUNT 4
#define HW_OSD_BLOCK_REG_COUNT (HW_OSD_BLOCK_COUNT*2)
#define HW_OSD_BLOCK_ENABLE_MASK 0x000F
#define HW_OSD_BLOCK_ENABLE_0 0x0001 /* osd blk0 enable */
#define HW_OSD_BLOCK_ENABLE_1 0x0002 /* osd blk1 enable */
#define HW_OSD_BLOCK_ENABLE_2 0x0004 /* osd blk2 enable */
#define HW_OSD_BLOCK_ENABLE_3 0x0008 /* osd blk3 enable */
#define HW_OSD_BLOCK_LAYOUT_MASK 0xFFFF0000
#define HW_OSD_BLOCK_LAYOUT_HORIZONTAL 0x00010000
#define HW_OSD_BLOCK_LAYOUT_VERTICAL 0x00020000
#define HW_OSD_BLOCK_LAYOUT_GRID 0x00030000
#define HW_OSD_BLOCK_LAYOUT_CUSTOMER 0xFFFF0000
#define OSD_LEFT 0
#define OSD_RIGHT 1
#define OSD_ORDER_01 1
#define OSD_ORDER_10 2
#define OSD_GLOBAL_ALPHA_DEF 0x100
#define OSD_DATA_BIG_ENDIAN 0
#define OSD_DATA_LITTLE_ENDIAN 1
#define OSD_TC_ALPHA_ENABLE_DEF 0 /* disable tc_alpha */
#define INT_VIU_VSYNC 30 /* 35 */
#define INT_VIU2_VSYNC 45
#define INT_RDMA 121
#define OSD_MAX_BUF_NUM 3 /* fence relative */
enum osd_index_e {
OSD1 = 0,
OSD2
};
enum osd_enable_e {
DISABLE = 0,
ENABLE
};
enum scan_mode_e {
SCAN_MODE_INTERLACE,
SCAN_MODE_PROGRESSIVE
};
struct color_bit_define_s {
enum color_index_e color_index;
u8 hw_colormat;
u8 hw_blkmode;
u8 red_offset;
u8 red_length;
u8 red_msb_right;
u8 green_offset;
u8 green_length;
u8 green_msb_right;
u8 blue_offset;
u8 blue_length;
u8 blue_msb_right;
u8 transp_offset;
u8 transp_length;
u8 transp_msb_right;
u8 color_type;
u8 bpp;
};
struct osd_ctl_s {
u32 xres_virtual;
u32 yres_virtual;
u32 xres;
u32 yres;
u32 disp_start_x; /* coordinate of screen */
u32 disp_start_y;
u32 disp_end_x;
u32 disp_end_y;
u32 addr;
u32 index;
};
struct osd_info_s {
u32 index;
u32 osd_reverse;
};
struct para_osd_info_s {
char *name;
u32 info;
u32 prev_idx;
u32 next_idx;
u32 cur_group_start;
u32 cur_group_end;
};
enum osd_dev_e {
DEV_OSD0 = 0,
DEV_OSD1,
DEV_ALL,
DEV_MAX
};
enum reverse_info_e {
REVERSE_FALSE = 0,
REVERSE_TRUE,
REVERSE_X,
REVERSE_Y,
REVERSE_MAX
};
enum hw_reg_index_e {
OSD_COLOR_MODE = 0,
OSD_ENABLE,
OSD_COLOR_KEY,
OSD_COLOR_KEY_ENABLE,
OSD_GBL_ALPHA,
OSD_CHANGE_ORDER,
OSD_FREESCALE_COEF,
DISP_GEOMETRY,
DISP_SCALE_ENABLE,
DISP_FREESCALE_ENABLE,
DISP_OSD_REVERSE,
DISP_OSD_ROTATE,
OSD_FIFO,
HW_REG_INDEX_MAX
};
struct pandata_s {
s32 x_start;
s32 x_end;
s32 y_start;
s32 y_end;
};
struct fb_geometry_s {
u32 width; /* in byte unit */
u32 height;
u32 canvas_idx;
u32 addr;
};
struct osd_scale_s {
u16 h_enable;
u16 v_enable;
};
struct osd_3d_mode_s {
struct osd_scale_s origin_scale;
u16 enable;
u16 left_right;
u16 l_start;
u16 l_end;
u16 r_start;
u16 r_end;
};
struct osd_rotate_s {
u32 on_off;
u32 angle;
};
struct osd_fence_map_s {
struct list_head list;
u32 fb_index;
u32 buf_num;
u32 xoffset;
u32 yoffset;
u32 yres;
s32 in_fd;
s32 out_fd;
u32 val;
struct sync_fence *in_fence;
struct files_struct *files;
};
struct afbcd_data_s {
u32 enable;
u32 phy_addr;
u32 addr[OSD_MAX_BUF_NUM];
u32 frame_width;
u32 frame_height;
u32 conv_lbuf_len;
};
typedef void (*update_func_t)(void);
struct hw_list_s {
struct list_head list;
update_func_t update_func;
};
struct hw_para_s {
struct pandata_s pandata[HW_OSD_COUNT];
struct pandata_s dispdata[HW_OSD_COUNT];
struct pandata_s scaledata[HW_OSD_COUNT];
struct pandata_s free_src_data[HW_OSD_COUNT];
struct pandata_s free_dst_data[HW_OSD_COUNT];
/* struct pandata_s rotation_pandata[HW_OSD_COUNT]; */
struct pandata_s cursor_dispdata[HW_OSD_COUNT];
u32 gbl_alpha[HW_OSD_COUNT];
u32 color_key[HW_OSD_COUNT];
u32 color_key_enable[HW_OSD_COUNT];
u32 enable[HW_OSD_COUNT];
u32 reg_status_save;
#ifdef FIQ_VSYNC
bridge_item_t fiq_handle_item;
#endif
struct osd_scale_s scale[HW_OSD_COUNT];
struct osd_scale_s free_scale[HW_OSD_COUNT];
u32 free_scale_enable[HW_OSD_COUNT];
struct fb_geometry_s fb_gem[HW_OSD_COUNT];
const struct color_bit_define_s *color_info[HW_OSD_COUNT];
u32 scan_mode;
u32 order;
struct osd_3d_mode_s mode_3d[HW_OSD_COUNT];
u32 updated[HW_OSD_COUNT];
/* u32 block_windows[HW_OSD_COUNT][HW_OSD_BLOCK_REG_COUNT]; */
u32 block_mode[HW_OSD_COUNT];
u32 free_scale_mode[HW_OSD_COUNT];
u32 osd_reverse[HW_OSD_COUNT];
/* struct osd_rotate_s rotate[HW_OSD_COUNT]; */
struct hw_list_s reg[HW_OSD_COUNT][HW_REG_INDEX_MAX];
u32 field_out_en;
u32 scale_workaround;
u32 fb_for_4k2k;
u32 antiflicker_mode;
u32 angle[HW_OSD_COUNT];
u32 clone[HW_OSD_COUNT];
u32 bot_type;
u32 hw_reset_flag;
struct afbcd_data_s osd_afbcd[HW_OSD_COUNT];
u32 urgent[HW_OSD_COUNT];
};
#endif /* _OSD_H_ */

View File

@@ -0,0 +1,197 @@
/*
* drivers/amlogic/media/osd/osd_antiflicker.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
/* Amlogic Headers */
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#include <linux/amlogic/media/ge2d/ge2d.h>
#endif
/* Local Headers */
#include "osd_canvas.h"
#include "osd_antiflicker.h"
#include "osd_log.h"
#include "osd_io.h"
#ifdef OSD_GE2D_ANTIFLICKER_SUPPORT
struct osd_antiflicker_s {
bool inited;
u32 yoffset;
u32 yres;
struct config_para_ex_s ge2d_config;
struct ge2d_context_s *ge2d_context;
};
static DEFINE_MUTEX(osd_antiflicker_mutex);
static struct osd_antiflicker_s ge2d_osd_antiflicker;
void osd_antiflicker_enable(u32 enable)
{
ge2d_antiflicker_enable(ge2d_osd_antiflicker.ge2d_context, enable);
}
static int osd_antiflicker_process(void)
{
int ret = -1;
struct canvas_s cs, cd;
u32 x0 = 0;
u32 y0 = 0;
u32 y1 = 0;
u32 yres = 0;
struct config_para_ex_s *ge2d_config = NULL;
struct ge2d_context_s *context = NULL;
ge2d_config = &ge2d_osd_antiflicker.ge2d_config;
context = ge2d_osd_antiflicker.ge2d_context;
mutex_lock(&osd_antiflicker_mutex);
canvas_read(OSD1_CANVAS_INDEX, &cs);
canvas_read(OSD1_CANVAS_INDEX, &cd);
if (ge2d_osd_antiflicker.yoffset > 0) {
y0 = ge2d_osd_antiflicker.yoffset;
y1 = ge2d_osd_antiflicker.yoffset;
}
yres = cs.height / ge2d_osd_antiflicker.yres;
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width / 4;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width / 4;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_para.canvas_index = OSD1_CANVAS_INDEX;
ge2d_config->src_para.mem_type = CANVAS_OSD0;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ARGB;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = cs.width / 4;
ge2d_config->src_para.height = cs.height;
ge2d_config->dst_para.canvas_index = OSD1_CANVAS_INDEX;
ge2d_config->dst_para.mem_type = CANVAS_OSD0;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ARGB;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = cd.width / 4;
ge2d_config->dst_para.height = cd.height;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ret = ge2d_context_config_ex(context, ge2d_config);
mutex_unlock(&osd_antiflicker_mutex);
if (ret < 0) {
osd_log_info("++ osd antiflicker ge2d config ex error.\n");
return ret;
}
stretchblt(context, x0, y0, cs.width / 4, (cs.height / yres), x0, y1,
cd.width / 4, (cd.height / yres));
return ret;
}
void osd_antiflicker_update_pan(u32 yoffset, u32 yres)
{
int ret = -1;
if (!ge2d_osd_antiflicker.inited)
return;
mutex_lock(&osd_antiflicker_mutex);
ge2d_osd_antiflicker.yoffset = yoffset;
ge2d_osd_antiflicker.yres = yres;
mutex_unlock(&osd_antiflicker_mutex);
#if 0
osd_antiflicker_process();
osd_antiflicker_process_2();
#endif
ret = osd_antiflicker_process();
if (ret < 0)
osd_antiflicker_task_stop();
}
int osd_antiflicker_task_start(void)
{
if (ge2d_osd_antiflicker.inited) {
osd_log_info("osd_antiflicker_task already started.\n");
return 0;
}
osd_log_info("osd_antiflicker_task start.\n");
if (ge2d_osd_antiflicker.ge2d_context == NULL)
ge2d_osd_antiflicker.ge2d_context = create_ge2d_work_queue();
memset(&ge2d_osd_antiflicker.ge2d_config,
0, sizeof(struct config_para_ex_s));
ge2d_osd_antiflicker.inited = true;
return 0;
}
void osd_antiflicker_task_stop(void)
{
if (!ge2d_osd_antiflicker.inited) {
osd_log_info("osd_antiflicker_task already stopped.\n");
return;
}
osd_log_info("osd_antiflicker_task stop.\n");
if (ge2d_osd_antiflicker.ge2d_context) {
destroy_ge2d_work_queue(ge2d_osd_antiflicker.ge2d_context);
ge2d_osd_antiflicker.ge2d_context = NULL;
}
ge2d_osd_antiflicker.inited = false;
}
#endif

View File

@@ -0,0 +1,47 @@
/*
* drivers/amlogic/media/osd/osd_antiflicker.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_ANTIFLICKER_H_
#define _OSD_ANTIFLICKER_H_
#include "osd_log.h"
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#define OSD_GE2D_ANTIFLICKER_SUPPORT 1
#endif
#ifdef OSD_GE2D_ANTIFLICKER_SUPPORT
extern void osd_antiflicker_update_pan(u32 yoffset, u32 yres);
extern int osd_antiflicker_task_start(void);
extern void osd_antiflicker_task_stop(void);
extern void osd_antiflicker_enable(u32 enable);
#else
static inline void osd_antiflicker_enable(u32 enable) {}
static inline void osd_antiflicker_update_pan(u32 yoffset, u32 yres) {}
static inline int osd_antiflicker_task_start(void)
{
osd_log_info("++ osd_antiflicker depends on GE2D module!\n");
return 0;
}
static inline void osd_antiflicker_task_stop(void)
{
osd_log_info("-- osd_antiflicker depends on GE2D module!\n");
}
#endif
#endif

View File

@@ -0,0 +1,519 @@
/*
* drivers/amlogic/media/osd/osd_backup.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
/* Local Headers */
#include "osd_io.h"
#include "osd_backup.h"
const u16 osd_reg_backup[OSD_REG_BACKUP_COUNT] = {
0x1a10, 0x1a13,
0x1a17, 0x1a18, 0x1a19, 0x1a1a, 0x1a1b, 0x1a1c, 0x1a1d, 0x1a1e,
0x1a2b, 0x1a2d
};
const u16 osd_afbc_reg_backup[OSD_AFBC_REG_BACKUP_COUNT] = {
0x31aa, 0x31a9,
0x31a6, 0x31a5, 0x31a4, 0x31a3, 0x31a2, 0x31a1, 0x31a0
};
static u32 osd_backup_count = OSD_VALUE_COUNT;
static u32 afbc_backup_count = OSD_AFBC_VALUE_COUNT;
u32 osd_backup[OSD_VALUE_COUNT];
u32 osd_afbc_backup[OSD_AFBC_VALUE_COUNT];
module_param_array(osd_backup, uint, &osd_backup_count, 0444);
MODULE_PARM_DESC(osd_backup, "\n osd register backup\n");
module_param_array(osd_afbc_backup, uint, &afbc_backup_count, 0444);
MODULE_PARM_DESC(osd_afbc_backup, "\n osd afbc register backup\n");
/* 0: not backup */
static u32 backup_enable;
module_param(backup_enable, uint, 0444);
void update_backup_reg(u32 addr, u32 value)
{
u32 base = OSD1_AFBCD_ENABLE;
if (!backup_enable)
return;
if ((addr >= OSD1_AFBCD_ENABLE) &&
(addr <= OSD1_AFBCD_PIXEL_VSCOPE) &&
(backup_enable & HW_RESET_AFBCD_REGS)) {
osd_afbc_backup[addr - base] = value;
}
base = VIU_OSD1_CTRL_STAT;
if ((addr >= VIU_OSD1_CTRL_STAT) &&
(addr <= VIU_OSD1_CTRL_STAT2) &&
(backup_enable & HW_RESET_OSD1_REGS)) {
osd_backup[addr - base] = value;
}
}
s32 get_backup_reg(u32 addr, u32 *value)
{
int i;
u32 base = OSD1_AFBCD_ENABLE;
if (!backup_enable || !value)
return -1;
if ((addr >= OSD1_AFBCD_ENABLE) &&
(addr <= OSD1_AFBCD_PIXEL_VSCOPE) &&
(backup_enable & HW_RESET_AFBCD_REGS)) {
for (i = 0; i < OSD_AFBC_REG_BACKUP_COUNT; i++)
if (addr == osd_afbc_reg_backup[i]) {
*value = osd_afbc_backup[addr - base];
return 0;
}
}
base = VIU_OSD1_CTRL_STAT;
if ((addr >= VIU_OSD1_CTRL_STAT) &&
(addr <= VIU_OSD1_CTRL_STAT2) &&
(backup_enable & HW_RESET_OSD1_REGS)) {
for (i = 0; i < OSD_REG_BACKUP_COUNT; i++)
if (addr == osd_reg_backup[i]) {
*value = osd_backup[addr - base];
return 0;
}
}
return -1;
}
void backup_regs_init(u32 backup_mask)
{
int i = 0;
u32 addr;
u32 base = VIU_OSD1_CTRL_STAT;
if (backup_enable)
return;
while ((backup_mask & HW_RESET_OSD1_REGS)
&& (i < OSD_REG_BACKUP_COUNT)) {
addr = osd_reg_backup[i];
osd_backup[addr - base] =
osd_reg_read(addr);
i++;
}
i = 0;
base = OSD1_AFBCD_ENABLE;
while ((backup_mask & HW_RESET_AFBCD_REGS)
&& (i < OSD_AFBC_REG_BACKUP_COUNT)) {
addr = osd_afbc_reg_backup[i];
osd_afbc_backup[addr - base] =
osd_reg_read(addr);
i++;
}
backup_enable = backup_mask;
}
u32 is_backup(void)
{
return backup_enable;
}
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
/* recovery section */
#define INVAILD_REG_ITEM {0xffff, 0x0, 0x0, 0x0}
#define REG_RECOVERY_TABLE 5
static struct reg_recovery_table gRecovery[REG_RECOVERY_TABLE];
static u32 recovery_enable;
static struct reg_item osd1_recovery_table[] = {
{VIU_OSD1_CTRL_STAT, 0x0, 0x401ff9f1, 1},
INVAILD_REG_ITEM, /* VIU_OSD1_COLOR_ADDR 0x1a11 */
INVAILD_REG_ITEM, /* VIU_OSD1_COLOR 0x1a12 */
{VIU_OSD1_BLK0_CFG_W4, 0x0, 0x0fff0fff, 1},
INVAILD_REG_ITEM, /* VIU_OSD1_BLK1_CFG_W4 0x1a14 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK2_CFG_W4 0x1a15 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK3_CFG_W4 0x1a16 */
{VIU_OSD1_TCOLOR_AG0, 0x0, 0xffffffff, 1},
{VIU_OSD1_TCOLOR_AG1, 0x0, 0xffffffff, 0},
{VIU_OSD1_TCOLOR_AG2, 0x0, 0xffffffff, 0},
{VIU_OSD1_TCOLOR_AG3, 0x0, 0xffffffff, 0},
{VIU_OSD1_BLK0_CFG_W0, 0x0, 0x30ffffff, 1},
{VIU_OSD1_BLK0_CFG_W1, 0x0, 0x1fff1fff, 1},
{VIU_OSD1_BLK0_CFG_W2, 0x0, 0x1fff1fff, 1},
{VIU_OSD1_BLK0_CFG_W3, 0x0, 0x0fff0fff, 1},
INVAILD_REG_ITEM, /* VIU_OSD1_BLK1_CFG_W0 0x1a1f */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK1_CFG_W1 0x1a20 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK1_CFG_W2 0x1a21 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK1_CFG_W3 0x1a22 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK2_CFG_W0 0x1a23 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK2_CFG_W1 0x1a24 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK2_CFG_W2 0x1a25 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK2_CFG_W3 0x1a26 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK3_CFG_W0 0x1a27 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK3_CFG_W1 0x1a28 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK3_CFG_W2 0x1a29 */
INVAILD_REG_ITEM, /* VIU_OSD1_BLK3_CFG_W3 0x1a2a */
{VIU_OSD1_FIFO_CTRL_STAT, 0x0, 0xffc3ffff, 1},
INVAILD_REG_ITEM, /* VIU_OSD1_TEST_RDDATA 0x1a2c */
{VIU_OSD1_CTRL_STAT2, 0x0, 0x0000ffff, 1},
};
static struct reg_item osd_afbcd_recovery_table[] = {
{OSD1_AFBCD_ENABLE, 0x0, 0x0000ff01, 1},
{OSD1_AFBCD_MODE, 0x0, 0x937f007f, 1},
{OSD1_AFBCD_SIZE_IN, 0x0, 0xffffffff, 1},
{OSD1_AFBCD_HDR_PTR, 0x0, 0xffffffff, 1},
{OSD1_AFBCD_FRAME_PTR, 0x0, 0xffffffff, 1},
{OSD1_AFBCD_CHROMA_PTR, 0x0, 0xffffffff, 1},
{OSD1_AFBCD_CONV_CTRL, 0x0, 0x0000ffff, 1},
INVAILD_REG_ITEM, /* unused 0x31a7 */
INVAILD_REG_ITEM, /* OSD1_AFBCD_STATUS 0x31a8 */
{OSD1_AFBCD_PIXEL_HSCOPE, 0x0, 0xffffffff, 1},
{OSD1_AFBCD_PIXEL_VSCOPE, 0x0, 0xffffffff, 1}
};
static struct reg_item freescale_recovery_table[] = {
{VPP_OSD_VSC_PHASE_STEP, 0x0, 0x0fffffff, 1},
{VPP_OSD_VSC_INI_PHASE, 0x0, 0xffffffff, 1},
{VPP_OSD_VSC_CTRL0, 0x0, 0x01fb7b7f, 1},
{VPP_OSD_HSC_PHASE_STEP, 0x0, 0x0fffffff, 1},
{VPP_OSD_HSC_INI_PHASE, 0x0, 0xffffffff, 1},
{VPP_OSD_HSC_CTRL0, 0x0, 0x007b7b7f, 1},
{VPP_OSD_HSC_INI_PAT_CTRL, 0x0, 0x0000ff77, 1},
{VPP_OSD_SC_DUMMY_DATA, 0x0, 0xffffffff, 0},
{VPP_OSD_SC_CTRL0, 0x0, 0x00007ffb, 1},
{VPP_OSD_SCI_WH_M1, 0x0, 0x1fff1fff, 1},
{VPP_OSD_SCO_H_START_END, 0x0, 0x0fff0fff, 1},
{VPP_OSD_SCO_V_START_END, 0x0, 0x0fff0fff, 1},
{VPP_OSD_SCALE_COEF_IDX, 0x0, 0x0000c37f, 0},
{VPP_OSD_SCALE_COEF, 0x0, 0xffffffff, 0}
};
static struct reg_item osd2_recovery_table[] = {
{VIU_OSD2_CTRL_STAT, 0x0, 0x401ff9f1, 1},
INVAILD_REG_ITEM, /* VIU_OSD2_COLOR_ADDR 0x1a31 */
INVAILD_REG_ITEM, /* VIU_OSD2_COLOR 0x1a32 */
INVAILD_REG_ITEM, /* VIU_OSD2_HL1_H_START_END 0x1a33 */
INVAILD_REG_ITEM, /* VIU_OSD2_HL1_V_START_END 0x1a34 */
INVAILD_REG_ITEM, /* VIU_OSD2_HL2_H_START_END 0x1a35 */
INVAILD_REG_ITEM, /* VIU_OSD2_HL2_V_START_END 0x1a36 */
{VIU_OSD2_TCOLOR_AG0, 0x0, 0xffffffff, 1},
{VIU_OSD2_TCOLOR_AG1, 0x0, 0xffffffff, 0},
{VIU_OSD2_TCOLOR_AG2, 0x0, 0xffffffff, 0},
{VIU_OSD2_TCOLOR_AG3, 0x0, 0xffffffff, 0},
{VIU_OSD2_BLK0_CFG_W0, 0x0, 0x00ffffff, 1},
{VIU_OSD2_BLK0_CFG_W1, 0x0, 0x1fff1fff, 1},
{VIU_OSD2_BLK0_CFG_W2, 0x0, 0x1fff1fff, 1},
{VIU_OSD2_BLK0_CFG_W3, 0x0, 0x0fff0fff, 1},
{VIU_OSD2_BLK1_CFG_W0, 0x0, 0x00ffffff, 0},
{VIU_OSD2_BLK1_CFG_W1, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK1_CFG_W2, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK1_CFG_W3, 0x0, 0x0fff0fff, 0},
{VIU_OSD2_BLK2_CFG_W0, 0x0, 0x00ffffff, 0},
{VIU_OSD2_BLK2_CFG_W1, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK2_CFG_W2, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK2_CFG_W3, 0x0, 0x0fff0fff, 0},
{VIU_OSD2_BLK3_CFG_W0, 0x0, 0x00ffffff, 0},
{VIU_OSD2_BLK3_CFG_W1, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK3_CFG_W2, 0x0, 0x1fff1fff, 0},
{VIU_OSD2_BLK3_CFG_W3, 0x0, 0x0fff0fff, 0},
{VIU_OSD2_FIFO_CTRL_STAT, 0x0, 0xffc3ffff, 1},
INVAILD_REG_ITEM, /* VIU_OSD2_TEST_RDDATA 0x1a4c */
{VIU_OSD2_CTRL_STAT2, 0x0, 0x00007ffd, 1}
};
static struct reg_item misc_recovery_table[] = {
{VIU_OSD2_BLK0_CFG_W4, 0x0, 0x0fff0fff, 1},
{VIU_OSD2_BLK1_CFG_W4, 0x0, 0xffffffff, 0},
{VIU_OSD2_BLK2_CFG_W4, 0x0, 0xffffffff, 0},
{VIU_OSD2_BLK3_CFG_W4, 0x0, 0xffffffff, 0},
{VPU_RDARB_MODE_L1C2, 0x0, 0x00010000, 1},
{VIU_MISC_CTRL1, 0x0, 0x0000ff00, 1}
};
void recovery_regs_init(void)
{
int i = 0;
if (recovery_enable)
return;
memset(gRecovery, 0, sizeof(gRecovery));
gRecovery[i].base_addr = VIU_OSD1_CTRL_STAT;
gRecovery[i].size = sizeof(osd1_recovery_table)
/ sizeof(struct reg_item);
gRecovery[i].table =
(struct reg_item *)&osd1_recovery_table[0];
i++;
gRecovery[i].base_addr = OSD1_AFBCD_ENABLE;
gRecovery[i].size = sizeof(osd_afbcd_recovery_table)
/ sizeof(struct reg_item);
gRecovery[i].table =
(struct reg_item *)&osd_afbcd_recovery_table[0];
i++;
gRecovery[i].base_addr = VPP_OSD_VSC_PHASE_STEP;
gRecovery[i].size = sizeof(freescale_recovery_table)
/ sizeof(struct reg_item);
gRecovery[i].table =
(struct reg_item *)&freescale_recovery_table[0];
i++;
gRecovery[i].base_addr = VIU_OSD2_CTRL_STAT;
gRecovery[i].size = sizeof(osd2_recovery_table)
/ sizeof(struct reg_item);
gRecovery[i].table =
(struct reg_item *)&osd2_recovery_table[0];
i++;
gRecovery[i].base_addr = 0xffffffff; /* not base addr */
gRecovery[i].size = sizeof(misc_recovery_table)
/ sizeof(struct reg_item);
gRecovery[i].table =
(struct reg_item *)&misc_recovery_table[0];
recovery_enable = 1;
}
int update_recovery_item(u32 addr, u32 value)
{
u32 base, size;
int i;
struct reg_item *table = NULL;
int ret = -1;
if (!recovery_enable)
return ret;
base = addr & 0xfff0;
switch (base) {
case VIU_OSD1_CTRL_STAT:
case VIU_OSD1_BLK1_CFG_W1:
/* osd1 */
if (backup_enable &
HW_RESET_OSD1_REGS) {
ret = 1;
break;
}
base = gRecovery[0].base_addr;
size = gRecovery[0].size;
table = gRecovery[0].table;
if ((addr >= base) &&
(addr < base + size)) {
table[addr - base].val = value;
if (table[addr - base].recovery)
table[addr - base].recovery = 1;
ret = 0;
}
break;
case VIU_OSD2_CTRL_STAT:
case VIU_OSD2_BLK1_CFG_W1:
/* osd2 */
base = gRecovery[3].base_addr;
size = gRecovery[3].size;
table = gRecovery[3].table;
if ((addr >= base) &&
(addr < base + size)) {
table[addr - base].val = value;
if (table[addr - base].recovery)
table[addr - base].recovery = 1;
ret = 0;
}
break;
case OSD1_AFBCD_ENABLE:
/* osd1 afbcd */
if (backup_enable &
HW_RESET_AFBCD_REGS) {
ret = 1;
break;
}
base = gRecovery[1].base_addr;
size = gRecovery[1].size;
table = gRecovery[1].table;
if ((addr >= base) &&
(addr < base + size)) {
table[addr - base].val = value;
if (table[addr - base].recovery)
table[addr - base].recovery = 1;
ret = 0;
}
break;
case VPP_OSD_VSC_PHASE_STEP:
base = gRecovery[2].base_addr;
size = gRecovery[2].size;
table = gRecovery[2].table;
if ((addr >= base) &&
(addr < base + size)) {
table[addr - base].val = value;
if (table[addr - base].recovery)
table[addr - base].recovery = 1;
ret = 0;
}
break;
default:
break;
}
if ((addr == VIU_OSD2_BLK0_CFG_W4) ||
(addr == VIU_OSD2_BLK1_CFG_W4) ||
(addr == VIU_OSD2_BLK2_CFG_W4) ||
(addr == VIU_OSD2_BLK3_CFG_W4) ||
(addr == VPU_RDARB_MODE_L1C2) ||
(addr == VIU_MISC_CTRL1)) {
table = gRecovery[4].table;
for (i = 0; i < gRecovery[4].size; i++) {
if (addr == table[i].addr) {
table[i].val = value;
if (table[i].recovery)
table[i].recovery = 1;
ret = 0;
break;
}
}
}
return ret;
}
s32 get_recovery_item(u32 addr, u32 *value, u32 *mask)
{
u32 base, size;
int i;
struct reg_item *table = NULL;
int ret = -1;
if (!recovery_enable)
return ret;
base = addr & 0xfff0;
switch (base) {
case VIU_OSD1_CTRL_STAT:
case VIU_OSD1_BLK1_CFG_W1:
/* osd1 */
if (backup_enable &
HW_RESET_OSD1_REGS) {
ret = 2;
break;
}
base = gRecovery[0].base_addr;
size = gRecovery[0].size;
table = gRecovery[0].table;
if ((addr >= base) &&
(addr < base + size)) {
table += (addr - base);
ret = 0;
}
break;
case VIU_OSD2_CTRL_STAT:
case VIU_OSD2_BLK1_CFG_W1:
/* osd2 */
base = gRecovery[3].base_addr;
size = gRecovery[3].size;
table = gRecovery[3].table;
if ((addr >= base) &&
(addr < base + size)) {
table += (addr - base);
ret = 0;
}
break;
case OSD1_AFBCD_ENABLE:
/* osd1 afbcd */
if (backup_enable &
HW_RESET_AFBCD_REGS) {
ret = 2;
break;
}
base = gRecovery[1].base_addr;
size = gRecovery[1].size;
table = gRecovery[1].table;
if ((addr >= base) &&
(addr < base + size)) {
table += (addr - base);
ret = 0;
}
break;
case VPP_OSD_VSC_PHASE_STEP:
base = gRecovery[2].base_addr;
size = gRecovery[2].size;
table = gRecovery[2].table;
if ((addr >= base) &&
(addr < base + size)) {
table += (addr - base);
ret = 0;
}
break;
default:
break;
}
if ((addr == VIU_OSD2_BLK0_CFG_W4) ||
(addr == VIU_OSD2_BLK1_CFG_W4) ||
(addr == VIU_OSD2_BLK2_CFG_W4) ||
(addr == VIU_OSD2_BLK3_CFG_W4) ||
(addr == VPU_RDARB_MODE_L1C2) ||
(addr == VIU_MISC_CTRL1)) {
table = gRecovery[4].table;
for (i = 0; i < gRecovery[4].size; i++) {
if (addr == table[i].addr) {
table += i;
ret = 0;
break;
}
}
}
if (ret == 0 && table) {
if (table->recovery == 1) {
u32 regmask = table->mask;
u32 real_value = osd_reg_read(addr);
if ((real_value & regmask)
== (table->val & regmask)) {
ret = 1;
*mask = regmask;
*value = real_value;
} else {
*mask = regmask;
*value = real_value & ~(regmask);
*value |= (table->val & regmask);
}
table->recovery = 2;
} else if (table->recovery == 2)
ret = 1;
else
ret = -1;
}
/* ret = 1, 2 need not recovery,
* ret = 0 need recovery,
* ret = -1, not find
*/
return ret;
}
#else
void recovery_regs_init(void)
{
}
int update_recovery_item(u32 addr, u32 value)
{
addr = 0;
value = 0;
return 0;
}
s32 get_recovery_item(u32 addr, u32 *value, u32 *mask)
{
addr = 0;
value = NULL;
mask = NULL;
return 0;
}
#endif

View File

@@ -0,0 +1,63 @@
/*
* drivers/amlogic/media/osd/osd_backup.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_BACKUP_H_
#define _OSD_BACKUP_H_
#include "osd_reg.h"
#define OSD_REG_BACKUP_COUNT 12
#define OSD_AFBC_REG_BACKUP_COUNT 9
#define OSD_VALUE_COUNT (VIU_OSD1_CTRL_STAT2 - VIU_OSD1_CTRL_STAT + 1)
#define OSD_AFBC_VALUE_COUNT (OSD1_AFBCD_PIXEL_VSCOPE - OSD1_AFBCD_ENABLE + 1)
extern const u16 osd_reg_backup[OSD_REG_BACKUP_COUNT];
extern const u16 osd_afbc_reg_backup[OSD_AFBC_REG_BACKUP_COUNT];
extern u32 osd_backup[OSD_VALUE_COUNT];
extern u32 osd_afbc_backup[OSD_AFBC_VALUE_COUNT];
enum hw_reset_flag_e {
HW_RESET_NONE = 0,
HW_RESET_AFBCD_REGS = 0x80000000,
HW_RESET_OSD1_REGS = 0x00000001,
HW_RESET_AFBCD_HARDWARE = 0x80000000,
};
struct reg_item {
u32 addr;
u32 val;
u32 mask;
int recovery;
};
struct reg_recovery_table {
u32 base_addr;
u32 size;
struct reg_item *table;
};
extern void update_backup_reg(u32 addr, u32 value);
extern s32 get_backup_reg(u32 addr, u32 *value);
extern void backup_regs_init(u32 backup_mask);
extern u32 is_backup(void);
extern void recovery_regs_init(void);
extern int update_recovery_item(u32 addr, u32 value);
extern s32 get_recovery_item(u32 addr, u32 *value, u32 *mask);
#endif

View File

@@ -0,0 +1,27 @@
/*
* drivers/amlogic/media/osd/osd_canvas.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_CANVAS_H_
#define _OSD_CANVAS_H_
#define OSD1_CANVAS_INDEX 0x40
#define OSD2_CANVAS_INDEX 0x43
#define OSD3_CANVAS_INDEX 0x41
#define OSD4_CANVAS_INDEX 0x42
#define ALLOC_CANVAS_INDEX 0x44
#endif

View File

@@ -0,0 +1,205 @@
/*
* drivers/amlogic/media/osd/osd_clone.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
/* Amlogic Headers */
#include <linux/amlogic/cpu_version.h>
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#include <linux/amlogic/media/ge2d/ge2d.h>
#endif
/* Local Headers */
#include "osd_clone.h"
#include "osd_log.h"
#include "osd_io.h"
#include "osd_canvas.h"
#ifdef OSD_GE2D_CLONE_SUPPORT
struct osd_clone_s {
bool inited;
int angle;
int buffer_number;
u32 osd1_yres;
u32 osd2_yres;
struct config_para_ex_s ge2d_config;
struct ge2d_context_s *ge2d_context;
};
static DEFINE_MUTEX(osd_clone_mutex);
static struct osd_clone_s s_osd_clone;
static void osd_clone_process(void)
{
struct canvas_s cs, cd;
u32 x0 = 0;
u32 y0 = 0;
u32 y1 = 0;
unsigned char x_rev = 0;
unsigned char y_rev = 0;
unsigned char xy_swap = 0;
struct config_para_ex_s *ge2d_config = &s_osd_clone.ge2d_config;
struct ge2d_context_s *context = s_osd_clone.ge2d_context;
canvas_read(OSD1_CANVAS_INDEX, &cs);
canvas_read(OSD2_CANVAS_INDEX, &cd);
y0 = s_osd_clone.osd1_yres * s_osd_clone.buffer_number;
y1 = s_osd_clone.osd2_yres * s_osd_clone.buffer_number;
if (s_osd_clone.angle == 1) {
xy_swap = 1;
x_rev = 1;
} else if (s_osd_clone.angle == 2) {
x_rev = 1;
y_rev = 1;
} else if (s_osd_clone.angle == 3) {
xy_swap = 1;
y_rev = 1;
}
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width / 4;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width / 4;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_para.canvas_index = OSD1_CANVAS_INDEX;
ge2d_config->src_para.mem_type = CANVAS_OSD0;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ABGR;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = cs.width / 4;
ge2d_config->src_para.height = cs.height;
ge2d_config->dst_para.canvas_index = OSD2_CANVAS_INDEX;
ge2d_config->dst_para.mem_type = CANVAS_OSD1;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ABGR;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = cd.width / 4;
ge2d_config->dst_para.height = cd.height;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.x_rev = x_rev;
ge2d_config->dst_para.y_rev = y_rev;
ge2d_config->dst_xy_swap = xy_swap;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
osd_log_err("++ osd clone ge2d config error.\n");
return;
}
stretchblt(context, x0, y0, cs.width / 4, s_osd_clone.osd1_yres, x0, y1,
cd.width / 4, s_osd_clone.osd2_yres);
}
void osd_clone_update_pan(int buffer_number)
{
if (!s_osd_clone.inited)
return;
mutex_lock(&osd_clone_mutex);
s_osd_clone.buffer_number = buffer_number;
mutex_unlock(&osd_clone_mutex);
osd_clone_process();
}
void osd_clone_set_virtual_yres(u32 osd1_yres, u32 osd2_yres)
{
mutex_lock(&osd_clone_mutex);
s_osd_clone.osd1_yres = osd1_yres;
s_osd_clone.osd2_yres = osd2_yres;
mutex_unlock(&osd_clone_mutex);
}
void osd_clone_get_virtual_yres(u32 *osd2_yres)
{
mutex_lock(&osd_clone_mutex);
*osd2_yres = s_osd_clone.osd2_yres;
mutex_unlock(&osd_clone_mutex);
}
void osd_clone_set_angle(int angle)
{
mutex_lock(&osd_clone_mutex);
s_osd_clone.angle = angle;
mutex_unlock(&osd_clone_mutex);
}
int osd_clone_task_start(void)
{
if (s_osd_clone.inited) {
osd_log_info("osd_clone_task already started.\n");
return 0;
}
osd_log_info("osd_clone_task start.\n");
if (s_osd_clone.ge2d_context == NULL)
s_osd_clone.ge2d_context = create_ge2d_work_queue();
memset(&s_osd_clone.ge2d_config, 0, sizeof(struct config_para_ex_s));
s_osd_clone.inited = true;
return 1;
}
void osd_clone_task_stop(void)
{
if (!s_osd_clone.inited) {
osd_log_info("osd_clone_task already stopped.\n");
return;
}
osd_log_info("osd_clone_task stop.\n");
if (s_osd_clone.ge2d_context) {
destroy_ge2d_work_queue(s_osd_clone.ge2d_context);
s_osd_clone.ge2d_context = NULL;
}
s_osd_clone.inited = false;
}
#endif

View File

@@ -0,0 +1,50 @@
/*
* drivers/amlogic/media/osd/osd_clone.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_CLONE_H_
#define _OSD_CLONE_H_
#include "osd_log.h"
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#define OSD_GE2D_CLONE_SUPPORT 1
#endif
#ifdef OSD_GE2D_CLONE_SUPPORT
extern void osd_clone_set_virtual_yres(u32 osd1_yres, u32 osd2_yres);
extern void osd_clone_get_virtual_yres(u32 *osd2_yres);
extern void osd_clone_set_angle(int angle);
extern void osd_clone_update_pan(int buffer_number);
extern int osd_clone_task_start(void);
extern void osd_clone_task_stop(void);
#else
static inline void osd_clone_set_virtual_yres(u32 osd1_yres, u32 osd2_yres) {}
static inline void osd_clone_get_virtual_yres(u32 *osd2_yres) {}
static inline void osd_clone_set_angle(int angle) {}
static inline void osd_clone_update_pan(int buffer_number) {}
static inline int osd_clone_task_start(void)
{
osd_log_info("++ osd_clone depends on GE2D module!\n");
return 0;
}
static inline void osd_clone_task_stop(void)
{
osd_log_info("-- osd_clone depends on GE2D module!\n");
}
#endif
#endif

View File

@@ -0,0 +1,465 @@
/*
* drivers/amlogic/media/osd/osd_debug.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
/* Amlogic Headers */
#include <linux/amlogic/cpu_version.h>
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#include <linux/amlogic/media/ge2d/ge2d.h>
#endif
/* Local Headers */
#include "osd_canvas.h"
#include "osd_log.h"
#include "osd_reg.h"
#include "osd_io.h"
#include "osd_hw.h"
#define OSD_TEST_DURATION 200
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
static struct config_para_s ge2d_config;
static struct config_para_ex_s ge2d_config_ex;
static struct ge2d_context_s *ge2d_context;
#endif
char osd_debug_help[] = "Usage:\n"
" echo [i | info] > debug ; Show osd pan/display/scale information\n"
" echo [t | test] > debug ; Start osd auto test\n"
" echo [r | read] reg > debug ; Read VCBUS register\n"
" echo [w | write] reg val > debug ; Write VCBUS register\n"
" echo [d | dump] {start end} > debug ; Dump VCBUS register\n\n";
static void osd_debug_dump_value(void)
{
u32 index = 0;
struct hw_para_s *hwpara = NULL;
struct pandata_s *pdata = NULL;
osd_get_hw_para(&hwpara);
if (hwpara == NULL)
return;
osd_log_info("--- OSD ---\n");
osd_log_info("scan_mode: %d\n", hwpara->scan_mode);
osd_log_info("order: %d\n", hwpara->order);
osd_log_info("bot_type: %d\n", hwpara->bot_type);
osd_log_info("field_out_en: %d\n", hwpara->field_out_en);
for (index = 0; index < HW_OSD_COUNT; index++) {
osd_log_info("\n--- OSD%d ---\n", index);
osd_log_info("enable: %d\n", hwpara->enable[index]);
osd_log_info("2x-scale enable.h:%d .v: %d\n",
hwpara->scale[index].h_enable,
hwpara->scale[index].v_enable);
osd_log_info("free-scale-mode: %d\n",
hwpara->free_scale_mode[index]);
osd_log_info("free-scale enable.h:%d .v: %d\n",
hwpara->free_scale[index].h_enable,
hwpara->free_scale[index].v_enable);
pdata = &hwpara->pandata[index];
osd_log_info("pan data:\n");
osd_log_info("\tx_start: 0x%08x, x_end: 0x%08x\n",
pdata->x_start, pdata->x_end);
osd_log_info("\ty_start: 0x%08x, y_end: 0x%08x\n",
pdata->y_start, pdata->y_end);
pdata = &hwpara->dispdata[index];
osd_log_info("disp data:\n");
osd_log_info("\tx_start: 0x%08x, x_end: 0x%08x\n",
pdata->x_start, pdata->x_end);
osd_log_info("\ty_start: 0x%08x, y_end: 0x%08x\n",
pdata->y_start, pdata->y_end);
pdata = &hwpara->scaledata[index];
osd_log_info("2x-scale data:\n");
osd_log_info("\tx_start: 0x%08x, x_end: 0x%08x\n",
pdata->x_start, pdata->x_end);
osd_log_info("\ty_start: 0x%08x, y_end: 0x%08x\n",
pdata->y_start, pdata->y_end);
pdata = &hwpara->free_src_data[index];
osd_log_info("free-scale src data:\n");
osd_log_info("\tx_start: 0x%08x, x_end: 0x%08x\n",
pdata->x_start, pdata->x_end);
osd_log_info("\ty_start: 0x%08x, y_end: 0x%08x\n",
pdata->y_start, pdata->y_end);
pdata = &hwpara->free_dst_data[index];
osd_log_info("free-scale dst data:\n");
osd_log_info("\tx_start: 0x%08x, x_end: 0x%08x\n",
pdata->x_start, pdata->x_end);
osd_log_info("\ty_start: 0x%08x, y_end: 0x%08x\n",
pdata->y_start, pdata->y_end);
}
}
static void osd_debug_dump_register_all(void)
{
u32 reg = 0;
u32 offset = 0;
u32 index = 0;
reg = VPU_VIU_VENC_MUX_CTRL;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_MISC;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_OFIFO_SIZE;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_HOLD_LINES;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_OSD_SC_CTRL0;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_OSD_SCI_WH_M1;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_OSD_SCO_H_START_END;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VPP_OSD_SCO_V_START_END;
osd_log_info("reg[0x%x]: 0x%08x\n\n", reg, osd_reg_read(reg));
for (index = 0; index < 2; index++) {
if (index == 1)
offset = REG_OFFSET;
reg = offset + VIU_OSD1_FIFO_CTRL_STAT;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_CTRL_STAT;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_CTRL_STAT2;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_BLK0_CFG_W0;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_BLK0_CFG_W1;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_BLK0_CFG_W2;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = offset + VIU_OSD1_BLK0_CFG_W3;
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
reg = VIU_OSD1_BLK0_CFG_W4;
if (index == 1)
reg = VIU_OSD2_BLK0_CFG_W4;
osd_log_info("reg[0x%x]: 0x%08x\n\n", reg, osd_reg_read(reg));
}
if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) ||
(get_cpu_type() == MESON_CPU_MAJOR_ID_GXM)) {
reg = VIU_MISC_CTRL1;
osd_log_info("reg[0x%x]: 0x%08x\n",
reg, osd_reg_read(reg));
for (reg = OSD1_AFBCD_ENABLE;
reg <= OSD1_AFBCD_PIXEL_VSCOPE; reg++)
osd_log_info("reg[0x%x]: 0x%08x\n",
reg, osd_reg_read(reg));
}
}
static void osd_debug_dump_register_region(u32 start, u32 end)
{
u32 reg = 0;
for (reg = start; reg <= end; reg += 4)
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
}
static void osd_debug_dump_register(int argc, char **argv)
{
int reg_start, reg_end;
int ret;
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
read_rdma_table();
#endif
if ((argc == 3) && argv[1] && argv[2]) {
ret = kstrtoint(argv[1], 16, &reg_start);
ret = kstrtoint(argv[2], 16, &reg_end);
osd_debug_dump_register_region(reg_start, reg_end);
} else {
osd_debug_dump_register_all();
}
}
static void osd_debug_read_register(int argc, char **argv)
{
int reg;
int ret;
if ((argc == 2) && argv[1]) {
ret = kstrtoint(argv[1], 16, &reg);
osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
} else {
osd_log_err("read: arg error\n");
}
}
static void osd_debug_write_register(int argc, char **argv)
{
int reg, val;
int ret;
if ((argc == 3) && argv[1] && argv[2]) {
ret = kstrtoint(argv[1], 16, &reg);
ret = kstrtoint(argv[2], 16, &val);
osd_reg_write(reg, val);
osd_log_info("reg[0x%x]: 0x%08x =0x%08x\n",
reg, val, osd_reg_read(reg));
} else {
osd_log_err("write: arg error\n");
}
}
static void osd_test_colorbar(void)
{
#define HHI_GCLK_OTHER 0x1054
u32 gclk_other = 0;
u32 encp_video_adv = 0;
gclk_other = aml_read_cbus(HHI_GCLK_OTHER);
encp_video_adv = osd_reg_read(ENCP_VIDEO_MODE_ADV);
/* start test mode */
osd_log_info("--- OSD TEST COLORBAR ---\n");
aml_write_cbus(HHI_GCLK_OTHER, 0xFFFFFFFF);
osd_reg_write(ENCP_VIDEO_MODE_ADV, 0);
osd_reg_write(VENC_VIDEO_TST_EN, 1);
/* TST_MODE COLORBAR */
osd_log_info("- COLORBAR -\n");
osd_reg_write(VENC_VIDEO_TST_MDSEL, 1);
msleep(OSD_TEST_DURATION);
/* TST_MODE THINLINE */
osd_log_info("- THINLINE -\n");
osd_reg_write(VENC_VIDEO_TST_MDSEL, 2);
msleep(OSD_TEST_DURATION);
/* TST_MODE DOTGRID */
osd_log_info("- DOTGRID -\n");
osd_reg_write(VENC_VIDEO_TST_MDSEL, 3);
msleep(OSD_TEST_DURATION);
/* stop test mode */
aml_write_cbus(HHI_GCLK_OTHER, gclk_other);
osd_reg_write(ENCP_VIDEO_MODE_ADV, encp_video_adv);
osd_reg_write(VENC_VIDEO_TST_EN, 0);
osd_reg_write(VENC_VIDEO_TST_MDSEL, 0);
}
static void osd_reset(void)
{
osd_set_free_scale_enable_hw(0, 0);
osd_enable_hw(0, 1);
}
static void osd_test_dummydata(void)
{
u32 dummy_data = 0;
dummy_data = osd_reg_read(VPP_DUMMY_DATA1);
osd_reset();
osd_log_info("--- OSD TEST DUMMYDATA ---\n");
osd_reg_write(VPP_DUMMY_DATA1, 0xFF);
msleep(OSD_TEST_DURATION);
osd_reg_write(VPP_DUMMY_DATA1, 0);
msleep(OSD_TEST_DURATION);
osd_reg_write(VPP_DUMMY_DATA1, 0xFF00);
msleep(OSD_TEST_DURATION);
osd_reg_write(VPP_DUMMY_DATA1, dummy_data);
}
static void osd_test_rect(void)
{
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
u32 x = 0;
u32 y = 0;
u32 w = 0;
u32 h = 0;
u32 color = 0;
struct canvas_s cs;
struct config_para_s *cfg = &ge2d_config;
struct config_para_ex_s *cfg_ex = &ge2d_config_ex;
struct ge2d_context_s *context = ge2d_context;
canvas_read(OSD1_CANVAS_INDEX, &cs);
context = create_ge2d_work_queue();
if (!context) {
osd_log_err("create work queue error\n");
return;
}
memset(cfg, 0, sizeof(struct config_para_s));
cfg->src_dst_type = OSD0_OSD0;
cfg->src_format = GE2D_FORMAT_S32_ARGB;
cfg->src_planes[0].addr = cs.addr;
cfg->src_planes[0].w = cs.width / 4;
cfg->src_planes[0].h = cs.height;
cfg->dst_planes[0].addr = cs.addr;
cfg->dst_planes[0].w = cs.width / 4;
cfg->dst_planes[0].h = cs.height;
if (ge2d_context_config(context, cfg) < 0) {
osd_log_err("ge2d config error.\n");
return;
}
x = 0;
y = 0;
w = cs.width / 4;
h = cs.height;
color = 0x0;
osd_log_info("- BLACK -");
osd_log_info("- (%d, %d)-(%d, %d) -\n", x, y, w, h);
fillrect(context, x, y, h, w, color);
msleep(OSD_TEST_DURATION);
x = 100;
y = 0;
w = 100;
h = 100;
color = 0xFF0000FF;
osd_log_info("- RED -\n");
osd_log_info("- (%d, %d)-(%d, %d) -\n", x, y, w, h);
fillrect(context, x, y, h, w, color);
msleep(OSD_TEST_DURATION);
x += 100;
color = 0x00FF00FF;
osd_log_info("- GREEN -\n");
osd_log_info("- (%d, %d)-(%d, %d) -\n", x, y, w, h);
fillrect(context, x, y, h, w, color);
msleep(OSD_TEST_DURATION);
x += 100;
color = 0x0000FFFF;
osd_log_info("- BlUE -\n");
osd_log_info("- (%d, %d)-(%d, %d) -\n", x, y, w, h);
fillrect(context, x, y, h, w, color);
msleep(OSD_TEST_DURATION);
memset(cfg_ex, 0, sizeof(struct config_para_ex_s));
cfg_ex->src_planes[0].addr = cs.addr;
cfg_ex->src_planes[0].w = cs.width / 4;
cfg_ex->src_planes[0].h = cs.height;
cfg_ex->dst_planes[0].addr = cs.addr;
cfg_ex->dst_planes[0].w = cs.width / 4;
cfg_ex->dst_planes[0].h = cs.height;
cfg_ex->src_para.canvas_index = OSD1_CANVAS_INDEX;
cfg_ex->src_para.mem_type = CANVAS_OSD0;
cfg_ex->src_para.format = GE2D_FORMAT_S32_ARGB;
cfg_ex->src_para.fill_color_en = 0;
cfg_ex->src_para.fill_mode = 0;
cfg_ex->src_para.x_rev = 0;
cfg_ex->src_para.y_rev = 0;
cfg_ex->src_para.color = 0xffffffff;
cfg_ex->src_para.top = 0;
cfg_ex->src_para.left = 0;
cfg_ex->src_para.width = cs.width / 4;
cfg_ex->src_para.height = cs.height;
cfg_ex->dst_para.canvas_index = OSD1_CANVAS_INDEX;
cfg_ex->dst_para.mem_type = CANVAS_OSD0;
cfg_ex->dst_para.format = GE2D_FORMAT_S32_ARGB;
cfg_ex->dst_para.top = 0;
cfg_ex->dst_para.left = 0;
cfg_ex->dst_para.width = cs.width / 4;
cfg_ex->dst_para.height = cs.height;
cfg_ex->dst_para.fill_color_en = 0;
cfg_ex->dst_para.fill_mode = 0;
cfg_ex->dst_para.color = 0;
cfg_ex->dst_para.x_rev = 0;
cfg_ex->dst_para.y_rev = 0;
cfg_ex->dst_xy_swap = 0;
if (ge2d_context_config_ex(context, cfg_ex) < 0) {
osd_log_err("ge2d config error.\n");
return;
}
stretchblt(context, 100, 0, 400, 100, 100, 200, 700, 200);
destroy_ge2d_work_queue(ge2d_context);
#endif
}
static void osd_debug_auto_test(void)
{
osd_test_colorbar();
osd_test_dummydata();
osd_test_rect();
}
char *osd_get_debug_hw(void)
{
return osd_debug_help;
}
int osd_set_debug_hw(const char *buf)
{
int argc;
char *buffer, *p, *para;
char *argv[4];
char cmd;
buffer = kstrdup(buf, GFP_KERNEL);
p = buffer;
for (argc = 0; argc < 4; argc++) {
para = strsep(&p, " ");
if (para == NULL)
break;
argv[argc] = para;
}
if (argc < 1 || argc > 4) {
kfree(buffer);
return -EINVAL;
}
cmd = argv[0][0];
switch (cmd) {
case 'i':
osd_debug_dump_value();
break;
case 'd':
osd_debug_dump_register(argc, argv);
break;
case 'r':
osd_debug_read_register(argc, argv);
break;
case 'w':
osd_debug_write_register(argc, argv);
break;
case 't':
osd_debug_auto_test();
break;
default:
osd_log_err("arg error\n");
break;
}
kfree(buffer);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* drivers/amlogic/media/osd/osd_fb.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_FB_H_
#define _OSD_FB_H_
/* Linux Headers */
#include <linux/list.h>
#include <linux/fb.h>
#include <linux/types.h>
/* Local Headers */
#include "osd.h"
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD2_ENABLE
#define OSD_COUNT 2 /* enable two OSD layers */
#else
#define OSD_COUNT 1 /* only enable one OSD layer */
#endif
#define INVALID_BPP_ITEM {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
struct osd_fb_dev_s {
struct mutex lock;
struct fb_info *fb_info;
struct platform_device *dev;
phys_addr_t fb_mem_paddr;
void __iomem *fb_mem_vaddr;
u32 fb_len;
phys_addr_t fb_mem_afbc_paddr[OSD_MAX_BUF_NUM];
void __iomem *fb_mem_afbc_vaddr[OSD_MAX_BUF_NUM];
u32 fb_afbc_len[OSD_MAX_BUF_NUM];
const struct color_bit_define_s *color;
enum vmode_e vmode;
struct osd_ctl_s osd_ctl;
u32 order;
u32 scale;
u32 enable_3d;
u32 preblend_enable;
u32 enable_key_flag;
u32 color_key;
u32 fb_index;
bool dis_osd_mchange;
};
struct fb_dmabuf_export {
__u32 buffer_idx;
__u32 fd;
__u32 flags;
};
#define OSD_INVALID_INFO 0xffffffff
#define OSD_FIRST_GROUP_START 1
#define OSD_SECOND_GROUP_START 4
#define OSD_END 7
extern phys_addr_t get_fb_rmem_paddr(int index);
extern void __iomem *get_fb_rmem_vaddr(int index);
extern size_t get_fb_rmem_size(int index);
extern int osd_blank(int blank_mode, struct fb_info *info);
extern struct osd_fb_dev_s *gp_fbdev_list[];
extern const struct color_bit_define_s default_color_format_array[];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
/*
* drivers/amlogic/media/osd/osd_hw.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_HW_H_
#define _OSD_HW_H_
#include <linux/amlogic/media/vout/vinfo.h>
#include "osd.h"
#define REG_OFFSET (0x20)
#define OSD_RELATIVE_BITS 0x33330
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
#include "osd_rdma.h"
#endif
extern int int_viu_vsync;
#ifdef CONFIG_HIBERNATION
extern void osd_freeze_hw(void);
extern void osd_thaw_hw(void);
extern void osd_restore_hw(void);
extern void osd_realdata_save_hw(void);
extern void osd_realdata_restore_hw(void);
#endif
extern void osd_set_color_key_hw(u32 index, u32 bpp, u32 colorkey);
extern void osd_srckey_enable_hw(u32 index, u8 enable);
extern void osd_set_gbl_alpha_hw(u32 index, u32 gbl_alpha);
extern u32 osd_get_gbl_alpha_hw(u32 index);
extern void osd_set_color_mode(u32 index,
const struct color_bit_define_s *color);
extern void osd_update_disp_axis_hw(
u32 index,
u32 display_h_start,
u32 display_h_end,
u32 display_v_start,
u32 display_v_end,
u32 xoffset,
u32 yoffset,
u32 mode_change);
extern void osd_setup_hw(u32 index,
struct osd_ctl_s *osd_ctl,
u32 xoffset,
u32 yoffset,
u32 xres,
u32 yres,
u32 xres_virtual,
u32 yres_virtual,
u32 disp_start_x,
u32 disp_start_y,
u32 disp_end_x,
u32 disp_end_y,
u32 fbmem,
phys_addr_t *afbc_fbmem,
const struct color_bit_define_s *color);
extern void osd_set_order_hw(u32 index, u32 order);
extern void osd_get_order_hw(u32 index, u32 *order);
extern void osd_set_free_scale_enable_hw(u32 index, u32 enable);
extern void osd_get_free_scale_enable_hw(u32 index, u32 *free_scale_enable);
extern void osd_set_free_scale_mode_hw(u32 index, u32 freescale_mode);
extern void osd_get_free_scale_mode_hw(u32 index, u32 *freescale_mode);
extern void osd_set_4k2k_fb_mode_hw(u32 fb_for_4k2k);
extern void osd_get_free_scale_mode_hw(u32 index, u32 *freescale_mode);
extern void osd_get_free_scale_width_hw(u32 index, u32 *free_scale_width);
extern void osd_get_free_scale_height_hw(u32 index, u32 *free_scale_height);
extern void osd_get_free_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_set_free_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1,
s32 y1);
extern void osd_get_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1);
extern void osd_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1);
extern void osd_get_block_windows_hw(u32 index, u32 *windows);
extern void osd_set_block_windows_hw(u32 index, u32 *windows);
extern void osd_get_block_mode_hw(u32 index, u32 *mode);
extern void osd_set_block_mode_hw(u32 index, u32 mode);
extern void osd_enable_3d_mode_hw(u32 index, u32 enable);
extern void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable,
u16 v_scale_enable);
extern void osd_get_flush_rate_hw(u32 *break_rate);
extern void osd_set_reverse_hw(u32 index, u32 reverse);
extern void osd_get_reverse_hw(u32 index, u32 *reverse);
extern void osd_set_antiflicker_hw(u32 index, struct vinfo_s *vinfo, u32 yres);
extern void osd_get_antiflicker_hw(u32 index, u32 *on_off);
extern void osd_get_angle_hw(u32 index, u32 *angle);
extern void osd_set_angle_hw(u32 index, u32 angle, u32 virtual_osd1_yres,
u32 virtual_osd2_yres);
extern void osd_get_clone_hw(u32 index, u32 *clone);
extern void osd_set_clone_hw(u32 index, u32 clone);
extern void osd_set_update_pan_hw(u32 index);
extern void osd_setpal_hw(u32 index, unsigned int regno,
unsigned int red, unsigned int green,
unsigned int blue, unsigned int transp);
extern void osd_enable_hw(u32 index, u32 enable);
extern void osd_pan_display_hw(u32 index, unsigned int xoffset,
unsigned int yoffset);
extern int osd_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
s32 in_fence_fd);
extern s32 osd_wait_vsync_event(void);
#if defined(CONFIG_AMLOGIC_MEDIA_FB_OSD2_CURSOR)
extern void osd_cursor_hw(u32 index, s16 x, s16 y, s16 xstart, s16 ystart,
u32 osd_w, u32 osd_h);
#endif
extern void osd_init_scan_mode(void);
extern void osd_suspend_hw(void);
extern void osd_resume_hw(void);
extern void osd_shutdown_hw(void);
extern void osd_init_hw(u32 logo_loaded);
extern void osd_init_scan_mode(void);
extern void osd_set_logo_index(int index);
extern int osd_get_logo_index(void);
extern int osd_get_init_hw_flag(void);
extern void osd_get_hw_para(struct hw_para_s **para);
extern int osd_set_debug_hw(const char *buf);
extern char *osd_get_debug_hw(void);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
extern void enable_rdma(int enable_flag);
#endif
#ifdef CONFIG_AM_FB_EXT
extern void osd_ext_clone_pan(u32 index);
#endif
extern void osd_set_pxp_mode(u32 mode);
extern void osd_set_afbc(u32 enable);
extern u32 osd_get_afbc(void);
extern u32 osd_get_reset_status(void);
extern void osd_switch_free_scale(
u32 pre_index, u32 pre_enable, u32 pre_scale,
u32 next_index, u32 next_enable, u32 next_scale);
extern void osd_get_urgent(u32 index, u32 *urgent);
extern void osd_set_urgent(u32 index, u32 urgent);
#endif

View File

@@ -0,0 +1,140 @@
/*
* drivers/amlogic/media/osd/osd_hw_def.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_HW_DEF_H_
#define _OSD_HW_DEF_H_
#include <linux/list.h>
#include "osd_hw.h"
static void osd1_update_color_mode(void);
static void osd1_update_enable(void);
static void osd1_update_color_key(void);
static void osd1_update_color_key_enable(void);
static void osd1_update_gbl_alpha(void);
static void osd1_update_order(void);
static void osd1_update_disp_geometry(void);
static void osd1_update_coef(void);
static void osd1_update_disp_freescale_enable(void);
static void osd1_update_disp_osd_reverse(void);
static void osd1_update_disp_osd_rotate(void);
static void osd1_update_disp_scale_enable(void);
static void osd1_update_disp_3d_mode(void);
static void osd1_update_fifo(void);
static void osd2_update_color_mode(void);
static void osd2_update_enable(void);
static void osd2_update_color_key(void);
static void osd2_update_color_key_enable(void);
static void osd2_update_gbl_alpha(void);
static void osd2_update_order(void);
static void osd2_update_disp_geometry(void);
static void osd2_update_coef(void);
static void osd2_update_disp_freescale_enable(void);
static void osd2_update_disp_osd_reverse(void);
static void osd2_update_disp_osd_rotate(void);
static void osd2_update_disp_scale_enable(void);
static void osd2_update_disp_3d_mode(void);
static void osd2_update_fifo(void);
LIST_HEAD(update_list);
static DEFINE_SPINLOCK(osd_lock);
static unsigned long lock_flags;
#ifdef FIQ_VSYNC
static unsigned long fiq_flag;
#endif
static update_func_t hw_func_array[HW_OSD_COUNT][HW_REG_INDEX_MAX] = {
{
osd1_update_color_mode,
osd1_update_enable,
osd1_update_color_key,
osd1_update_color_key_enable,
osd1_update_gbl_alpha,
osd1_update_order,
osd1_update_coef,
osd1_update_disp_geometry,
osd1_update_disp_scale_enable,
osd1_update_disp_freescale_enable,
osd1_update_disp_osd_reverse,
osd1_update_disp_osd_rotate,
osd1_update_fifo,
},
{
osd2_update_color_mode,
osd2_update_enable,
osd2_update_color_key,
osd2_update_color_key_enable,
osd2_update_gbl_alpha,
osd2_update_order,
osd2_update_coef,
osd2_update_disp_geometry,
osd2_update_disp_scale_enable,
osd2_update_disp_freescale_enable,
osd2_update_disp_osd_reverse,
osd2_update_disp_osd_rotate,
osd2_update_fifo,
},
};
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
#ifdef FIQ_VSYNC
#define add_to_update_list(osd_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_lock, lock_flags); \
raw_local_save_flags(fiq_flag); \
local_fiq_disable(); \
osd_hw.reg[osd_idx][cmd_idx].update_func(); \
raw_local_irq_restore(fiq_flag); \
spin_unlock_irqrestore(&osd_lock, lock_flags); \
} while (0)
#else
#define add_to_update_list(osd_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_lock, lock_flags); \
osd_hw.reg[osd_idx][cmd_idx].update_func(); \
spin_unlock_irqrestore(&osd_lock, lock_flags); \
} while (0)
#endif
#else
#ifdef FIQ_VSYNC
#define add_to_update_list(osd_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_lock, lock_flags); \
raw_local_save_flags(fiq_flag); \
local_fiq_disable(); \
osd_hw.updated[osd_idx] |= (1<<cmd_idx); \
raw_local_irq_restore(fiq_flag); \
spin_unlock_irqrestore(&osd_lock, lock_flags); \
} while (0)
#else
#define add_to_update_list(osd_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_lock, lock_flags); \
osd_hw.updated[osd_idx] |= (1<<cmd_idx); \
spin_unlock_irqrestore(&osd_lock, lock_flags); \
} while (0)
#endif
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
#define remove_from_update_list(osd_idx, cmd_idx)
#else
#define remove_from_update_list(osd_idx, cmd_idx) \
(osd_hw.updated[osd_idx] &= ~(1<<cmd_idx))
#endif
#endif

View File

@@ -0,0 +1,108 @@
/*
* drivers/amlogic/media/osd/osd_io.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_IO_H_
#define _OSD_IO_H_
#include <linux/amlogic/iomap.h>
#include "osd_log.h"
#include "osd_backup.h"
static inline uint32_t osd_cbus_read(uint32_t reg)
{
uint32_t ret = 0;
ret = (uint32_t)aml_read_cbus(reg);
osd_log_dbg3("%s(0x%x)=0x%x\n", __func__, reg, ret);
return ret;
};
static inline void osd_cbus_write(uint32_t reg,
const uint32_t val)
{
uint32_t ret = 0;
aml_write_cbus(reg, val);
ret = aml_read_cbus(reg);
osd_log_dbg3("%s(0x%x, 0x%x)=0x%x\n", __func__, reg, val, ret);
};
static inline uint32_t osd_reg_read(uint32_t reg)
{
uint32_t ret = 0;
/* if (get_backup_reg(reg, &ret) != 0) */
/* not read from bakcup */
ret = (uint32_t)aml_read_vcbus(reg);
osd_log_dbg3("%s(0x%x)=0x%x\n", __func__, reg, ret);
return ret;
};
static inline void osd_reg_write(uint32_t reg,
const uint32_t val)
{
aml_write_vcbus(reg, val);
update_backup_reg(reg, val);
osd_log_dbg3("%s(0x%x, 0x%x)\n", __func__, reg, val);
};
static inline void osd_reg_set_mask(uint32_t reg,
const uint32_t mask)
{
osd_reg_write(reg, (osd_reg_read(reg) | (mask)));
}
static inline void osd_reg_clr_mask(uint32_t reg,
const uint32_t mask)
{
osd_reg_write(reg, (osd_reg_read(reg) & (~(mask))));
}
static inline void osd_reg_set_bits(uint32_t reg,
const uint32_t value,
const uint32_t start,
const uint32_t len)
{
osd_reg_write(reg, ((osd_reg_read(reg) &
~(((1L << (len)) - 1) << (start))) |
(((value) & ((1L << (len)) - 1)) << (start))));
}
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
u32 VSYNCOSD_RD_MPEG_REG(u32 reg);
int VSYNCOSD_WR_MPEG_REG(u32 reg, u32 val);
int VSYNCOSD_WR_MPEG_REG_BITS(u32 reg, u32 val, u32 start, u32 len);
int VSYNCOSD_SET_MPEG_REG_MASK(u32 reg, u32 mask);
int VSYNCOSD_CLR_MPEG_REG_MASK(u32 reg, u32 mask);
int VSYNCOSD_IRQ_WR_MPEG_REG(u32 reg, u32 val);
#else
#define VSYNCOSD_RD_MPEG_REG(reg) osd_reg_read(reg)
#define VSYNCOSD_WR_MPEG_REG(reg, val) osd_reg_write(reg, val)
#define VSYNCOSD_WR_MPEG_REG_BITS(reg, val, start, len) \
osd_reg_set_bits(reg, val, start, len)
#define VSYNCOSD_SET_MPEG_REG_MASK(reg, mask) osd_reg_set_mask(reg, mask)
#define VSYNCOSD_CLR_MPEG_REG_MASK(reg, mask) osd_reg_clr_mask(reg, mask)
#define VSYNCOSD_IRQ_WR_MPEG_REG(reg, val) osd_reg_write(reg, val)
#endif
#endif

View File

@@ -0,0 +1,61 @@
/*
* drivers/amlogic/media/osd/osd_log.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_LOG_H_
#define _OSD_LOG_H_
#include <stdarg.h>
#include <linux/printk.h>
#define OSD_LOG_LEVEL_NULL 0
#define OSD_LOG_LEVEL_DEBUG 1
#define OSD_LOG_LEVEL_DEBUG2 2
#define OSD_LOG_LEVEL_DEBUG3 3
extern unsigned int osd_log_level;
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define osd_log_info(fmt, ...) \
pr_info(fmt, ##__VA_ARGS__)
#define osd_log_err(fmt, ...) \
pr_err(fmt, ##__VA_ARGS__)
#define osd_log_dbg(fmt, ...) \
do { \
if (osd_log_level >= OSD_LOG_LEVEL_DEBUG) { \
pr_info(fmt, ##__VA_ARGS__); \
} \
} while (0)
#define osd_log_dbg2(fmt, ...) \
do { \
if (osd_log_level >= OSD_LOG_LEVEL_DEBUG2) { \
pr_info(fmt, ##__VA_ARGS__); \
} \
} while (0)
#define osd_log_dbg3(fmt, ...) \
do { \
if (osd_log_level >= OSD_LOG_LEVEL_DEBUG3) { \
pr_info(fmt, ##__VA_ARGS__); \
} \
} while (0)
#endif

View File

@@ -0,0 +1,252 @@
/*
* drivers/amlogic/media/osd/osd_progressbar.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/of_fdt.h>
#include <linux/console.h>
#include <linux/amlogic/ge2d/ge2d.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#include "osd_canvas.h"
#include "osd_fb.h"
#include "osd_hw.h"
#include "osd_io.h"
#include "osd_reg.h"
struct src_dst_info_s {
struct rectangle_s src_rect;
struct rectangle_s dst_rect;
unsigned int color;
};
struct osd_progress_bar_s {
struct ge2d_context_s *ge2d_context;
const struct vinfo_s *vinfo;
struct src_dst_info_s op_info;
u32 bar_border;
u32 bar_width;
u32 bar_height;
};
static struct osd_progress_bar_s progress_bar;
static struct config_para_s ge2d_config;
static struct ge2d_context_s *ge2d_context;
static int init_fb1_first(const struct vinfo_s *vinfo)
{
struct osd_ctl_s osd_ctl;
const struct color_bit_define_s *color;
u32 reg = 0, data32 = 0;
size_t osd_size;
void __iomem *osd_vaddr;
osd_ctl.index = 1;
color = &default_color_format_array[31];
osd_ctl.addr = get_fb_rmem_paddr(osd_ctl.index);
osd_vaddr = get_fb_rmem_vaddr(osd_ctl.index);
osd_size = get_fb_rmem_size(osd_ctl.index);
osd_ctl.xres = vinfo->width;
osd_ctl.yres = vinfo->height;
osd_ctl.xres_virtual = osd_ctl.xres;
osd_ctl.yres_virtual = osd_ctl.yres;
osd_ctl.disp_start_x = 0;
osd_ctl.disp_end_x = osd_ctl.xres - 1;
osd_ctl.disp_start_y = (vinfo->height * 9) / 10;
osd_ctl.disp_end_y = osd_ctl.yres - 1;
reg = osd_ctl.index == 0 ? VIU_OSD1_BLK0_CFG_W0 : VIU_OSD2_BLK0_CFG_W0;
data32 = VSYNCOSD_RD_MPEG_REG(reg) & (~(0xf<<8));
data32 |= color->hw_blkmode << 8; /* osd_blk_mode */
VSYNCOSD_WR_MPEG_REG(reg, data32);
memset(osd_vaddr, 0, osd_size);
pr_debug("addr is 0x%08x, xres is %d, yres is %d\n",
osd_ctl.addr, osd_ctl.xres, osd_ctl.yres);
osd_setup_hw(osd_ctl.index,
&osd_ctl,
0,
0,
osd_ctl.xres,
osd_ctl.yres,
osd_ctl.xres_virtual,
osd_ctl.yres_virtual,
osd_ctl.disp_start_x,
osd_ctl.disp_start_y,
osd_ctl.disp_end_x,
osd_ctl.disp_end_y,
osd_ctl.addr,
NULL,
color);
return 0;
}
int osd_show_progress_bar(u32 percent)
{
static u32 progress;
u32 step = 1;
/* wait_queue_head_t wait_head; */
struct osd_fb_dev_s *fb_dev;
struct ge2d_context_s *context = progress_bar.ge2d_context;
struct src_dst_info_s *op_info = &progress_bar.op_info;
if (context == NULL) {
/* osd_init_progress_bar(); */
pr_debug("context is NULL\n");
return -1;
}
fb_dev = gp_fbdev_list[1];
if (fb_dev == NULL) {
pr_debug("fb1 should exit!!!");
return -EFAULT;
}
while (progress < percent) {
pr_debug("progress is %d, x: [%d], y: [%d], w: [%d], h: [%d]\n",
progress, op_info->dst_rect.x, op_info->dst_rect.y,
op_info->dst_rect.w, op_info->dst_rect.h);
fillrect(context, op_info->dst_rect.x,
op_info->dst_rect.y,
op_info->dst_rect.w,
op_info->dst_rect.h,
op_info->color);
/* wait_event_interruptible_timeout(wait_head,0,4); */
progress += step;
op_info->dst_rect.x += op_info->dst_rect.w;
op_info->color -= (0xff*step/100) << 16;
}
if (percent == 100) {
progress = 0;
osd_blank(1, fb_dev->fb_info);
destroy_ge2d_work_queue(progress_bar.ge2d_context);
}
return 0;
}
EXPORT_SYMBOL(osd_show_progress_bar);
int osd_init_progress_bar(void)
{
struct src_dst_info_s *op_info = &progress_bar.op_info;
const struct vinfo_s *vinfo = progress_bar.vinfo;
struct osd_fb_dev_s *fb_dev;
struct canvas_s cs;
struct config_para_s *cfg = &ge2d_config;
struct ge2d_context_s *context = ge2d_context;
u32 step = 1;
memset(&progress_bar, 0, sizeof(struct osd_progress_bar_s));
vinfo = get_current_vinfo();
progress_bar.bar_border =
(((vinfo->field_height ?
vinfo->field_height :
vinfo->height) * 4 / 720)>>2)<<2;
progress_bar.bar_width =
(((vinfo->width * 200 / 1280)>>2)<<2) + progress_bar.bar_border;
progress_bar.bar_height =
(((vinfo->field_height ?
vinfo->field_height :
vinfo->height) * 32 / 720) >> 2) << 2;
if (!init_fb1_first(vinfo)) {
fb_dev = gp_fbdev_list[1];
if (fb_dev == NULL) {
pr_debug("fb1 should exit!!!");
return -EFAULT;
}
canvas_read(OSD2_CANVAS_INDEX, &cs);
context = create_ge2d_work_queue();
if (!context) {
pr_debug("create work queue error\n");
return -EFAULT;
}
memset(cfg, 0, sizeof(struct config_para_s));
cfg->src_dst_type = OSD1_OSD1;
cfg->src_format = GE2D_FORMAT_S32_ARGB;
cfg->src_planes[0].addr = cs.addr;
cfg->src_planes[0].w = cs.width / 4;
cfg->src_planes[0].h = cs.height;
cfg->dst_planes[0].addr = cs.addr;
cfg->dst_planes[0].w = cs.width / 4;
cfg->dst_planes[0].h = cs.height;
if (ge2d_context_config(context, cfg) < 0) {
pr_debug("ge2d config error.\n");
return -EFAULT;
}
if (context == NULL) {
pr_debug("ge2d_context is NULL!!!!!!\n");
return -EFAULT;
}
progress_bar.ge2d_context = context;
pr_debug("progress bar setup ge2d device OK\n");
/* show fb1 */
console_lock();
osd_blank(0, fb_dev->fb_info);
console_unlock();
op_info->color = 0x555555ff;
op_info->dst_rect.x =
(vinfo->width / 2) - progress_bar.bar_width;
op_info->dst_rect.y = 0;
op_info->dst_rect.w = progress_bar.bar_width * 2;
op_info->dst_rect.h = progress_bar.bar_height;
pr_debug("fill==dst:%d-%d-%d-%d\n",
op_info->dst_rect.x, op_info->dst_rect.y,
op_info->dst_rect.w, op_info->dst_rect.h);
fillrect(context, op_info->dst_rect.x,
op_info->dst_rect.y,
op_info->dst_rect.w,
op_info->dst_rect.h,
op_info->color);
} else {
pr_debug("fb1 init failed, exit!!!");
return -EFAULT;
}
/* initial op info before draw actrualy */
op_info->dst_rect.x += progress_bar.bar_border;
op_info->dst_rect.y += progress_bar.bar_border;
op_info->dst_rect.w =
(progress_bar.bar_width - progress_bar.bar_border)
* 2 * step/100;
op_info->dst_rect.h =
progress_bar.bar_height - progress_bar.bar_border * 2;
op_info->color = 0xffffff;
return 0;
}
EXPORT_SYMBOL(osd_init_progress_bar);

View File

@@ -0,0 +1,125 @@
/*
* drivers/amlogic/media/osd/osd_prot.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/slab.h>
/* Local Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "osd_hw.h"
#include "osd_io.h"
#include "osd_reg.h"
#include "osd_prot.h"
int osd_set_prot(unsigned char x_rev,
unsigned char y_rev,
unsigned char bytes_per_pixel,
unsigned char conv_422to444,
unsigned char little_endian,
unsigned int hold_lines,
unsigned int x_start,
unsigned int x_end,
unsigned int y_start,
unsigned int y_end,
unsigned int y_len_m1,
unsigned char y_step,
unsigned char pat_start_ptr,
unsigned char pat_end_ptr,
unsigned long pat_val,
unsigned int canv_addr,
unsigned int cid_val,
unsigned char cid_mode,
unsigned char cugt,
unsigned char req_onoff_en,
unsigned int req_on_max,
unsigned int req_off_min,
unsigned char osd_index,
unsigned char on)
{
unsigned long data32;
if (!on) {
/* no one use prot1. */
VSYNCOSD_CLR_MPEG_REG_MASK(VPU_PROT1_MMC_CTRL, 0xf << 12);
VSYNCOSD_CLR_MPEG_REG_MASK(VPU_PROT1_CLK_GATE, 1 << 0);
if (osd_index == OSD1) {
/* switch back to little endian */
VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0,
1, 15, 1);
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_PROT_CTRL, 0);
} else if (osd_index == OSD2) {
/* switch back to little endian */
VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0,
1, 15, 1);
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_PROT_CTRL, 0);
}
return 0;
}
if (osd_index == OSD1) {
/* bit[12..15] OSD1 OSD2 OSD3 OSD4 */
VSYNCOSD_WR_MPEG_REG_BITS(VPU_PROT1_MMC_CTRL, 1, 12, 4);
VSYNCOSD_WR_MPEG_REG(VIU_OSD1_PROT_CTRL, 1 << 15 | y_len_m1);
/* before rotate set big endian */
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD1_BLK0_CFG_W0, 1 << 15);
} else if (osd_index == OSD2) {
VSYNCOSD_WR_MPEG_REG_BITS(VPU_PROT1_MMC_CTRL, 2, 12, 4);
/* bit[12..15] OSD1 OSD2 OSD3 OSD4 */
VSYNCOSD_WR_MPEG_REG(VIU_OSD2_PROT_CTRL, 1 << 15 | y_len_m1);
/* before rotate set big endian */
VSYNCOSD_CLR_MPEG_REG_MASK(VIU_OSD2_BLK0_CFG_W0, 1 << 15);
}
data32 = (x_end << 16) |
(x_start << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_X_START_END, data32);
data32 = (y_end << 16) |
(y_start << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_START_END, data32);
data32 = (y_step << 16) |
(y_len_m1 << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_Y_LEN_STEP, data32);
data32 = (pat_start_ptr << 4) |
(pat_end_ptr << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_RPT_LOOP, data32);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_RPT_PAT, pat_val);
data32 = (cugt << 20) |
(cid_mode << 16) |
(cid_val << 8) |
(canv_addr << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_DDR, data32);
data32 = (hold_lines << 8) |
(little_endian << 7) |
(conv_422to444 << 6) |
(bytes_per_pixel << 4) |
(y_rev << 3) |
(x_rev << 2) |
(1 <<
0);
/* [1:0] req_en: 0=Idle; 1=Rotate mode; 2=FIFO mode. */
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_GEN_CNTL, data32);
data32 = (req_onoff_en << 31) |
(req_off_min << 16) |
(req_on_max << 0);
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_REQ_ONOFF, data32);
/* Enable clock */
VSYNCOSD_WR_MPEG_REG(VPU_PROT1_CLK_GATE, 1);
return 0;
}

View File

@@ -0,0 +1,59 @@
/*
* drivers/amlogic/media/osd/osd_prot.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_PROT_H_
#define _OSD_PROT_H_
#include "osd_hw.h"
#define CUGT 0
#define CID_VALUE 161
#define CID_MODE 6
#define REQ_ONOFF_EN 0
#define REQ_ON_MAX 0
#define REQ_OFF_MIN 0
#define PAT_VAL 0x00000000
#define PAT_START_PTR 1
#define PAT_END_PTR 1
#define HOLD_LINES 14
#define Y_STEP 0
extern int osd_set_prot(unsigned char x_rev,
unsigned char y_rev,
unsigned char bytes_per_pixel,
unsigned char conv_422to444,
unsigned char little_endian,
unsigned int hold_lines,
unsigned int x_start,
unsigned int x_end,
unsigned int y_start,
unsigned int y_end,
unsigned int y_len_m1,
unsigned char y_step,
unsigned char pat_start_ptr,
unsigned char pat_end_ptr,
unsigned long pat_val,
unsigned int canv_addr,
unsigned int cid_val,
unsigned char cid_mode,
unsigned char cugt,
unsigned char req_onoff_en,
unsigned int req_on_max,
unsigned int req_off_min,
unsigned char osd_index,
unsigned char on_off);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
/*
* drivers/amlogic/media/osd/osd_rdma.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_RDMA_H_
#define _OSD_RDMA_H_
#include <linux/types.h>
#include "osd_io.h"
#include "osd_reg.h"
struct rdma_table_item {
u32 addr;
u32 val;
};
#define TABLE_SIZE PAGE_SIZE
#define MAX_TABLE_ITEM (TABLE_SIZE/sizeof(struct rdma_table_item_t))
#define OSD_RDMA_CHANNEL_INDEX osd_rdma_handle
#define START_ADDR (RDMA_AHB_START_ADDR_MAN+(OSD_RDMA_CHANNEL_INDEX<<1))
#define END_ADDR (RDMA_AHB_END_ADDR_MAN+(OSD_RDMA_CHANNEL_INDEX<<1))
#define OSD_RDMA_FLAG_REG VIU_OSD2_TCOLOR_AG3
#define OSD_RDMA_FLAG_REJECT (0x99 << 0)
/* hw rdma own this flag, change it to zero when start rdma,
* change it to 0 when complete
*/
#define OSD_RDMA_STATUS_IS_REJECT \
(osd_reg_read(OSD_RDMA_FLAG_REG) & OSD_RDMA_FLAG_REJECT)
/* hw rdma op, set REJECT */
#define OSD_RDMA_STATUS_MARK_TBL_RST \
((osd_reg_read(OSD_RDMA_FLAG_REG) \
& ~OSD_RDMA_FLAG_REJECT) | \
(OSD_RDMA_FLAG_REJECT))
#define OSD_RDMA_STATUS_MARK_TBL_DONE \
((osd_reg_read(OSD_RDMA_FLAG_REG) \
& ~OSD_RDMA_FLAG_REJECT)) \
/* cpu op, clear REJECT */
#define OSD_RDMA_STATUS_CLEAR_REJECT \
(osd_reg_write(OSD_RDMA_FLAG_REG, \
(osd_reg_read(OSD_RDMA_FLAG_REG) & \
~OSD_RDMA_FLAG_REJECT)))
extern void osd_update_scan_mode(void);
extern void osd_update_3d_mode(void);
extern void osd_update_vsync_hit(void);
extern void osd_hw_reset(void);
extern int read_rdma_table(void);
extern int osd_rdma_enable(u32 enable);
extern int osd_rdma_reset_and_flush(u32 reset_bit);
extern int rdma_reset_tigger_flag;
extern int rdma_mgr_irq_request;
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
extern void osd_rdma_interrupt_done_clear(void);
#endif
extern int osd_rdma_uninit(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
/*
* drivers/amlogic/media/osd/osd_sync.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_SYNC_H_
#define _OSD_SYNC_H_
struct fb_sync_request_s {
unsigned int xoffset;
unsigned int yoffset;
int in_fen_fd;
int out_fen_fd;
};
#endif

View File

@@ -0,0 +1,17 @@
#
# Frame buffer configuration
#
menu "Amlogic OSD_EXT Module"
config AMLOGIC_MEDIA_FB_EXT
bool "Amlogic OSD_EXT Support"
default n
depends on AMLOGIC_MEDIA_FB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
depends on AMLOGIC_MEDIA_CANVAS
depends on AMLOGIC_VOUT2
help
This is the frame buffer device driver.
endmenu

View File

@@ -0,0 +1,5 @@
obj-$(CONFIG_AMLOGIC_MEDIA_FB_EXT) += fb_ext.o
fb_ext-objs = osd_hw.o osd_fb.o osd_clone.o
ccflags-y += -Idrivers/staging/android/
ccflags-y += -Idrivers/amlogic/media/

View File

@@ -0,0 +1,193 @@
/*
* drivers/amlogic/media/osd_ext/osd_clone.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
/* Amlogic Headers */
#include <linux/amlogic/cpu_version.h>
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
#include <linux/amlogic/media/canvas/canvas.h>
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#include <linux/amlogic/media/ge2d/ge2d.h>
#endif
/* Local Headers */
#include <osd/osd_io.h>
#include <osd/osd_log.h>
#include <osd/osd_canvas.h>
#include "osd_clone.h"
#ifdef OSD_EXT_GE2D_CLONE_SUPPORT
struct osd_ext_clone_s {
bool inited;
int angle;
int pan;
struct config_para_ex_s ge2d_config;
struct ge2d_context_s *ge2d_context;
};
static DEFINE_MUTEX(osd_ext_clone_mutex);
static struct osd_ext_clone_s s_osd_ext_clone;
static void osd_clone_process(void)
{
struct canvas_s cs, cd;
u32 x0 = 0;
u32 y0 = 0;
u32 y1 = 0;
unsigned char x_rev = 0;
unsigned char y_rev = 0;
unsigned char xy_swap = 0;
struct config_para_ex_s *ge2d_config = &s_osd_ext_clone.ge2d_config;
struct ge2d_context_s *context = s_osd_ext_clone.ge2d_context;
canvas_read(OSD1_CANVAS_INDEX, &cs);
canvas_read(OSD3_CANVAS_INDEX, &cd);
if (s_osd_ext_clone.pan == 1) {
y0 = cs.height / 2;
y1 = cd.height / 2;
}
if (s_osd_ext_clone.angle == 1) {
xy_swap = 1;
x_rev = 1;
} else if (s_osd_ext_clone.angle == 2) {
x_rev = 1;
y_rev = 1;
} else if (s_osd_ext_clone.angle == 3) {
xy_swap = 1;
y_rev = 1;
}
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width / 4;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width / 4;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_para.canvas_index = OSD1_CANVAS_INDEX;
ge2d_config->src_para.mem_type = CANVAS_OSD0;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ARGB;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = cs.width / 4;
ge2d_config->src_para.height = cs.height;
ge2d_config->dst_para.canvas_index = OSD3_CANVAS_INDEX;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S32_ARGB;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = cd.width / 4;
ge2d_config->dst_para.height = cd.height;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.x_rev = x_rev;
ge2d_config->dst_para.y_rev = y_rev;
ge2d_config->dst_xy_swap = xy_swap;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
osd_log_err("++ osd clone ge2d config error.\n");
return;
}
stretchblt(context, x0, y0, cs.width / 4, cs.height / 2,
x0, y1, cd.width / 4, cd.height / 2);
}
void osd_ext_clone_update_pan(int pan)
{
if (!s_osd_ext_clone.inited)
return;
mutex_lock(&osd_ext_clone_mutex);
s_osd_ext_clone.pan = pan;
mutex_unlock(&osd_ext_clone_mutex);
osd_clone_process();
}
void osd_ext_clone_set_angle(int angle)
{
mutex_lock(&osd_ext_clone_mutex);
s_osd_ext_clone.angle = angle;
mutex_unlock(&osd_ext_clone_mutex);
}
int osd_ext_clone_task_start(void)
{
if (s_osd_ext_clone.inited) {
osd_log_info("osd_ext_clone_task already started.\n");
return 0;
}
osd_log_info("osd_ext_clone_task start.\n");
if (s_osd_ext_clone.ge2d_context == NULL)
s_osd_ext_clone.ge2d_context = create_ge2d_work_queue();
memset(&s_osd_ext_clone.ge2d_config,
0, sizeof(struct config_para_ex_s));
s_osd_ext_clone.inited = true;
return 0;
}
void osd_ext_clone_task_stop(void)
{
if (!s_osd_ext_clone.inited) {
osd_log_info("osd_ext_clone_task already stopped.\n");
return;
}
osd_log_info("osd_ext_clone_task stop.\n");
if (s_osd_ext_clone.ge2d_context) {
destroy_ge2d_work_queue(s_osd_ext_clone.ge2d_context);
s_osd_ext_clone.ge2d_context = NULL;
}
s_osd_ext_clone.inited = false;
}
#endif

View File

@@ -0,0 +1,46 @@
/*
* drivers/amlogic/media/osd_ext/osd_clone.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_CLONE_H_
#define _OSD_CLONE_H_
#include <osd/osd_log.h>
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#define OSD_EXT_GE2D_CLONE_SUPPORT 1
#endif
#ifdef OSD_EXT_GE2D_CLONE_SUPPORT
extern void osd_ext_clone_set_angle(int angle);
extern void osd_ext_clone_update_pan(int pan);
extern int osd_ext_clone_task_start(void);
extern void osd_ext_clone_task_stop(void);
#else
static inline void osd_ext_clone_set_angle(int angle) {}
static inline void osd_ext_clone_update_pan(int pan) {}
static inline int osd_ext_clone_task_start(void)
{
osd_log_info("++ osd_ext_clone depends on GE2D module!\n");
return 0;
}
static inline void osd_ext_clone_task_stop(void)
{
osd_log_info("-- osd_ext_clone depends on GE2D module!\n");
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,274 @@
/*
* drivers/amlogic/media/osd_ext/osd_fb.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_FB_H_
#define _OSD_FB_H_
/* Linux Headers */
#include <linux/list.h>
#include <linux/fb.h>
/* Amlogic Headers */
#include <linux/amlogic/display/vinfo.h>
/* Local Headers */
#include <osd/osd.h>
#define OSD_COUNT 2 /* enable two OSD layers */
#define INVALID_BPP_ITEM {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
static const struct color_bit_define_s default_color_format_array[] = {
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
{
COLOR_INDEX_02_PAL4, 0, 0,
0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0,
FB_VISUAL_PSEUDOCOLOR, 2,
},
INVALID_BPP_ITEM,
{
COLOR_INDEX_04_PAL16, 0, 1,
0, 4, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0,
FB_VISUAL_PSEUDOCOLOR, 4,
},
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
{
COLOR_INDEX_08_PAL256, 0, 2,
0, 8, 0, 0, 8, 0, 0, 8, 0, 0, 0, 0,
FB_VISUAL_PSEUDOCOLOR, 8,
},
/*16 bit color*/
{
COLOR_INDEX_16_655, 0, 4,
10, 6, 0, 5, 5, 0, 0, 5, 0, 0, 0, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_844, 1, 4,
8, 8, 0, 4, 4, 0, 0, 4, 0, 0, 0, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_6442, 2, 4,
10, 6, 0, 6, 4, 0, 2, 4, 0, 0, 2, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_4444_R, 3, 4,
12, 4, 0, 8, 4, 0, 4, 4, 0, 0, 4, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_4642_R, 7, 4,
12, 4, 0, 6, 6, 0, 2, 4, 0, 0, 2, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_1555_A, 6, 4,
10, 5, 0, 5, 5, 0, 0, 5, 0, 15, 1, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_4444_A, 5, 4,
8, 4, 0, 4, 4, 0, 0, 4, 0, 12, 4, 0,
FB_VISUAL_TRUECOLOR, 16
},
{
COLOR_INDEX_16_565, 4, 4,
11, 5, 0, 5, 6, 0, 0, 5, 0, 0, 0, 0,
FB_VISUAL_TRUECOLOR, 16
},
/*24 bit color*/
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
{
COLOR_INDEX_24_6666_A, 4, 7,
12, 6, 0, 6, 6, 0, 0, 6, 0, 18, 6, 0,
FB_VISUAL_TRUECOLOR, 24
},
{
COLOR_INDEX_24_6666_R, 3, 7,
18, 6, 0, 12, 6, 0, 6, 6, 0, 0, 6, 0,
FB_VISUAL_TRUECOLOR, 24
},
{
COLOR_INDEX_24_8565, 2, 7,
11, 5, 0, 5, 6, 0, 0, 5, 0, 16, 8, 0,
FB_VISUAL_TRUECOLOR, 24
},
{
COLOR_INDEX_24_5658, 1, 7,
19, 5, 0, 13, 6, 0, 8, 5, 0, 0, 8, 0,
FB_VISUAL_TRUECOLOR, 24
},
{
COLOR_INDEX_24_888_B, 5, 7,
0, 8, 0, 8, 8, 0, 16, 8, 0, 0, 0, 0,
FB_VISUAL_TRUECOLOR, 24
},
{
COLOR_INDEX_24_RGB, 0, 7,
16, 8, 0, 8, 8, 0, 0, 8, 0, 0, 0, 0,
FB_VISUAL_TRUECOLOR, 24
},
/*32 bit color*/
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
INVALID_BPP_ITEM,
{
COLOR_INDEX_32_BGRA, 3, 5,
8, 8, 0, 16, 8, 0, 24, 8, 0, 0, 8, 0,
FB_VISUAL_TRUECOLOR, 32
},
{
COLOR_INDEX_32_ABGR, 2, 5,
0, 8, 0, 8, 8, 0, 16, 8, 0, 24, 8, 0,
FB_VISUAL_TRUECOLOR, 32
},
{
COLOR_INDEX_32_RGBA, 0, 5,
24, 8, 0, 16, 8, 0, 8, 8, 0, 0, 8, 0,
FB_VISUAL_TRUECOLOR, 32
},
{
COLOR_INDEX_32_ARGB, 1, 5,
16, 8, 0, 8, 8, 0, 0, 8, 0, 24, 8, 0,
FB_VISUAL_TRUECOLOR, 32
},
/*YUV color*/
{COLOR_INDEX_YUV_422, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16},
};
static __u32 var_screeninfo[5];
static struct fb_var_screeninfo fb_def_var[] = {
{
.xres = 768,
.yres = 1024,
.xres_virtual = 768,
.yres_virtual = 2048,
.xoffset = 0,
.yoffset = 0,
.bits_per_pixel = 32,
.grayscale = 0,
.red = {0, 0, 0},
.green = {0, 0, 0},
.blue = {0, 0, 0},
.transp = {0, 0, 0},
.nonstd = 0,
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.accel_flags = 0,
.pixclock = 0,
.left_margin = 0,
.right_margin = 0,
.upper_margin = 0,
.lower_margin = 0,
.hsync_len = 0,
.vsync_len = 0,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
.rotate = 0,
}
#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD2_ENABLE
,
{
#if defined(CONFIG_FB_OSD2_DEFAULT_WIDTH)
.xres = CONFIG_FB_OSD2_DEFAULT_WIDTH,
#else
.xres = 32,
#endif
#if defined(CONFIG_FB_OSD2_DEFAULT_HEIGHT)
.yres = CONFIG_FB_OSD2_DEFAULT_HEIGHT,
#else
.yres = 32,
#endif
#if defined(CONFIG_FB_OSD2_DEFAULT_WIDTH_VIRTUAL)
.xres_virtual = CONFIG_FB_OSD2_DEFAULT_WIDTH_VIRTUAL,
#else
.xres_virtual = 32,
#endif
#if defined(CONFIG_FB_OSD2_DEFAULT_HEIGHT_VIRTUAL)
.yres_virtual = CONFIG_FB_OSD2_DEFAULT_HEIGHT_VIRTUAL,
#else
.yres_virtual = 32,
#endif
.xoffset = 0,
.yoffset = 0,
#if defined(CONFIG_FB_OSD2_DEFAULT_BITS_PER_PIXEL)
.bits_per_pixel = CONFIG_FB_OSD2_DEFAULT_BITS_PER_PIXEL,
#else
.bits_per_pixel = 32,
#endif
.grayscale = 0,
.red = {0, 0, 0},
.green = {0, 0, 0},
.blue = {0, 0, 0},
.transp = {0, 0, 0},
.nonstd = 0,
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.accel_flags = 0,
.pixclock = 0,
.left_margin = 0,
.right_margin = 0,
.upper_margin = 0,
.lower_margin = 0,
.hsync_len = 0,
.vsync_len = 0,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
.rotate = 0,
}
#endif
};
static struct fb_fix_screeninfo fb_def_fix = {
.id = "OSD FB EXT",
.xpanstep = 1,
.ypanstep = 1,
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.accel = FB_ACCEL_NONE,
};
struct osd_fb_dev_s {
struct mutex lock;
struct fb_info *fb_info;
struct platform_device *dev;
u32 fb_mem_paddr;
void __iomem *fb_mem_vaddr;
u32 fb_len;
const struct color_bit_define_s *color;
enum vmode_e vmode;
struct osd_ctl_s osd_ctl;
u32 order;
u32 scale;
u32 enable_3d;
u32 preblend_enable;
u32 enable_key_flag;
u32 color_key;
};
#endif /* _OSD_FB_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
/*
* drivers/amlogic/media/osd_ext/osd_hw.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_HW_H_
#define _OSD_HW_H_
#include <osd/osd.h>
#define REG_OFFSET 0x20
#define OSD_RELATIVE_BITS 0x333f0
extern void osd_ext_set_color_key_hw(u32 index, u32 bpp, u32 colorkey);
extern void osd_ext_srckey_enable_hw(u32 index, u8 enable);
extern void osd_ext_set_gbl_alpha_hw(u32 index, u32 gbl_alpha);
extern u32 osd_ext_get_gbl_alpha_hw(u32 index);
extern void osd_ext_setup(struct osd_ctl_s *osd_ext_ctl,
u32 xoffset,
u32 yoffset,
u32 xres,
u32 yres,
u32 xres_virtual,
u32 yres_virtual,
u32 disp_start_x,
u32 disp_start_y,
u32 disp_end_x,
u32 disp_end_y,
u32 fbmem,
const struct color_bit_define_s *color,
int index);
extern void osd_ext_update_disp_axis_hw(
u32 index,
u32 display_h_start,
u32 display_h_end,
u32 display_v_start,
u32 display_v_end,
u32 xoffset,
u32 yoffset,
u32 mode_change);
extern void osd_ext_set_order_hw(u32 index, u32 order);
extern u32 osd_ext_get_order_hw(u32 index);
extern void osd_ext_set_free_scale_enable_hw(u32 index, u32 enable);
extern void osd_ext_get_free_scale_enable_hw(u32 index,
u32 *free_scale_enable);
extern void osd_ext_get_free_scale_width_hw(u32 index, u32 *free_scale_width);
extern void osd_ext_get_free_scale_height_hw(u32 index,
u32 *free_scale_height);
extern void osd_ext_get_free_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_ext_set_free_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1,
s32 y1);
extern void osd_ext_get_scale_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_ext_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1,
s32 y1);
extern void osd_ext_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1,
s32 *y1);
extern void osd_ext_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1,
s32 y1);
extern void osd_ext_get_free_scale_mode_hw(u32 index, u32 *freescale_mode);
extern void osd_ext_set_free_scale_mode_hw(u32 index, u32 freescale_mode);
extern void osd_ext_set_debug_hw(u32 index, u32 flag);
extern void osd_ext_get_block_windows_hw(u32 index, u32 *windows);
extern void osd_ext_set_block_windows_hw(u32 index, u32 *windows);
extern void osd_ext_get_block_mode_hw(u32 index, u32 *mode);
extern void osd_ext_set_block_mode_hw(u32 index, u32 mode);
extern void osd_ext_enable_3d_mode_hw(int index, int enable);
extern void osd_ext_set_2x_scale_hw(u32 index, u16 h_scale_enable,
u16 v_scale_enable);
extern void osd_ext_setpal_hw(u32 index, unsigned int regno,
unsigned int red, unsigned int green,
unsigned int blue, unsigned int transp);
extern void osd_ext_enable_hw(u32 index, int enable);
extern void osd_ext_pan_display_hw(u32 index, unsigned int xoffset,
unsigned int yoffset);
extern int osd_ext_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
s32 in_fence_fd);
extern s32 osd_ext_wait_vsync_event(void);
extern void osd_ext_suspend_hw(void);
extern void osd_ext_resume_hw(void);
extern void osd_ext_init_hw(u32 logo_loaded);
extern void osd_ext_get_angle_hw(u32 index, u32 *angle);
extern void osd_ext_set_angle_hw(u32 index, u32 angle);
extern void osd_ext_get_clone_hw(u32 index, u32 *clone);
extern void osd_ext_set_clone_hw(u32 index, u32 clone);
#endif

View File

@@ -0,0 +1,108 @@
/*
* drivers/amlogic/media/osd_ext/osd_hw_def.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_HW_DEF_H_
#define _OSD_HW_DEF_H_
#include <linux/list.h>
#include "osd_hw.h"
static void osd1_update_color_mode(void);
static void osd1_update_enable(void);
static void osd1_update_color_key(void);
static void osd1_update_color_key_enable(void);
static void osd1_update_gbl_alpha(void);
static void osd1_update_order(void);
static void osd1_update_coef(void);
static void osd1_update_disp_geometry(void);
static void osd1_update_disp_freescale_enable(void);
static void osd1_update_disp_osd_rotate(void);
static void osd1_update_disp_scale_enable(void);
static void osd1_update_disp_3d_mode(void);
static void osd2_update_color_mode(void);
static void osd2_update_enable(void);
static void osd2_update_color_key(void);
static void osd2_update_color_key_enable(void);
static void osd2_update_gbl_alpha(void);
static void osd2_update_order(void);
static void osd2_update_coef(void);
static void osd2_update_disp_geometry(void);
static void osd2_update_disp_freescale_enable(void);
static void osd2_update_disp_osd_rotate(void);
static void osd2_update_disp_scale_enable(void);
static void osd2_update_disp_3d_mode(void);
static DEFINE_SPINLOCK(osd_ext_lock);
static struct hw_para_s osd_ext_hw;
static unsigned long lock_flags;
#ifdef FIQ_VSYNC
static unsigned long fiq_flag;
#endif
static update_func_t hw_func_array[HW_OSD_COUNT][HW_REG_INDEX_MAX] = {
{
osd1_update_color_mode,
osd1_update_enable,
osd1_update_color_key,
osd1_update_color_key_enable,
osd1_update_gbl_alpha,
osd1_update_order,
osd1_update_coef,
osd1_update_disp_geometry,
osd1_update_disp_scale_enable,
osd1_update_disp_freescale_enable,
NULL,
osd1_update_disp_osd_rotate,
},
{
osd2_update_color_mode,
osd2_update_enable,
osd2_update_color_key,
osd2_update_color_key_enable,
osd2_update_gbl_alpha,
osd2_update_order,
osd2_update_coef,
osd2_update_disp_geometry,
osd2_update_disp_scale_enable,
osd2_update_disp_freescale_enable,
NULL,
osd2_update_disp_osd_rotate,
},
};
#ifdef FIQ_VSYNC
#define add_to_update_list(osd_ext_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_ext_lock, lock_flags); \
raw_local_save_flags(fiq_flag); \
local_fiq_disable(); \
osd_ext_hw.updated[osd_ext_idx] |= (1<<cmd_idx); \
raw_local_irq_restore(fiq_flag); \
spin_unlock_irqrestore(&osd_ext_lock, lock_flags); \
} while (0)
#else
#define add_to_update_list(osd_ext_idx, cmd_idx) \
do { \
spin_lock_irqsave(&osd_ext_lock, lock_flags); \
osd_ext_hw.updated[osd_ext_idx] |= (1<<cmd_idx); \
spin_unlock_irqrestore(&osd_ext_lock, lock_flags); \
} while (0)
#endif
#define remove_from_update_list(osd_ext_idx, cmd_idx) \
(osd_ext_hw.updated[osd_ext_idx] &= ~(1<<cmd_idx))
#endif

View File

@@ -0,0 +1,132 @@
/*
* drivers/amlogic/media/osd_ext/osd_prot.c
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/slab.h>
/* Amlogic Headers */
#include <linux/amlogic/vout/vout_notify.h>
/* Local Headers */
#include <osd/osd_io.h>
#include <osd/osd_reg.h>
#include "osd_hw.h"
#include "osd_prot.h"
int osd_ext_set_prot(unsigned char x_rev,
unsigned char y_rev,
unsigned char bytes_per_pixel,
unsigned char conv_422to444,
unsigned char little_endian,
unsigned int hold_lines,
unsigned int x_start,
unsigned int x_end,
unsigned int y_start,
unsigned int y_end,
unsigned int y_len_m1,
unsigned char y_step,
unsigned char pat_start_ptr,
unsigned char pat_end_ptr,
unsigned long pat_val,
unsigned int canv_addr,
unsigned int cid_val,
unsigned char cid_mode,
unsigned char cugt,
unsigned char req_onoff_en,
unsigned int req_on_max,
unsigned int req_off_min,
unsigned char osd_index,
unsigned char on)
{
unsigned long data32;
if (!on) {
/* no one use prot1. */
osd_reg_clr_mask(VPU_PROT1_MMC_CTRL, 0xf << 12);
osd_reg_clr_mask(VPU_PROT1_CLK_GATE, 1 << 0);
if (osd_index == OSD1) {
/* switch back to little endian */
osd_reg_set_bits(VIU2_OSD1_BLK0_CFG_W0, 1, 15, 1);
osd_reg_write(VIU2_OSD1_PROT_CTRL, 0);
} else if (osd_index == OSD2) {
/* switch back to little endian */
osd_reg_set_bits(VIU2_OSD2_BLK0_CFG_W0, 1, 15, 1);
osd_reg_write(VIU2_OSD2_PROT_CTRL, 0);
}
return 0;
}
if (osd_index == OSD1) {
/* bit[12..15] OSD1 OSD2 OSD3 OSD4 */
osd_reg_set_bits(VPU_PROT1_MMC_CTRL, 4, 12, 4);
osd_reg_write(VIU2_OSD1_PROT_CTRL, 1 << 15 | y_len_m1);
/* before rotate set big endian */
osd_reg_clr_mask(VIU2_OSD1_BLK0_CFG_W0, 1 << 15);
} else if (osd_index == OSD2) {
/* bit[12..15] OSD1 OSD2 OSD3 OSD4 */
osd_reg_set_bits(VPU_PROT1_MMC_CTRL, 8, 12, 4);
osd_reg_write(VIU2_OSD2_PROT_CTRL, 1 << 15 | y_len_m1);
/* before rotate set big endian */
osd_reg_clr_mask(VIU2_OSD2_BLK0_CFG_W0, 1 << 15);
}
data32 = (x_end << 16) |
(x_start << 0);
osd_reg_write(VPU_PROT1_X_START_END, data32);
data32 = (y_end << 16) |
(y_start << 0);
osd_reg_write(VPU_PROT1_Y_START_END, data32);
data32 = (y_step << 16) |
(y_len_m1 << 0);
osd_reg_write(VPU_PROT1_Y_LEN_STEP, data32);
data32 = (pat_start_ptr << 4) |
(pat_end_ptr << 0);
osd_reg_write(VPU_PROT1_RPT_LOOP, data32);
osd_reg_write(VPU_PROT1_RPT_PAT, pat_val);
data32 = (cugt << 20) |
(cid_mode << 16) |
(cid_val << 8) |
(canv_addr << 0);
osd_reg_write(VPU_PROT1_DDR, data32);
data32 = (hold_lines << 8) |
(little_endian << 7) |
(conv_422to444 << 6) |
(bytes_per_pixel << 4) |
(y_rev << 3) |
(x_rev << 2) |
(1 << 0);
/* [1:0] req_en: 0=Idle; 1=Rotate mode; 2=FIFO mode. */
osd_reg_write(VPU_PROT1_GEN_CNTL, data32);
data32 = (req_onoff_en << 31) |
(req_off_min << 16) |
(req_on_max << 0);
osd_reg_write(VPU_PROT1_REQ_ONOFF, data32);
osd_reg_write(VPU_PROT1_CLK_GATE, 1); /* Enable clock */
return 0;
}

View File

@@ -0,0 +1,57 @@
/*
* drivers/amlogic/media/osd_ext/osd_prot.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _OSD_PROT_H_
#define _OSD_PROT_H_
#define CUGT 0
#define CID_VALUE 161
#define CID_MODE 6
#define REQ_ONOFF_EN 0
#define REQ_ON_MAX 0
#define REQ_OFF_MIN 0
#define PAT_VAL 0x00000000
#define PAT_START_PTR 1
#define PAT_END_PTR 1
#define HOLD_LINES 28
#define Y_STEP 0
extern int osd_ext_set_prot(unsigned char x_rev,
unsigned char y_rev,
unsigned char bytes_per_pixel,
unsigned char conv_422to444,
unsigned char little_endian,
unsigned int hold_lines,
unsigned int x_start,
unsigned int x_end,
unsigned int y_start,
unsigned int y_end,
unsigned int y_len_m1,
unsigned char y_step,
unsigned char pat_start_ptr,
unsigned char pat_end_ptr,
unsigned long pat_val,
unsigned int canv_addr,
unsigned int cid_val,
unsigned char cid_mode,
unsigned char cugt,
unsigned char req_onoff_en,
unsigned int req_on_max,
unsigned int req_off_min,
unsigned char osd_index,
unsigned char on_off);
#endif

View File

@@ -58,7 +58,9 @@ u32 get_video_enabled(void);
int ext_frame_capture_poll(int endflags);
#endif
/*extern u32 disp_canvas_index[2][6];*/
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
extern u32 disp_canvas_index[2][6];
#endif
#endif
/*VIDEO_PRIV_HEADER_HH*/

View File

@@ -1,66 +0,0 @@
/*
* include/linux/amlogic/display/vinfo.h
*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _VINFO_H_
#define _VINFO_H_
#include <linux/amlogic/color_fmt.h>
/* the MSB is represent vmode set by vmode_init */
#define VMODE_INIT_BIT_MASK 0x8000
#define VMODE_MODE_BIT_MASK 0xff
enum vmode_e {
VMODE_HDMI,
VMODE_CVBS,
VMODE_LCD,
VMODE_NULL, /* null mode is used as temporary witch mode state */
VMODE_MAX,
VMODE_INIT_NULL,
VMODE_MASK = 0xFF,
};
#define SUPPORT_2020 0x01
/* master_display_info for display device */
struct master_display_info_s {
u32 present_flag;
u32 features; /* feature bits bt2020/2084 */
u32 primaries[3][2]; /* normalized 50000 in G,B,R order */
u32 white_point[2]; /* normalized 50000 */
u32 luminance[2]; /* max/min lumin, normalized 10000 */
};
struct vinfo_s {
char *name;
enum vmode_e mode;
char ext_name[32];
u32 width;
u32 height;
u32 field_height;
u32 aspect_ratio_num;
u32 aspect_ratio_den;
u32 screen_real_width;
u32 screen_real_height;
u32 sync_duration_num;
u32 sync_duration_den;
u32 video_clk;
enum color_fmt_e viu_color_fmt;
struct master_display_info_s master_display_info;
void *vout_device;
};
#endif /* _VINFO_H_ */

View File

@@ -123,6 +123,7 @@
#define MATRIX_YCC_TO_RGB 1
#define MATRIX_RGB_TO_YCC 2
#define MATRIX_FULL_RANGE_YCC_TO_RGB 3
#define MATRIX_RGB_TO_FULL_RANGE_YCC 4
#define GE2D_ENDIAN_SHIFT 24
@@ -815,6 +816,13 @@ struct compat_config_para_ex_s {
_IOW(GE2D_IOC_MAGIC, 0x01, struct compat_config_para_ex_s)
#endif
#define GE2D_SRCCOLORKEY _IOW(GE2D_IOC_MAGIC, 0x02, struct config_para_s)
#ifdef CONFIG_COMPAT
#define GE2D_SRCCOLORKEY32 \
_IOW(GE2D_IOC_MAGIC, 0x02, struct compat_config_para_s)
#endif
extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg);
extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg);
extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg);

View File

@@ -18,6 +18,8 @@
#ifndef _GE2D_CMD_H_
#define _GE2D_CMD_H_
#define GE2D_BLEND_NOALPHA_NOBLOCK 0x470a
#define GE2D_BLEND_NOALPHA 0x4709
#define GE2D_STRETCHBLIT_NOALPHA_NOBLOCK 0x4708
#define GE2D_BLIT_NOALPHA_NOBLOCK 0x4707
#define GE2D_BLEND_NOBLOCK 0x4706
@@ -32,10 +34,10 @@
#define GE2D_BLIT 0x46ff
#define GE2D_STRETCHBLIT 0x46fe
#define GE2D_FILLRECTANGLE 0x46fd
#define GE2D_SRCCOLORKEY 0x46fc
#define GE2D_SRCCOLORKEY_OLD 0x46fc
#define GE2D_SET_COEF 0x46fb
/* #define GE2D_CONFIG_EX 0x46fa */
/* #define GE2D_CONFIG 0x46f9 */
#define GE2D_CONFIG_EX_OLD 0x46fa
#define GE2D_CONFIG_OLD 0x46f9
#define GE2D_ANTIFLICKER_ENABLE 0x46f8
#endif

View File

@@ -110,4 +110,15 @@ void blend_noblk(struct ge2d_context_s *wq,
int dst_x, int dst_y, int dst_w, int dst_h,
int op);
void blend_noalpha(struct ge2d_context_s *wq,
int src_x, int src_y, int src_w, int src_h,
int src2_x, int src2_y, int src2_w, int src2_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int op);
void blend_noalpha_noblk(struct ge2d_context_s *wq,
int src_x, int src_y, int src_w, int src_h,
int src2_x, int src2_y, int src2_w, int src2_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int op);
#endif

View File

@@ -23,9 +23,11 @@ struct rdma_op_s {
void *arg;
};
#define RDMA_TRIGGER_VSYNC_INPUT 0x1
#define RDMA_TRIGGER_MANUAL 0x100
#define RDMA_TRIGGER_DEBUG1 0x101
#define RDMA_TRIGGER_DEBUG2 0x102
#define RDMA_AUTO_START_MASK 0x80000
/*
* rdma_read_reg(), rdma_write_reg(), rdma_clear() can only be called

View File

@@ -17,7 +17,7 @@
#ifndef VIDEO_HEADER_
#define VIDEO_HEADER_
#ifdef CONFIG_VSYNC_RDMA
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
int VSYNC_WR_MPEG_REG(u32 adr, u32 val);
int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len);

View File

@@ -13,7 +13,7 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
*/
#ifndef _VOUT_NOTIFY_H_
#define _VOUT_NOTIFY_H_