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"
source "drivers/amlogic/media/deinterlace/Kconfig"
source "drivers/amlogic/media/vin/Kconfig"
source "drivers/amlogic/media/video_processor/Kconfig"
obj-$(CONFIG_AMLOGIC_VOUT) += vout/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += osd/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += osd_ext/
-obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += logo/
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += deinterlace/
obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/
obj-$(CONFIG_AMLOGIC_MEDIA_DRIVERS) += video_processor/
\ No newline at end of file
+++ /dev/null
-#
-# 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
+++ /dev/null
-obj-$(CONFIG_AMLOGIC_MEDIA_LOGO) += logo.o
-
-ccflags-y += -Idrivers/amlogic/display/
-ccflags-y += -Idrivers/amlogic/media/
\ No newline at end of file
It need enable canvas.
It need enable vout.
-config AMLOGIC_MEDIAFB_OSD_SYNC_FENCE
+config AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
bool "OSD SYNC FENCE"
default n
depends on AMLOGIC_MEDIA_FB
obj-$(CONFIG_AMLOGIC_MEDIA_FB) += fb.o
-fb-objs = osd_hw.o osd_fb.o osd_debug.o osd_backup.o
+fb-objs = osd_hw.o osd_fb.o osd_debug.o osd_backup.o osd_logo.o
fb-objs += osd_antiflicker.o osd_clone.o
obj-$(CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA) += osd_rdma.o
static int early_resume_flag;
#endif
+static struct delayed_work osd_dwork;
+static bool fb_map_flag;
static int osd_shutdown_flag;
unsigned int osd_log_level;
fb_index = fbdev->fb_index;
fix = &info->fix;
var = &info->var;
- if (fb_rmem.base == 0) {
+ /* read fb-reserved memory first */
+ if (fb_rmem.base &&
+ (fb_memsize[0] + fb_memsize[1]) <= fb_rmem.size) {
+ if (!fb_ion_client)
+ fb_ion_client = meson_ion_client_create(-1, "meson-fb");
+ fb_rmem_size[fb_index] = fb_memsize[fb_index];
+ if (fb_index == DEV_OSD0)
+ fb_rmem_paddr[fb_index] = fb_rmem.base;
+ else if (fb_index == DEV_OSD1) {
+ if ((OSD_COUNT == 2) &&
+ ((fb_memsize[0] + fb_memsize[1]) <= fb_rmem.size)) {
+ fb_rmem_paddr[fb_index] =
+ fb_rmem.base + fb_memsize[0];
+ }
+ }
+ if ((fb_rmem_paddr[fb_index] > 0) &&
+ (fb_rmem_size[fb_index] > 0)) {
+ if (fb_map_flag)
+ fb_rmem_vaddr[fb_index] =
+ phys_to_virt(fb_rmem_paddr[fb_index]);
+ else
+ fb_rmem_vaddr[fb_index] =
+ ioremap_wc(fb_rmem_paddr[fb_index],
+ fb_rmem_size[fb_index]);
+ if (!fb_rmem_vaddr[fb_index])
+ osd_log_err("fb[%d] ioremap error",
+ fb_index);
+ }
+ } else {
#ifdef CONFIG_AMLOGIC_ION
pr_info("use ion buffer for fb memory\n");
if (!fb_ion_client)
(unsigned long)fb_rmem_size[fb_index] / SZ_1M);
}
#endif
- } else {
- fb_rmem_size[fb_index] = fb_memsize[fb_index];
- if (fb_index == DEV_OSD0)
- fb_rmem_paddr[fb_index] = fb_rmem.base;
- else if (fb_index == DEV_OSD1) {
- if ((OSD_COUNT == 2) &&
- ((fb_memsize[0] + fb_memsize[1]) <= fb_rmem.size)) {
- fb_rmem_paddr[fb_index] =
- fb_rmem.base + fb_memsize[0];
- }
- }
- if ((fb_rmem_paddr[fb_index] > 0) &&
- (fb_rmem_size[fb_index] > 0)) {
- fb_rmem_vaddr[fb_index] =
- ioremap_wc(fb_rmem_paddr[fb_index],
- fb_rmem_size[fb_index]);
- if (!fb_rmem_vaddr[fb_index])
- osd_log_err("fb[%d] ioremap error",
- fb_index);
- }
}
fbdev->fb_len = fb_rmem_size[fb_index];
fbdev->fb_mem_paddr = fb_rmem_paddr[fb_index];
if ((logo_index < 0) || (logo_index != fb_index)) {
osd_log_info("---------------clear fb%d memory %p\n",
fb_index, fbdev->fb_mem_vaddr);
+ set_logo_loaded();
memset(fbdev->fb_mem_vaddr, 0x0, fbdev->fb_len);
if (fb_index == DEV_OSD0 && osd_get_afbc()) {
for (j = 1; j < OSD_MAX_BUF_NUM; j++) {
break;
#endif
case VOUT_EVENT_MODE_CHANGE:
+ set_osd_logo_freescaler();
for (i = 0; i < OSD_COUNT; i++) {
fb_dev = gp_fbdev_list[i];
if (fb_dev == NULL)
}
#endif
+static void mem_free_work(struct work_struct *work)
+{
+ long r = -EINVAL;
+ unsigned long start_addr;
+ unsigned long end_addr;
+
+ if (fb_rmem.base && fb_map_flag) {
+ if (fb_rmem.size >= (fb_memsize[0] + fb_memsize[1])) {
+ /* logo reserved memory after fb0/fb1 memory, free it*/
+ start_addr = fb_rmem.base
+ + fb_memsize[0] + fb_memsize[1];
+ end_addr = fb_rmem.base + fb_rmem.size;
+ } else {
+ /* logo reserved only, free it*/
+ start_addr = fb_rmem.base;
+ end_addr = fb_rmem.base + fb_rmem.size;
+ }
+ osd_log_info("%s, free memory: addr:%lx\n",
+ __func__, start_addr);
+ r = free_reserved_area(__va(start_addr),
+ __va(end_addr), 0, "fb-memory");
+ }
+}
+
static int osd_probe(struct platform_device *pdev)
{
struct fb_info *fbi = NULL;
struct fb_fix_screeninfo *fix;
int index, bpp;
struct osd_fb_dev_s *fbdev = NULL;
- enum vmode_e current_mode = VMODE_MASK;
- enum vmode_e logo_init = 0;
const void *prop;
int prop_idx = 0;
const char *str;
goto failed1;
}
#endif
+ /* init osd logo */
+ ret = logo_work_init();
+ if (ret == 0)
+ osd_init_hw(1);
+ else
+ osd_init_hw(0);
+
/* get buffer size from dt */
ret = of_property_read_u32_array(pdev->dev.of_node,
"mem_size", fb_memsize, 2);
/* get default display mode from dt */
ret = of_property_read_string(pdev->dev.of_node,
"display_mode_default", &str);
- if (ret)
- current_mode = VMODE_MASK;
- #ifdef CONFIG_AMLOGIC_TV_OUTPUT
- else
- current_mode = vmode_name_to_mode(str);
- #endif
prop = of_get_property(pdev->dev.of_node, "pxp_mode", NULL);
if (prop)
prop_idx = of_read_ulong(prop, 1);
osd_set_urgent(1, (prop_idx != 0) ? 1 : 0);
}
- /* if osd_init_hw is not set by logo, set vmode and init osd hw */
- logo_init = osd_get_init_hw_flag();
- if (logo_init == 0) {
- if (current_mode < VMODE_MASK)
- set_current_vmode(current_mode);
- osd_init_hw(0);
- }
-
vinfo = get_current_vinfo();
- osd_log_info("%s vinfo:%p\n", __func__, vinfo);
for (index = 0; index < OSD_COUNT; index++) {
/* register frame buffer memory */
fbi = framebuffer_alloc(sizeof(struct osd_fb_dev_s),
/* register vout client */
vout_register_client(&osd_notifier_nb);
+ INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
+ schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
osd_log_info("osd probe OK\n");
return 0;
static int rmem_fb_device_init(struct reserved_mem *rmem, struct device *dev)
{
+ if (!of_get_flat_dt_prop(rmem->fdt_node, "no-map", NULL)) {
+ fb_map_flag = true;
+ osd_log_info("momery mapped[can free]\n");
+ } else
+ fb_map_flag = false;
return 0;
}
platform_driver_unregister(&osd_driver);
}
-module_init(osd_init_module);
+subsys_initcall(osd_init_module);
module_exit(osd_exit_module);
MODULE_AUTHOR("Platform-BJ <platform.bj@amlogic.com>");
module_param(osd_auto_adjust_filter, uint, 0664);
MODULE_PARM_DESC(osd_auto_adjust_filter, "osd_auto_adjust_filter");
-static int osd_init_hw_flag;
static int osd_logo_index = 1;
module_param(osd_logo_index, int, 0664);
MODULE_PARM_DESC(osd_logo_index, "osd_logo_index");
osd_hw.free_src_data[OSD2].x_end = 0;
osd_hw.free_src_data[OSD2].y_start = 0;
osd_hw.free_src_data[OSD2].y_end = 0;
- osd_hw.free_scale_mode[OSD1] = 1;
+ osd_hw.free_scale_mode[OSD1] = 0;
osd_hw.free_scale_mode[OSD2] = 1;
if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM)
osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0x002020ff);
osd_rdma_enable(1);
#endif
- osd_init_hw_flag = 1;
}
#if defined(CONFIG_AMLOGIC_MEDIA_FB_OSD2_CURSOR)
osd_logo_index = index;
}
-int osd_get_init_hw_flag(void)
-{
- return osd_init_hw_flag;
-}
-
void osd_get_hw_para(struct hw_para_s **para)
{
*para = &osd_hw;
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);
+int logo_work_init(void);
+void set_logo_loaded(void);
+int set_osd_logo_freescaler(void);
#endif
/*
- * drivers/amlogic/media/logo/logo.c
+ * drivers/amlogic/media/osd/osd_logo.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* 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>
+#include <linux/delay.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+
/* Local Headers */
-#include <osd/osd_hw.h>
+#include "osd_hw.h"
+#include "osd_log.h"
#undef pr_fmt
#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 {
int value;
};
+
static struct para_pair_s logo_args[] = {
{"osd0", LOGO_DEV_OSD0},
{"osd1", LOGO_DEV_OSD1},
{"loaded", LOGO_LOADED},
};
+
struct logo_info_s {
int index;
u32 vmode;
.loaded = 0,
};
-
static int get_value_by_name(char *name, struct para_pair_s *pair, u32 cnt)
{
u32 i = 0;
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;
-}
-EXPORT_SYMBOL(get_logo_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]);
+ count = sizeof(logo_args) / sizeof(logo_args[0]);
value = get_value_by_name(para, logo_args, count);
if (value >= 0) {
switch (value) {
}
return 0;
}
-__setup("logo=", logo_setup);
-static int __init get_hdmi_mode(char *str)
+
+int set_osd_logo_freescaler(void)
{
- hdmimode = get_current_vmode();
- /* hdmimode = vmode_name_to_mode(str); */
+ const struct vinfo_s *vinfo;
+ u32 index = logo_info.index;
+
+ if (logo_info.loaded == 0)
+ return 0;
+ if (osd_get_logo_index() != logo_info.index) {
+ pr_info("logo changed, return!\n");
+ return -1;
+ }
+
+ osd_set_free_scale_mode_hw(index, 1);
+ osd_set_free_scale_enable_hw(index, 0);
- pr_info("get hdmimode: %s\n", str);
- return 1;
+ 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);
+ }
+ osd_set_free_scale_enable_hw(index, 0x10001);
+ osd_enable_hw(index, 1);
+ return 0;
}
-__setup("hdmimode=", get_hdmi_mode);
-static int __init get_cvbs_mode(char *str)
+
+void set_logo_loaded(void)
{
- if (strncmp("480", str, 3) == 0)
- cvbsmode = 0;//VMODE_480CVBS;//DEBUG_TMP
- else if (strncmp("576", str, 3) == 0)
- cvbsmode = 0;//VMODE_576CVBS;//DEBUG_TMP
- else if (strncmp("nocvbs", str, 6) == 0)
- cvbsmode = hdmimode;
- pr_info("get cvbsmode: %s\n", str);
- return 1;
+ logo_info.loaded = 0;
}
-__setup("cvbsmode=", get_cvbs_mode);
-static int __init logo_init(void)
-{
- int ret = 0;
+__setup("logo=", logo_setup);
- pr_info("%s\n", __func__);
+int logo_work_init(void)
+{
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;
+ return -1;
+ osd_set_logo_index(logo_info.index);
+ return 0;
}
-subsys_initcall(logo_init);
/*********************************************************/
static int __init video_early_init(void)
{
+ const struct vinfo_s *vinfo;
+
/* todo: move this to clock tree, enable VPU clock */
#if DEBUG_TMP
WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,
(3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M
//moved to vpu.c, default config by dts
#endif
+ vinfo = get_current_vinfo();
+ if (!vinfo)
+ return -1;
- if (get_logo_vmode() >= VMODE_MAX) {
+ if (vinfo->mode >= VMODE_MAX) {
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
if (is_meson_gxtvbb_cpu())
WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff,
if (is_meson_gxbb_cpu())
SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE);
- if (get_logo_vmode() >= VMODE_MAX) {
+ if (vinfo->mode >= VMODE_MAX) {
CLEAR_VCBUS_REG_MASK(VPP_VSC_PHASE_CTRL,
VPP_PHASECTL_TYPE_INTERLACE);
#ifndef CONFIG_FB_AML_TCON
WRITE_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off, 0x08080808);
}
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
- if (get_logo_vmode() >= VMODE_MAX) {
+ if (vinfo->mode >= VMODE_MAX) {
CLEAR_VCBUS_REG_MASK(VPP2_VSC_PHASE_CTRL,
VPP_PHASECTL_TYPE_INTERLACE);
#ifndef CONFIG_FB_AML_TCON