vout_serve: add vout, vout2 support for g12a

PD#156734: vout_serve: add vout, vout2 support for g12a

Change-Id: I1cb45beca5325f9013901687d7d995bfb9a25766
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2018-01-02 11:27:09 +08:00
committed by Yixun Lan
parent 231a12fb9c
commit dbf24e0936
24 changed files with 2147 additions and 467 deletions

View File

@@ -14285,3 +14285,19 @@ M: Qiufang Dai <qiufang.dai@amlogic.com>
F: drivers/amlogic/clk/g12a/g12a_clk_gpu.c
F: drivers/amlogic/clk/g12a/g12a_clk_media.c
AMLOGIC VOUT_SERVE
M: Evoke Zhang <evoke.zhang@amlogic.com>
F: drivers/amlogic/media/vout/vout_serve/vout2_notify.c
F: drivers/amlogic/media/vout/vout_serve/vout2_serve.c
F: drivers/amlogic/media/vout/vout_serve/vout_func.c
F: drivers/amlogic/media/vout/vout_serve/vout_func.h
AMLOGIC GPIO IRQ
M: Xingyu Chen <xingyu.chen@amlogic.com>
F: drivers/amlogic/irqchip/*
F: Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
AMLOGIC PINCTRL DRIVER
M: Xingyu Chen <xingyu.chen@amlogic.com>
F: drivers/amlogic/pinctrl/*
F: include/dt-bindings/gpio/*

View File

@@ -56,6 +56,18 @@
};
};
vout {
compatible = "amlogic, vout";
dev_name = "vout";
status = "okay";
};
vout2 {
compatible = "amlogic, vout2";
dev_name = "vout";
status = "okay";
};
}; /* end of / */
&aobus{

View File

@@ -279,6 +279,7 @@ CONFIG_AMLOGIC_BL_EXTERN_I2C_LP8556=y
CONFIG_AMLOGIC_BL_EXTERN_MIPI_LT070ME05=y
CONFIG_AMLOGIC_LOCAL_DIMMING=y
CONFIG_AMLOGIC_VOUT_SERVE=y
CONFIG_AMLOGIC_VOUT2_SERVE=y
CONFIG_AMLOGIC_MEDIA_FB=y
CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE=y
CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA=y

View File

@@ -1390,6 +1390,25 @@ void prepare_hdr10_param(
}
}
static inline void fresh_tx_hdr_pkt(struct vout_device_s *vdev)
{
if (vdev) {
if (vdev->fresh_tx_hdr_pkt)
vdev->fresh_tx_hdr_pkt(&hdr10_data);
}
}
static inline void fresh_tx_vsif_pkt(struct vout_device_s *vdev,
int dv_en, int dv_mode)
{
int tmp = (dv_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL ? 1 : 0);
if (vdev) {
if (vdev->fresh_tx_vsif_pkt)
vdev->fresh_tx_vsif_pkt(dv_en, tmp);
}
}
static bool send_hdmi_pkt(
enum signal_format_e dst_format,
const struct vinfo_s *vinfo)
@@ -1507,12 +1526,8 @@ static bool send_hdmi_pkt(
hdr10_data.max_frame_average =
(p_hdr->max_frame_average_light_level_MSB << 8)
| p_hdr->max_frame_average_light_level_LSB;
if (vdev) {
if (vdev->fresh_tx_hdr_pkt)
vdev->fresh_tx_hdr_pkt(&hdr10_data);
if (vdev->fresh_tx_vsif_pkt)
vdev->fresh_tx_vsif_pkt(0, 0);
}
fresh_tx_hdr_pkt(vdev);
fresh_tx_vsif_pkt(vdev, 0, 0);
if (flag) {
pr_dolby_dbg("Info frame for hdr10 changed:\n");
@@ -1553,15 +1568,8 @@ static bool send_hdmi_pkt(
hdr10_data.luminance[1] = 0;
hdr10_data.max_content = 0;
hdr10_data.max_frame_average = 0;
if (vdev) {
if (vdev->fresh_tx_hdr_pkt)
vdev->fresh_tx_hdr_pkt(&hdr10_data);
if (vdev->fresh_tx_vsif_pkt)
vdev->fresh_tx_vsif_pkt(
1, dolby_vision_mode ==
DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL
? 1 : 0);
}
fresh_tx_hdr_pkt(vdev);
fresh_tx_vsif_pkt(vdev, 1, dolby_vision_mode);
} else {
hdr10_data.features =
(1 << 29) /* video available */
@@ -1581,12 +1589,8 @@ static bool send_hdmi_pkt(
hdr10_data.luminance[1] = 0;
hdr10_data.max_content = 0;
hdr10_data.max_frame_average = 0;
if (vdev) {
if (vdev->fresh_tx_hdr_pkt)
vdev->fresh_tx_hdr_pkt(&hdr10_data);
if (vdev->fresh_tx_vsif_pkt)
vdev->fresh_tx_vsif_pkt(0, 0);
}
fresh_tx_hdr_pkt(vdev);
fresh_tx_vsif_pkt(vdev, 0, 0);
}
return flag;
}

View File

@@ -8908,7 +8908,7 @@ static int __init video_early_init(void)
/*(3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M*/
/*moved to vpu.c, default config by dts */
if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/
#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB))
WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff,
@@ -8921,11 +8921,12 @@ static int __init video_early_init(void)
VPP_OFIFO_SIZE_WID);
#endif
#endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
} else {
#else
if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB))
WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff,
VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID);
}
#endif
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096);
WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096);
@@ -8940,23 +8941,20 @@ static int __init video_early_init(void)
if (is_meson_gxbb_cpu())
SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE);
if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/
#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */
CLEAR_VCBUS_REG_MASK(VPP_VSC_PHASE_CTRL,
VPP_PHASECTL_TYPE_INTERLACE);
#ifndef CONFIG_FB_AML_TCON
SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE);
#endif
WRITE_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off, 0x08080808);
}
#endif
#ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2
if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/
#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */
CLEAR_VCBUS_REG_MASK(VPP2_VSC_PHASE_CTRL,
VPP_PHASECTL_TYPE_INTERLACE);
#ifndef CONFIG_FB_AML_TCON
SET_VCBUS_REG_MASK(VPP2_MISC, VPP_OUT_SATURATE);
#endif
WRITE_VCBUS_REG(VPP2_HOLD_LINES, 0x08080808);
}
#endif
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x800,
VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID);

View File

@@ -583,6 +583,24 @@ static int cvbs_module_disable(enum vmode_e cur_vmod)
return 0;
}
static int cvbs_vout_state;
static int cvbs_vout_set_state(int index)
{
cvbs_vout_state |= (1 << index);
return 0;
}
static int cvbs_vout_clr_state(int index)
{
cvbs_vout_state &= ~(1 << index);
return 0;
}
static int cvbs_vout_get_state(void)
{
return cvbs_vout_state;
}
#ifdef CONFIG_PM
static int cvbs_suspend(void)
{
@@ -602,14 +620,17 @@ static int cvbs_resume(void)
}
#endif
static struct vout_server_s cvbs_server = {
.name = "vout_cvbs_server",
static struct vout_server_s cvbs_vout_server = {
.name = "cvbs_vout_server",
.op = {
.get_vinfo = cvbs_get_current_info,
.set_vmode = cvbs_set_current_vmode,
.validate_vmode = cvbs_validate_vmode,
.vmode_is_supported = cvbs_vmode_is_supported,
.disable = cvbs_module_disable,
.set_state = cvbs_vout_set_state,
.clr_state = cvbs_vout_clr_state,
.get_state = cvbs_vout_get_state,
.set_vframe_rate_hint = NULL,
.set_vframe_rate_end_hint = NULL,
.set_vframe_rate_policy = NULL,
@@ -621,15 +642,45 @@ static struct vout_server_s cvbs_server = {
},
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct vout_server_s cvbs_vout2_server = {
.name = "cvbs_vout2_server",
.op = {
.get_vinfo = cvbs_get_current_info,
.set_vmode = cvbs_set_current_vmode,
.validate_vmode = cvbs_validate_vmode,
.vmode_is_supported = cvbs_vmode_is_supported,
.disable = cvbs_module_disable,
.set_state = cvbs_vout_set_state,
.clr_state = cvbs_vout_clr_state,
.get_state = cvbs_vout_get_state,
.set_vframe_rate_hint = NULL,
.set_vframe_rate_end_hint = NULL,
.set_vframe_rate_policy = NULL,
.get_vframe_rate_policy = NULL,
#ifdef CONFIG_PM
.vout_suspend = cvbs_suspend,
.vout_resume = cvbs_resume,
#endif
},
};
#endif
static void cvbs_init_vout(void)
{
if (info->vinfo == NULL)
info->vinfo = &cvbs_info[MODE_480CVBS];
if (vout_register_server(&cvbs_server))
if (vout_register_server(&cvbs_vout_server))
cvbs_log_err("register cvbs module server fail\n");
else
cvbs_log_info("register cvbs module server ok\n");
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
if (vout2_register_server(&cvbs_vout2_server))
cvbs_log_err("register cvbs module vout2 server fail\n");
else
cvbs_log_info("register cvbs module vout2 server ok\n");
#endif
}
/* **************************************************** */
@@ -1292,7 +1343,10 @@ static int cvbsout_remove(struct platform_device *pdev)
cdev_del(info->cdev);
kfree(info);
}
vout_unregister_server(&cvbs_server);
vout_unregister_server(&cvbs_vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_unregister_server(&cvbs_vout2_server);
#endif
cvbs_log_info("%s\n", __func__);
return 0;
}

View File

@@ -2447,14 +2447,35 @@ static int hdmitx_module_disable(enum vmode_e cur_vmod)
return 0;
}
static struct vout_server_s hdmitx_server = {
.name = "vout_hdmitx_server",
static int hdmitx_vout_state;
static int hdmitx_vout_set_state(int index)
{
hdmitx_vout_state |= (1 << index);
return 0;
}
static int hdmitx_vout_clr_state(int index)
{
hdmitx_vout_state &= ~(1 << index);
return 0;
}
static int hdmitx_vout_get_state(void)
{
return hdmitx_vout_state;
}
static struct vout_server_s hdmitx_vout_server = {
.name = "hdmitx_vout_server",
.op = {
.get_vinfo = hdmitx_get_current_vinfo,
.set_vmode = hdmitx_set_current_vmode,
.validate_vmode = hdmitx_validate_vmode,
.vmode_is_supported = hdmitx_vmode_is_supported,
.disable = hdmitx_module_disable,
.set_state = hdmitx_vout_set_state,
.clr_state = hdmitx_vout_clr_state,
.get_state = hdmitx_vout_get_state,
#ifdef CONFIG_PM
.vout_suspend = NULL,
.vout_resume = NULL,
@@ -2462,6 +2483,26 @@ static struct vout_server_s hdmitx_server = {
},
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct vout_server_s hdmitx_vout2_server = {
.name = "hdmitx_vout2_server",
.op = {
.get_vinfo = hdmitx_get_current_vinfo,
.set_vmode = hdmitx_set_current_vmode,
.validate_vmode = hdmitx_validate_vmode,
.vmode_is_supported = hdmitx_vmode_is_supported,
.disable = hdmitx_module_disable,
.set_state = hdmitx_vout_set_state,
.clr_state = hdmitx_vout_clr_state,
.get_state = hdmitx_vout_get_state,
#ifdef CONFIG_PM
.vout_suspend = NULL,
.vout_resume = NULL,
#endif
},
};
#endif
#include <linux/soundcard.h>
#include <sound/core.h>
@@ -3357,7 +3398,10 @@ static int amhdmitx_probe(struct platform_device *pdev)
hdmitx_device.nb.notifier_call = hdmitx_reboot_notifier;
register_reboot_notifier(&hdmitx_device.nb);
vout_register_server(&hdmitx_server);
vout_register_server(&hdmitx_vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_register_server(&hdmitx_vout2_server);
#endif
#ifdef CONFIG_AMLOGIC_SND_SOC
aout_register_client(&hdmitx_notifier_nb_a);
#else
@@ -3390,7 +3434,10 @@ static int amhdmitx_remove(struct platform_device *pdev)
hdmitx_device.HWOp.UnInit(&hdmitx_device);
hdmitx_device.hpd_event = 0xff;
kthread_stop(hdmitx_device.task);
vout_unregister_server(&hdmitx_server);
vout_unregister_server(&hdmitx_vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_unregister_server(&hdmitx_vout2_server);
#endif
#ifdef CONFIG_AMLOGIC_SND_SOC
aout_unregister_client(&hdmitx_notifier_nb_a);
#endif

View File

@@ -62,13 +62,11 @@ extern int lcd_class_remove(void);
#ifdef CONFIG_AMLOGIC_LCD_TV
extern void lcd_vbyone_interrupt_enable(int flag);
extern void lcd_tv_clk_update(struct lcd_config_s *pconf);
extern void lcd_tv_vout_server_init(void);
extern int lcd_tv_probe(struct device *dev);
extern int lcd_tv_remove(struct device *dev);
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
extern void lcd_tablet_clk_update(struct lcd_config_s *pconf);
extern void lcd_tablet_vout_server_init(void);
extern int lcd_tablet_probe(struct device *dev);
extern int lcd_tablet_remove(struct device *dev);
#endif

View File

@@ -49,6 +49,24 @@
* vout server api
* **************************************************
*/
static struct vinfo_s *lcd_get_current_info(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
return lcd_drv->lcd_info;
}
static int lcd_vmode_is_supported(enum vmode_e mode)
{
mode &= VMODE_MODE_BIT_MASK;
if (lcd_debug_print_flag)
LCDPR("%s vmode = %d\n", __func__, mode);
if (mode == VMODE_LCD)
return true;
return false;
}
static enum vmode_e lcd_validate_vmode(char *mode)
{
if (mode == NULL)
@@ -60,13 +78,6 @@ static enum vmode_e lcd_validate_vmode(char *mode)
return VMODE_MAX;
}
static struct vinfo_s *lcd_get_current_info(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
return lcd_drv->lcd_info;
}
static int lcd_set_current_vmode(enum vmode_e mode)
{
int ret = 0;
@@ -90,17 +101,6 @@ static int lcd_set_current_vmode(enum vmode_e mode)
return ret;
}
static int lcd_vmode_is_supported(enum vmode_e mode)
{
mode &= VMODE_MODE_BIT_MASK;
if (lcd_debug_print_flag)
LCDPR("%s vmode = %d\n", __func__, mode);
if (mode == VMODE_LCD)
return true;
return false;
}
static int lcd_vout_disable(enum vmode_e cur_vmod)
{
aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
@@ -108,6 +108,24 @@ static int lcd_vout_disable(enum vmode_e cur_vmod)
return 0;
}
static int lcd_vout_state;
static int lcd_vout_set_state(int index)
{
lcd_vout_state |= (1 << index);
return 0;
}
static int lcd_vout_clr_state(int index)
{
lcd_vout_state &= ~(1 << index);
return 0;
}
static int lcd_vout_get_state(void)
{
return lcd_vout_state;
}
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
struct lcd_vframe_match_s {
int fps;
@@ -343,6 +361,9 @@ static struct vout_server_s lcd_vout_server = {
.validate_vmode = lcd_validate_vmode,
.vmode_is_supported = lcd_vmode_is_supported,
.disable = lcd_vout_disable,
.set_state = lcd_vout_set_state,
.clr_state = lcd_vout_clr_state,
.get_state = lcd_vout_get_state,
.set_vframe_rate_hint = lcd_set_vframe_rate_hint,
.set_vframe_rate_end_hint = lcd_set_vframe_rate_end_hint,
.set_vframe_rate_policy = lcd_set_vframe_rate_policy,
@@ -354,6 +375,30 @@ static struct vout_server_s lcd_vout_server = {
},
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct vout_server_s lcd_vout2_server = {
.name = "lcd_vout2_server",
.op = {
.get_vinfo = lcd_get_current_info,
.set_vmode = lcd_set_current_vmode,
.validate_vmode = lcd_validate_vmode,
.vmode_is_supported = lcd_vmode_is_supported,
.disable = lcd_vout_disable,
.set_state = lcd_vout_set_state,
.clr_state = lcd_vout_clr_state,
.get_state = lcd_vout_get_state,
.set_vframe_rate_hint = lcd_set_vframe_rate_hint,
.set_vframe_rate_end_hint = lcd_set_vframe_rate_end_hint,
.set_vframe_rate_policy = lcd_set_vframe_rate_policy,
.get_vframe_rate_policy = lcd_get_vframe_rate_policy,
#ifdef CONFIG_PM
.vout_suspend = lcd_suspend,
.vout_resume = lcd_resume,
#endif
},
};
#endif
static void lcd_tablet_vinfo_update(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
@@ -430,10 +475,15 @@ static void lcd_tablet_vinfo_update_default(void)
}
}
void lcd_tablet_vout_server_init(void)
static void lcd_tablet_vout_server_init(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_tablet_vinfo_update_default();
vout_register_server(&lcd_vout_server);
lcd_drv->vout_server = &lcd_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
lcd_drv->vout2_server = &lcd_vout2_server;
#endif
}
/* **************************************************

View File

@@ -227,6 +227,7 @@ static void lcd_vmode_vinfo_update(enum vmode_e mode)
lcd_drv->lcd_info->video_clk = pconf->lcd_timing.lcd_clk;
lcd_drv->lcd_info->htotal = pconf->lcd_basic.h_period;
lcd_drv->lcd_info->vtotal = pconf->lcd_basic.v_period;
lcd_drv->lcd_info->viu_mux = VIU_MUX_ENCL;
lcd_hdr_vinfo_update();
}
@@ -328,6 +329,24 @@ static int lcd_vout_disable(enum vmode_e cur_vmod)
return 0;
}
static int lcd_vout_state;
static int lcd_vout_set_state(int index)
{
lcd_vout_state |= (1 << index);
return 0;
}
static int lcd_vout_clr_state(int index)
{
lcd_vout_state &= ~(1 << index);
return 0;
}
static int lcd_vout_get_state(void)
{
return lcd_vout_state;
}
#ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION
struct lcd_vframe_match_s {
int fps;
@@ -572,6 +591,9 @@ static struct vout_server_s lcd_vout_server = {
.validate_vmode = lcd_validate_vmode,
.vmode_is_supported = lcd_vmode_is_supported,
.disable = lcd_vout_disable,
.set_state = lcd_vout_set_state,
.clr_state = lcd_vout_clr_state,
.get_state = lcd_vout_get_state,
.set_vframe_rate_hint = lcd_set_vframe_rate_hint,
.set_vframe_rate_end_hint = lcd_set_vframe_rate_end_hint,
.set_vframe_rate_policy = lcd_set_vframe_rate_policy,
@@ -624,10 +646,15 @@ static void lcd_vinfo_update_default(void)
}
}
void lcd_tv_vout_server_init(void)
static void lcd_tv_vout_server_init(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_vinfo_update_default();
vout_register_server(&lcd_vout_server);
lcd_drv->vout_server = &lcd_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
lcd_drv->vout2_server = NULL;
#endif
}
/* ************************************************** *

View File

@@ -700,21 +700,17 @@ static void lcd_fops_remove(void)
static void lcd_init_vout(void)
{
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_tv_vout_server_init();
break;
if (lcd_driver->vout_server_init)
lcd_driver->vout_server_init();
else
LCDERR("vout_server_init is null\n");
if (lcd_driver->vout_server)
vout_register_server(lcd_driver->vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
if (lcd_driver->vout2_server)
vout2_register_server(lcd_driver->vout2_server);
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
case LCD_MODE_TABLET:
lcd_tablet_vout_server_init();
break;
#endif
default:
LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode);
break;
}
}
static int lcd_mode_probe(struct device *dev)

View File

@@ -9,3 +9,10 @@ config AMLOGIC_VOUT_SERVE
Amlogic Video output Server support.
Provide display mode service for all of the display modules.
config AMLOGIC_VOUT2_SERVE
bool "Amlogic Vout2_Serve Module"
default n
help
Amlogic Video output2 Server support.
Provide 2nd display mode service for all of the display modules.

View File

@@ -1,2 +1,3 @@
obj-$(CONFIG_AMLOGIC_VOUT_SERVE) += vout_notify.o vout_serve.o
obj-$(CONFIG_AMLOGIC_VOUT_SERVE) += vout_notify.o vout_serve.o vout_func.o
obj-$(CONFIG_AMLOGIC_VOUT2_SERVE) += vout2_notify.o vout2_serve.o

View File

@@ -0,0 +1,214 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout2_notify.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/module.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/err.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "vout_func.h"
static BLOCKING_NOTIFIER_HEAD(vout2_notifier_list);
/**
* vout_register_client - register a client notifier
* @nb: notifier block to callback on events
*/
int vout2_register_client(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&vout2_notifier_list, nb);
}
EXPORT_SYMBOL(vout2_register_client);
/**
* vout_unregister_client - unregister a client notifier
* @nb: notifier block to callback on events
*/
int vout2_unregister_client(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&vout2_notifier_list, nb);
}
EXPORT_SYMBOL(vout2_unregister_client);
/**
* vout_notifier_call_chain - notify clients of fb_events
*
*/
int vout2_notifier_call_chain(unsigned long val, void *v)
{
return blocking_notifier_call_chain(&vout2_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(vout2_notifier_call_chain);
/*
*interface export to client who want to get current vinfo.
*/
struct vinfo_s *get_current_vinfo2(void)
{
struct vinfo_s *vinfo = NULL;
struct vout_module_s *p_module = NULL;
p_module = vout_func_get_vout2_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo)
vinfo = p_module->curr_vout_server->op.get_vinfo();
}
if (vinfo == NULL) /* avoid crash mistake */
vinfo = get_invalid_vinfo(2);
return vinfo;
}
EXPORT_SYMBOL(get_current_vinfo2);
/*
*interface export to client who want to get current vmode.
*/
enum vmode_e get_current_vmode2(void)
{
const struct vinfo_s *vinfo;
struct vout_module_s *p_module = NULL;
enum vmode_e mode = VMODE_MAX;
p_module = vout_func_get_vout2_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo) {
vinfo = p_module->curr_vout_server->op.get_vinfo();
if (vinfo)
mode = vinfo->mode;
}
}
return mode;
}
EXPORT_SYMBOL(get_current_vmode2);
const char *get_name_by_vmode2(enum vmode_e mode)
{
const char *str = NULL;
const struct vinfo_s *vinfo = NULL;
struct vout_module_s *p_module = NULL;
p_module = vout_func_get_vout2_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo)
vinfo = p_module->curr_vout_server->op.get_vinfo();
}
if (vinfo == NULL)
vinfo = get_invalid_vinfo(2);
str = vinfo->name;
return str;
}
EXPORT_SYMBOL(get_name_by_vmode2);
/*
* interface export to client who want to set current vmode.
*/
int set_current_vmode2(enum vmode_e mode)
{
return vout_func_set_current_vmode(2, mode);
}
EXPORT_SYMBOL(set_current_vmode2);
/*
*interface export to client who want to set current vmode.
*/
enum vmode_e validate_vmode2(char *name)
{
return vout_func_validate_vmode(2, name);
}
EXPORT_SYMBOL(validate_vmode2);
/*
*interface export to client who want to notify about source frame rate.
*/
int set_vframe2_rate_hint(int duration)
{
return vout_func_set_vframe_rate_hint(2, duration);
}
EXPORT_SYMBOL(set_vframe2_rate_hint);
/*
*interface export to client who want to notify about source frame rate end.
*/
int set_vframe2_rate_end_hint(void)
{
return vout_func_set_vframe_rate_end_hint(2);
}
EXPORT_SYMBOL(set_vframe2_rate_end_hint);
/*
*interface export to client who want to notify about source fr_policy.
*/
int set_vframe2_rate_policy(int policy)
{
return vout_func_set_vframe_rate_policy(2, policy);
}
EXPORT_SYMBOL(set_vframe2_rate_policy);
/*
*interface export to client who want to notify about source fr_policy.
*/
int get_vframe2_rate_policy(void)
{
return vout_func_get_vframe_rate_policy(2);
}
EXPORT_SYMBOL(get_vframe2_rate_policy);
int vout2_suspend(void)
{
return vout_func_vout_suspend(2);
}
EXPORT_SYMBOL(vout2_suspend);
int vout2_resume(void)
{
return vout_func_vout_resume(2);
}
EXPORT_SYMBOL(vout2_resume);
/*
*interface export to client who want to shutdown.
*/
int vout2_shutdown(void)
{
return vout_func_vout_shutdown(2);
}
EXPORT_SYMBOL(vout2_shutdown);
/*
*here we offer two functions to get and register vout module server
*vout module server will set and store tvmode attributes for vout encoder
*we can ensure TVMOD SET MODULE independent with these two function.
*/
int vout2_register_server(struct vout_server_s *mem_server)
{
return vout_func_vout_register_server(2, mem_server);
}
EXPORT_SYMBOL(vout2_register_server);
int vout2_unregister_server(struct vout_server_s *mem_server)
{
return vout_func_vout_unregister_server(2, mem_server);
}
EXPORT_SYMBOL(vout2_unregister_server);

View File

@@ -0,0 +1,821 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout2_serve.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/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ctype.h>
#include <linux/of.h>
#include <linux/major.h>
#include <linux/uaccess.h>
#include <linux/extcon.h>
#include <linux/cdev.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "vout_func.h"
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
#include <linux/amlogic/pm.h>
static struct early_suspend early_suspend;
static int early_suspend_flag;
#endif
#define VOUT_CDEV_NAME "display2"
#define VOUT_CLASS_NAME "display2"
#define MAX_NUMBER_PARA 10
#define VMODE_NAME_LEN_MAX 64
static struct class *vout2_class;
static DEFINE_MUTEX(vout2_serve_mutex);
static char vout2_mode[VMODE_NAME_LEN_MAX];
static char local_name[VMODE_NAME_LEN_MAX] = {0};
static char vout2_axis[64];
static struct extcon_dev *vout2_excton_setmode;
static const unsigned int vout2_cable[] = {
EXTCON_TYPE_DISP,
EXTCON_NONE,
};
static struct vout_cdev_s *vout2_cdev;
/* **********************************************************
* null display support
* **********************************************************
*/
static struct vinfo_s nulldisp_vinfo = {
.name = "null",
.mode = VMODE_NULL,
.width = 1920,
.height = 1080,
.field_height = 1080,
.aspect_ratio_num = 16,
.aspect_ratio_den = 9,
.sync_duration_num = 60,
.sync_duration_den = 1,
.video_clk = 148500000,
.htotal = 2200,
.vtotal = 1125,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
};
static struct vinfo_s *nulldisp_get_current_info(void)
{
return &nulldisp_vinfo;
}
static int nulldisp_set_current_vmode(enum vmode_e mode)
{
return 0;
}
static enum vmode_e nulldisp_validate_vmode(char *name)
{
if (strncmp(nulldisp_vinfo.name, name,
strlen(nulldisp_vinfo.name)) == 0) {
return nulldisp_vinfo.mode;
}
return VMODE_MAX;
}
static int nulldisp_vmode_is_supported(enum vmode_e mode)
{
if (nulldisp_vinfo.mode == mode)
return true;
return false;
}
static int nulldisp_disable(enum vmode_e cur_vmod)
{
return 0;
}
static int nulldisp_vout_state;
static int nulldisp_vout_set_state(int bit)
{
nulldisp_vout_state |= (1 << bit);
return 0;
}
static int nulldisp_vout_clr_state(int bit)
{
nulldisp_vout_state &= ~(1 << bit);
return 0;
}
static int nulldisp_vout_get_state(void)
{
return nulldisp_vout_state;
}
static struct vout_server_s nulldisp_vout2_server = {
.name = "nulldisp_vout2_server",
.op = {
.get_vinfo = nulldisp_get_current_info,
.set_vmode = nulldisp_set_current_vmode,
.validate_vmode = nulldisp_validate_vmode,
.vmode_is_supported = nulldisp_vmode_is_supported,
.disable = nulldisp_disable,
.set_state = nulldisp_vout_set_state,
.clr_state = nulldisp_vout_clr_state,
.get_state = nulldisp_vout_get_state,
},
};
/* ********************************************************** */
char *get_vout2_mode_internal(void)
{
return vout2_mode;
}
EXPORT_SYMBOL(get_vout2_mode_internal);
static int set_vout2_mode(char *name)
{
enum vmode_e mode;
int ret = 0;
VOUTPR("vout2: vmode set to %s\n", name);
if (strcmp(name, local_name) == 0) {
VOUTPR("vout2: don't set the same mode as current\n");
return -1;
}
mode = validate_vmode2(name);
if (mode == VMODE_MAX) {
VOUTERR("vout2: no matched vout2 mode\n");
return -1;
}
memset(local_name, 0, sizeof(local_name));
snprintf(local_name, VMODE_NAME_LEN_MAX, "%s", name);
extcon_set_state_sync(vout2_excton_setmode, EXTCON_TYPE_DISP, 1);
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
ret = set_current_vmode2(mode);
if (ret) {
VOUTERR("vout2: new mode %s set error\n", name);
} else {
snprintf(vout2_mode, VMODE_NAME_LEN_MAX, "%s", name);
VOUTPR("vout2: new mode %s set ok\n", vout2_mode);
}
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
extcon_set_state_sync(vout2_excton_setmode, EXTCON_TYPE_DISP, 0);
return ret;
}
static int set_vout2_init_mode(void)
{
enum vmode_e vmode = VMODE_NULL;
int ret = 0;
ret = set_current_vmode2(vmode);
if (ret) {
VOUTERR("vout2: init mode null set error\n");
} else {
snprintf(vout2_mode, VMODE_NAME_LEN_MAX, "null");
VOUTPR("vout2: init mode %s set ok\n", vout2_mode);
}
return ret;
}
static int parse_para(const char *para, int para_num, int *result)
{
char *token = NULL;
char *params, *params_base;
int *out = result;
int len = 0, count = 0;
int res = 0;
int ret = 0;
if (!para)
return 0;
params = kstrdup(para, GFP_KERNEL);
params_base = params;
token = params;
len = strlen(token);
do {
token = strsep(&params, " ");
while (token && (isspace(*token)
|| !isgraph(*token)) && len) {
token++;
len--;
}
if ((!token) || (*token == '\n') || (len == 0))
break;
ret = kstrtoint(token, 0, &res);
if (ret < 0)
break;
len = strlen(token);
*out++ = res;
count++;
} while ((token) && (count < para_num) && (len > 0));
kfree(params_base);
return count;
}
#define OSD_COUNT 2
static void set_vout2_axis(char *para)
{
static struct disp_rect_s disp_rect[OSD_COUNT];
/* char count = OSD_COUNT * 4; */
int *pt = &disp_rect[0].x;
int parsed[MAX_NUMBER_PARA] = {};
/* parse window para */
if (parse_para(para, 8, parsed) >= 4)
memcpy(pt, parsed, sizeof(struct disp_rect_s) * OSD_COUNT);
/* if ((count >= 4) && (count < 8))
* disp_rect[1] = disp_rect[0];
*/
VOUTPR("vout2: osd0=> x:%d,y:%d,w:%d,h:%d\n"
"osd1=> x:%d,y:%d,w:%d,h:%d\n",
*pt, *(pt + 1), *(pt + 2), *(pt + 3),
*(pt + 4), *(pt + 5), *(pt + 6), *(pt + 7));
vout2_notifier_call_chain(VOUT_EVENT_OSD_DISP_AXIS, &disp_rect[0]);
}
static ssize_t vout2_mode_show(struct class *class,
struct class_attribute *attr, char *buf)
{
int ret = 0;
ret = snprintf(buf, VMODE_NAME_LEN_MAX, "%s\n", vout2_mode);
return ret;
}
static ssize_t vout2_mode_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
char mode[64];
mutex_lock(&vout2_serve_mutex);
snprintf(mode, VMODE_NAME_LEN_MAX, "%s", buf);
set_vout2_mode(mode);
mutex_unlock(&vout2_serve_mutex);
return count;
}
static ssize_t vout2_axis_show(struct class *class,
struct class_attribute *attr, char *buf)
{
int ret = 0;
ret = snprintf(buf, 64, "%s\n", vout2_axis);
return ret;
}
static ssize_t vout2_axis_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
mutex_lock(&vout2_serve_mutex);
snprintf(vout2_axis, 64, "%s", buf);
set_vout2_axis(vout2_axis);
mutex_unlock(&vout2_serve_mutex);
return count;
}
static ssize_t vout2_fr_policy_show(struct class *class,
struct class_attribute *attr, char *buf)
{
int policy;
int ret = 0;
policy = get_vframe2_rate_policy();
ret = sprintf(buf, "%d\n", policy);
return ret;
}
static ssize_t vout2_fr_policy_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int policy;
int ret = 0;
mutex_lock(&vout2_serve_mutex);
ret = kstrtoint(buf, 10, &policy);
if (ret) {
pr_info("%s: invalid data\n", __func__);
mutex_unlock(&vout2_serve_mutex);
return -EINVAL;
}
ret = set_vframe2_rate_policy(policy);
if (ret)
pr_info("%s: %d failed\n", __func__, policy);
mutex_unlock(&vout2_serve_mutex);
return count;
}
static ssize_t vout2_vinfo_show(struct class *class,
struct class_attribute *attr, char *buf)
{
const struct vinfo_s *info = NULL;
ssize_t len = 0;
info = get_current_vinfo2();
if (info == NULL)
return sprintf(buf, "current vinfo2 is null\n");
len = sprintf(buf, "current vinfo2:\n"
" name: %s\n"
" mode: %d\n"
" width: %d\n"
" height: %d\n"
" field_height: %d\n"
" aspect_ratio_num: %d\n"
" aspect_ratio_den: %d\n"
" sync_duration_num: %d\n"
" sync_duration_den: %d\n"
" screen_real_width: %d\n"
" screen_real_height: %d\n"
" htotal: %d\n"
" vtotal: %d\n"
" video_clk: %d\n"
" viu_color_fmt: %d\n"
" viu_mux: %d\n\n",
info->name, info->mode,
info->width, info->height, info->field_height,
info->aspect_ratio_num, info->aspect_ratio_den,
info->sync_duration_num, info->sync_duration_den,
info->screen_real_width, info->screen_real_height,
info->htotal, info->vtotal,
info->video_clk, info->viu_color_fmt, info->viu_mux);
len += sprintf(buf+len, "master_display_info:\n"
" present_flag %d\n"
" features 0x%x\n"
" primaries 0x%x, 0x%x\n"
" 0x%x, 0x%x\n"
" 0x%x, 0x%x\n"
" white_point 0x%x, 0x%x\n"
" luminance %d, %d\n\n",
info->master_display_info.present_flag,
info->master_display_info.features,
info->master_display_info.primaries[0][0],
info->master_display_info.primaries[0][1],
info->master_display_info.primaries[1][0],
info->master_display_info.primaries[1][1],
info->master_display_info.primaries[2][0],
info->master_display_info.primaries[2][1],
info->master_display_info.white_point[0],
info->master_display_info.white_point[1],
info->master_display_info.luminance[0],
info->master_display_info.luminance[1]);
len += sprintf(buf+len, "hdr_info:\n"
" hdr_support %d\n"
" lumi_max %d\n"
" lumi_avg %d\n"
" lumi_min %d\n",
info->hdr_info.hdr_support,
info->hdr_info.lumi_max,
info->hdr_info.lumi_avg,
info->hdr_info.lumi_min);
return len;
}
static struct class_attribute vout2_class_attrs[] = {
__ATTR(mode, 0644, vout2_mode_show, vout2_mode_store),
__ATTR(axis, 0644, vout2_axis_show, vout2_axis_store),
__ATTR(fr_policy, 0644,
vout2_fr_policy_show, vout2_fr_policy_store),
__ATTR(vinfo, 0444, vout2_vinfo_show, NULL),
};
static int vout2_attr_create(void)
{
int i;
int ret = 0;
/* create vout class */
vout2_class = class_create(THIS_MODULE, VOUT_CLASS_NAME);
if (IS_ERR(vout2_class)) {
VOUTERR("vout2: create vout2 class fail\n");
return -1;
}
/* create vout class attr files */
for (i = 0; i < ARRAY_SIZE(vout2_class_attrs); i++) {
if (class_create_file(vout2_class, &vout2_class_attrs[i])) {
VOUTERR("vout2: create vout2 attribute %s fail\n",
vout2_class_attrs[i].attr.name);
}
}
VOUTPR("vout2: create vout2 attribute OK\n");
return ret;
}
static int vout2_attr_remove(void)
{
int i;
if (vout2_class == NULL)
return 0;
for (i = 0; i < ARRAY_SIZE(vout2_class_attrs); i++)
class_remove_file(vout2_class, &vout2_class_attrs[i]);
class_destroy(vout2_class);
vout2_class = NULL;
return 0;
}
/* ************************************************************* */
/* vout2 ioctl */
/* ************************************************************* */
static int vout2_io_open(struct inode *inode, struct file *file)
{
struct vout_cdev_s *vcdev;
VOUTPR("%s\n", __func__);
vcdev = container_of(inode->i_cdev, struct vout_cdev_s, cdev);
file->private_data = vcdev;
return 0;
}
static int vout2_io_release(struct inode *inode, struct file *file)
{
VOUTPR("%s\n", __func__);
file->private_data = NULL;
return 0;
}
static long vout2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
void __user *argp;
int mcd_nr;
struct vinfo_s *info = NULL;
struct vinfo_base_s baseinfo;
mcd_nr = _IOC_NR(cmd);
VOUTPR("%s: cmd_dir = 0x%x, cmd_nr = 0x%x\n",
__func__, _IOC_DIR(cmd), mcd_nr);
argp = (void __user *)arg;
switch (mcd_nr) {
case VOUT_IOC_NR_GET_VINFO:
info = get_current_vinfo2();
if (info == NULL)
ret = -EFAULT;
else if (info->mode == VMODE_INIT_NULL)
ret = -EFAULT;
else {
baseinfo.mode = info->mode;
baseinfo.width = info->width;
baseinfo.height = info->height;
baseinfo.field_height = info->field_height;
baseinfo.aspect_ratio_num = info->aspect_ratio_num;
baseinfo.aspect_ratio_den = info->aspect_ratio_den;
baseinfo.sync_duration_num = info->sync_duration_num;
baseinfo.sync_duration_den = info->sync_duration_den;
baseinfo.screen_real_width = info->screen_real_width;
baseinfo.screen_real_height = info->screen_real_height;
baseinfo.video_clk = info->video_clk;
baseinfo.viu_color_fmt = info->viu_color_fmt;
baseinfo.hdr_info = info->hdr_info;
if (copy_to_user(argp, &baseinfo,
sizeof(struct vinfo_base_s)))
ret = -EFAULT;
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
#ifdef CONFIG_COMPAT
static long vout2_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned long ret;
arg = (unsigned long)compat_ptr(arg);
ret = vout2_ioctl(file, cmd, arg);
return ret;
}
#endif
static const struct file_operations vout2_fops = {
.owner = THIS_MODULE,
.open = vout2_io_open,
.release = vout2_io_release,
.unlocked_ioctl = vout2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = vout2_compat_ioctl,
#endif
};
static int vout2_fops_create(void)
{
int ret = 0;
vout2_cdev = kmalloc(sizeof(struct vout_cdev_s), GFP_KERNEL);
if (!vout2_cdev) {
VOUTERR("vout2: failed to allocate vout2_cdev\n");
return -1;
}
ret = alloc_chrdev_region(&vout2_cdev->devno, 0, 1, VOUT_CDEV_NAME);
if (ret < 0) {
VOUTERR("vout2: failed to alloc vout2 devno\n");
goto vout2_fops_err1;
}
cdev_init(&vout2_cdev->cdev, &vout2_fops);
vout2_cdev->cdev.owner = THIS_MODULE;
ret = cdev_add(&vout2_cdev->cdev, vout2_cdev->devno, 1);
if (ret) {
VOUTERR("vout2: failed to add vout2 cdev\n");
goto vout2_fops_err2;
}
vout2_cdev->dev = device_create(vout2_class, NULL, vout2_cdev->devno,
NULL, VOUT_CDEV_NAME);
if (IS_ERR(vout2_cdev->dev)) {
ret = PTR_ERR(vout2_cdev->dev);
VOUTERR("vout2: failed to create vout2 device: %d\n", ret);
goto vout2_fops_err3;
}
VOUTPR("vout2: %s OK\n", __func__);
return 0;
vout2_fops_err3:
cdev_del(&vout2_cdev->cdev);
vout2_fops_err2:
unregister_chrdev_region(vout2_cdev->devno, 1);
vout2_fops_err1:
kfree(vout2_cdev);
vout2_cdev = NULL;
return -1;
}
static void vout2_fops_remove(void)
{
cdev_del(&vout2_cdev->cdev);
unregister_chrdev_region(vout2_cdev->devno, 1);
kfree(vout2_cdev);
vout2_cdev = NULL;
}
/* ************************************************************* */
#ifdef CONFIG_PM
static int aml_vout2_suspend(struct platform_device *pdev, pm_message_t state)
{
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
if (early_suspend_flag)
return 0;
#endif
vout2_suspend();
return 0;
}
static int aml_vout2_resume(struct platform_device *pdev)
{
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
if (early_suspend_flag)
return 0;
#endif
vout2_resume();
return 0;
}
#endif
#ifdef CONFIG_HIBERNATION
static int aml_vout2_freeze(struct device *dev)
{
return 0;
}
static int aml_vout2_thaw(struct device *dev)
{
return 0;
}
static int aml_vout2_restore(struct device *dev)
{
enum vmode_e mode;
mode = get_current_vmode2();
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
return 0;
}
static int aml_vout2_pm_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
return aml_vout2_suspend(pdev, PMSG_SUSPEND);
}
static int aml_vout2_pm_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
return aml_vout2_resume(pdev);
}
#endif
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
static void aml_vout2_early_suspend(struct early_suspend *h)
{
if (early_suspend_flag)
return;
vout2_suspend();
early_suspend_flag = 1;
}
static void aml_vout2_late_resume(struct early_suspend *h)
{
if (!early_suspend_flag)
return;
early_suspend_flag = 0;
vout2_resume();
}
#endif
static void aml_vout2_extcon_register(struct platform_device *pdev)
{
struct extcon_dev *edev;
int ret;
/*set display mode*/
edev = extcon_dev_allocate(vout2_cable);
if (IS_ERR(edev)) {
VOUTERR("failed to allocate vout2 extcon setmode\n");
return;
}
edev->dev.parent = &pdev->dev;
edev->name = "vout2_excton_setmode";
dev_set_name(&edev->dev, "setmode2");
ret = extcon_dev_register(edev);
if (ret) {
VOUTERR("failed to register vout2 extcon setmode\n");
return;
}
vout2_excton_setmode = edev;
}
static void aml_vout2_extcon_free(void)
{
extcon_dev_free(vout2_excton_setmode);
vout2_excton_setmode = NULL;
}
/*****************************************************************
**
** vout driver interface
**
******************************************************************/
static int aml_vout2_probe(struct platform_device *pdev)
{
int ret = -1;
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
early_suspend.suspend = aml_vout2_early_suspend;
early_suspend.resume = aml_vout2_late_resume;
register_early_suspend(&early_suspend);
#endif
vout2_class = NULL;
ret = vout2_attr_create();
ret = vout2_fops_create();
vout2_register_server(&nulldisp_vout2_server);
set_vout2_init_mode();
aml_vout2_extcon_register(pdev);
VOUTPR("vout2: %s OK\n", __func__);
return ret;
}
static int aml_vout2_remove(struct platform_device *pdev)
{
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
unregister_early_suspend(&early_suspend);
#endif
aml_vout2_extcon_free();
vout2_attr_remove();
vout2_fops_remove();
vout2_unregister_server(&nulldisp_vout2_server);
return 0;
}
static void aml_vout2_shutdown(struct platform_device *pdev)
{
VOUTPR("vout2: %s\n", __func__);
vout2_shutdown();
}
static const struct of_device_id aml_vout2_dt_match[] = {
{ .compatible = "amlogic, vout2",},
{ },
};
#ifdef CONFIG_HIBERNATION
const struct dev_pm_ops vout2_pm = {
.freeze = aml_vout2_freeze,
.thaw = aml_vout2_thaw,
.restore = aml_vout2_restore,
.suspend = aml_vout2_pm_suspend,
.resume = aml_vout2_pm_resume,
};
#endif
static struct platform_driver vout2_driver = {
.probe = aml_vout2_probe,
.remove = aml_vout2_remove,
.shutdown = aml_vout2_shutdown,
#ifdef CONFIG_PM
.suspend = aml_vout2_suspend,
.resume = aml_vout2_resume,
#endif
.driver = {
.name = "vout2",
.of_match_table = aml_vout2_dt_match,
#ifdef CONFIG_HIBERNATION
.pm = &vout2_pm,
#endif
},
};
static int __init vout2_init_module(void)
{
int ret = 0;
if (platform_driver_register(&vout2_driver)) {
VOUTERR("vout2: failed to register VOUT2 driver\n");
ret = -ENODEV;
}
return ret;
}
static __exit void vout2_exit_module(void)
{
platform_driver_unregister(&vout2_driver);
}
module_init(vout2_init_module);
module_exit(vout2_exit_module);
MODULE_AUTHOR("Platform-BJ <platform.bj@amlogic.com>");
MODULE_DESCRIPTION("VOUT2 Server Module");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,549 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout_func.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/module.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/err.h>
/* Amlogic Headers */
#include <linux/amlogic/iomap.h>
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "vout_func.h"
static DEFINE_MUTEX(vout_mutex);
static struct vout_module_s vout_module = {
.vout_server_list = {
&vout_module.vout_server_list,
&vout_module.vout_server_list
},
.curr_vout_server = NULL,
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct vout_module_s vout2_module = {
.vout_server_list = {
&vout2_module.vout_server_list,
&vout2_module.vout_server_list
},
.curr_vout_server = NULL,
};
#endif
static struct vinfo_s invalid_vinfo = {
.name = "invalid",
.mode = VMODE_INIT_NULL,
.width = 1920,
.height = 1080,
.field_height = 1080,
.aspect_ratio_num = 16,
.aspect_ratio_den = 9,
.sync_duration_num = 60,
.sync_duration_den = 1,
.video_clk = 148500000,
.htotal = 2200,
.vtotal = 1125,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
};
struct vinfo_s *get_invalid_vinfo(int index)
{
VOUTERR("invalid vinfo%d. current vmode is not supported\n", index);
return &invalid_vinfo;
}
EXPORT_SYMBOL(get_invalid_vinfo);
struct vout_module_s *vout_func_get_vout_module(void)
{
return &vout_module;
}
EXPORT_SYMBOL(vout_func_get_vout_module);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
struct vout_module_s *vout_func_get_vout2_module(void)
{
return &vout2_module;
}
EXPORT_SYMBOL(vout_func_get_vout2_module);
#endif
static unsigned int vout_func_vcbus_read(unsigned int _reg)
{
return aml_read_vcbus(_reg);
};
static void vout_func_vcbus_write(unsigned int _reg, unsigned int _value)
{
aml_write_vcbus(_reg, _value);
};
static void vout_func_vcbus_setb(unsigned int _reg, unsigned int _value,
unsigned int _start, unsigned int _len)
{
vout_func_vcbus_write(_reg, ((vout_func_vcbus_read(_reg) &
~(((1L << (_len))-1) << (_start))) |
(((_value)&((1L<<(_len))-1)) << (_start))));
}
static inline int vout_func_check_state(int index, unsigned int state,
struct vout_server_s *p_server)
{
if (state & ~(1 << index)) {
/*VOUTERR("vout%d: server %s is actived by another vout\n",
* index, p_server->name);
*/
return -1;
}
return 0;
}
static void vout_func_update_viu(int index, struct vout_server_s *p_server)
{
struct vinfo_s *vinfo = NULL;
unsigned int post_reg = VPP_POSTBLEND_H_SIZE;
unsigned int bit = 0, mux = 3;
return;
if (p_server->op.get_vinfo)
vinfo = p_server->op.get_vinfo();
else
vinfo = get_invalid_vinfo(index);
switch (index) {
case 1:
post_reg = VPP_POSTBLEND_H_SIZE;
bit = 0;
break;
case 2:
post_reg = VPP2_POSTBLEND_H_SIZE;
bit = 2;
break;
default:
break;
}
mux = vinfo->viu_mux;
vout_func_vcbus_write(post_reg, vinfo->width);
vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, mux, bit, 2);
}
/*
* interface export to client who want to set current vmode.
*/
int vout_func_set_current_vmode(int index, enum vmode_e mode)
{
int ret = -1;
struct vout_server_s *p_server;
struct vout_module_s *p_module = NULL;
int state;
mutex_lock(&vout_mutex);
if (index == 1)
p_module = &vout_module;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_module = &vout2_module;
#endif
list_for_each_entry(p_server, &p_module->vout_server_list, list) {
if (p_server->op.vmode_is_supported == NULL) {
p_server->op.disable(mode);
continue;
}
if (p_server->op.vmode_is_supported(mode) == true) {
p_module->curr_vout_server = p_server;
ret = p_server->op.set_vmode(mode);
if (p_server->op.set_state)
p_server->op.set_state(index);
vout_func_update_viu(index, p_server);
} else {
if (p_server->op.get_state) {
state = p_server->op.get_state();
if (state & (1 << index))
p_server->op.disable(mode);
}
if (p_server->op.clr_state)
p_server->op.clr_state(index);
}
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_set_current_vmode);
/*
*interface export to client who want to set current vmode.
*/
enum vmode_e vout_func_validate_vmode(int index, char *name)
{
enum vmode_e ret = VMODE_MAX;
struct vout_server_s *p_server;
struct vout_module_s *p_module = NULL;
int state;
mutex_lock(&vout_mutex);
if (index == 1)
p_module = &vout_module;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_module = &vout2_module;
#endif
list_for_each_entry(p_server, &p_module->vout_server_list, list) {
/* check state for another vout */
if (p_server->op.get_state) {
state = p_server->op.get_state();
if (vout_func_check_state(index, state, p_server))
continue;
}
if (p_server->op.validate_vmode) {
ret = p_server->op.validate_vmode(name);
if (ret != VMODE_MAX) /* valid vmode find. */
break;
}
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_validate_vmode);
int vout_func_set_vframe_rate_hint(int index, int duration)
{
int ret = -1;
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_server = vout2_module.curr_vout_server;
#endif
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.set_vframe_rate_hint)
ret = p_server->op.set_vframe_rate_hint(duration);
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_set_vframe_rate_hint);
/*
*interface export to client who want to notify about source frame rate end.
*/
int vout_func_set_vframe_rate_end_hint(int index)
{
int ret = -1;
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_server = vout2_module.curr_vout_server;
#endif
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.set_vframe_rate_end_hint)
ret = p_server->op.set_vframe_rate_end_hint();
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_set_vframe_rate_end_hint);
/*
*interface export to client who want to notify about source fr_policy.
*/
int vout_func_set_vframe_rate_policy(int index, int policy)
{
int ret = -1;
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_server = vout2_module.curr_vout_server;
#endif
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.set_vframe_rate_policy)
ret = p_server->op.set_vframe_rate_policy(policy);
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_set_vframe_rate_policy);
/*
*interface export to client who want to notify about source fr_policy.
*/
int vout_func_get_vframe_rate_policy(int index)
{
int ret = -1;
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_server = vout2_module.curr_vout_server;
#endif
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.get_vframe_rate_policy)
ret = p_server->op.get_vframe_rate_policy();
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_get_vframe_rate_policy);
int vout_func_vout_suspend(int index)
{
int ret = 0;
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
else if (index == 2)
p_server = vout2_module.curr_vout_server;
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.vout_suspend)
ret = p_server->op.vout_suspend();
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(vout_func_vout_suspend);
int vout_func_vout_resume(int index)
{
struct vout_server_s *p_server = NULL;
mutex_lock(&vout_mutex);
if (index == 1)
p_server = vout_module.curr_vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_server = vout2_module.curr_vout_server;
#endif
if (!IS_ERR_OR_NULL(p_server)) {
if (p_server->op.vout_resume) {
/* ignore error when resume. */
p_server->op.vout_resume();
}
}
mutex_unlock(&vout_mutex);
return 0;
}
EXPORT_SYMBOL(vout_func_vout_resume);
/*
*interface export to client who want to shutdown.
*/
int vout_func_vout_shutdown(int index)
{
int ret = -1;
struct vout_server_s *p_server;
struct vout_module_s *p_module = NULL;
if (index == 1)
p_module = &vout_module;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_module = &vout2_module;
#endif
list_for_each_entry(p_server, &p_module->vout_server_list, list) {
if (p_server->op.vout_shutdown)
ret = p_server->op.vout_shutdown();
}
return ret;
}
EXPORT_SYMBOL(vout_func_vout_shutdown);
/*
*here we offer two functions to get and register vout module server
*vout module server will set and store tvmode attributes for vout encoder
*we can ensure TVMOD SET MODULE independent with these two function.
*/
int vout_func_vout_register_server(int index,
struct vout_server_s *mem_server)
{
struct list_head *p_iter;
struct vout_server_s *p_server;
struct vout_module_s *p_module = NULL;
if (mem_server == NULL) {
VOUTERR("vout%d: server is NULL\n", index);
return -1;
}
if (mem_server->name == NULL) {
VOUTERR("vout%d: server name is NULL\n", index);
return -1;
}
VOUTPR("vout%d: register server: %s\n", index, mem_server->name);
mutex_lock(&vout_mutex);
if (index == 1)
p_module = &vout_module;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_module = &vout2_module;
#endif
list_for_each(p_iter, &p_module->vout_server_list) {
p_server = list_entry(p_iter, struct vout_server_s, list);
if (p_server->name &&
(strcmp(p_server->name, mem_server->name) == 0)) {
VOUTPR("vout%d: server %s is already registered\n",
index, mem_server->name);
/* vout server already registered. */
mutex_unlock(&vout_mutex);
return -1;
}
}
list_add(&mem_server->list, &p_module->vout_server_list);
mutex_unlock(&vout_mutex);
return 0;
}
EXPORT_SYMBOL(vout_func_vout_register_server);
int vout_func_vout_unregister_server(int index,
struct vout_server_s *mem_server)
{
struct vout_server_s *p_server;
struct vout_module_s *p_module = NULL;
if (mem_server == NULL) {
VOUTERR("vout%d: server is NULL\n", index);
return -1;
}
VOUTPR("vout%d: unregister server: %s\n", index, mem_server->name);
mutex_lock(&vout_mutex);
if (index == 1)
p_module = &vout_module;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
else if (index == 2)
p_module = &vout2_module;
#endif
list_for_each_entry(p_server, &p_module->vout_server_list, list) {
if (p_server->name && mem_server->name &&
(strcmp(p_server->name, mem_server->name) == 0)) {
/*
* We will not move current vout server pointer
* automatically if current vout server pointer
* is the one which will be deleted next.
* So you should change current vout server
* first then remove it
*/
if (p_module->curr_vout_server == p_server)
p_module->curr_vout_server = NULL;
list_del(&mem_server->list);
mutex_unlock(&vout_mutex);
return 0;
}
}
mutex_unlock(&vout_mutex);
return 0;
}
EXPORT_SYMBOL(vout_func_vout_unregister_server);
/* fps = 9600/duration/100 hz */
static int vsource_fps_table[][2] = {
/* duration fps */
{1600, 6000,},
{1601, 5994,},
{1602, 5994,},
{1920, 5000,},
{3200, 3000,},
{3203, 2997,},
{3840, 2500,},
{4000, 2400,},
{4004, 2397,},
};
int vout_get_vsource_fps(int duration)
{
int i;
int fps = 6000;
for (i = 0; i < 9; i++) {
if (duration == vsource_fps_table[i][0]) {
fps = vsource_fps_table[i][1];
break;
}
}
return fps;
}
EXPORT_SYMBOL(vout_get_vsource_fps);
int vout_get_hpd_state(void)
{
int ret = 0;
#ifdef CONFIG_AMLOGIC_HDMITX
ret = get_hpd_state();
#endif
return ret;
}
EXPORT_SYMBOL(vout_get_hpd_state);

View File

@@ -0,0 +1,83 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout_func.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 _VOUT_FUNC_H_
#define _VOUT_FUNC_H_
#include <linux/cdev.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#define VOUTPR(fmt, args...) pr_info("vout: "fmt"", ## args)
#define VOUTERR(fmt, args...) pr_err("vout: error: "fmt"", ## args)
/* [ 3: 2] cntl_viu2_sel_venc:
* 0=No connection, 1=ENCI, 2=ENCP, 3=ENCT.
* [ 1: 0] cntl_viu1_sel_venc:
* 0=No connection, 1=ENCI, 2=ENCP, 3=ENCT.
*/
#define VPU_VIU_VENC_MUX_CTRL 0x271a
#define VPP_POSTBLEND_H_SIZE 0x1d21
#define VPP2_POSTBLEND_H_SIZE 0x1921
struct vout_cdev_s {
dev_t devno;
struct cdev cdev;
struct device *dev;
};
#ifdef CONFIG_AMLOGIC_HDMITX
extern int get_hpd_state(void);
#endif
extern int vout_get_hpd_state(void);
extern struct vinfo_s *get_invalid_vinfo(int index);
extern struct vout_module_s *vout_func_get_vout_module(void);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
extern struct vout_module_s *vout_func_get_vout2_module(void);
#endif
extern int vout_func_set_current_vmode(int index, enum vmode_e mode);
extern enum vmode_e vout_func_validate_vmode(int index, char *name);
extern int vout_func_set_vframe_rate_hint(int index, int duration);
extern int vout_func_set_vframe_rate_end_hint(int index);
extern int vout_func_set_vframe_rate_policy(int index, int policy);
extern int vout_func_get_vframe_rate_policy(int index);
extern int vout_func_vout_suspend(int index);
extern int vout_func_vout_resume(int index);
extern int vout_func_vout_shutdown(int index);
extern int vout_func_vout_register_server(int index,
struct vout_server_s *mem_server);
extern int vout_func_vout_unregister_server(int index,
struct vout_server_s *mem_server);
extern int set_current_vmode(enum vmode_e);
extern enum vmode_e validate_vmode(char *p);
extern int vout_suspend(void);
extern int vout_resume(void);
extern int vout_shutdown(void);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
extern int set_current_vmode2(enum vmode_e);
extern enum vmode_e validate_vmode2(char *p);
extern int vout2_suspend(void);
extern int vout2_resume(void);
extern int vout2_shutdown(void);
#endif
#endif

View File

@@ -19,23 +19,15 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/err.h>
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "vout_serve.h"
#include "vout_func.h"
static BLOCKING_NOTIFIER_HEAD(vout_notifier_list);
static DEFINE_MUTEX(vout_mutex);
static struct vout_module_s vout_module = {
.vout_server_list = {
&vout_module.vout_server_list,
&vout_module.vout_server_list
},
.curr_vout_server = NULL,
};
/**
* vout_register_client - register a client notifier
@@ -67,43 +59,23 @@ int vout_notifier_call_chain(unsigned long val, void *v)
}
EXPORT_SYMBOL_GPL(vout_notifier_call_chain);
static struct vinfo_s vinfo_invalid = {
.name = "invalid",
.mode = VMODE_INIT_NULL,
.width = 1920,
.height = 1080,
.field_height = 1080,
.aspect_ratio_num = 16,
.aspect_ratio_den = 9,
.sync_duration_num = 60,
.sync_duration_den = 1,
.video_clk = 148500000,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
};
static struct vinfo_s *get_invalid_vinfo(void)
{
VOUTERR("invalid vinfo. current vmode is not supported\n");
return &vinfo_invalid;
}
/*
*interface export to client who want to get current vinfo.
*/
struct vinfo_s *get_current_vinfo(void)
{
struct vinfo_s *info = NULL;
struct vinfo_s *vinfo = NULL;
struct vout_module_s *p_module = NULL;
if (vout_module.curr_vout_server) {
if (vout_module.curr_vout_server->op.get_vinfo)
info = vout_module.curr_vout_server->op.get_vinfo();
p_module = vout_func_get_vout_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo)
vinfo = p_module->curr_vout_server->op.get_vinfo();
}
if (info == NULL) /* avoid crash mistake */
info = get_invalid_vinfo();
if (vinfo == NULL) /* avoid crash mistake */
vinfo = get_invalid_vinfo(1);
return info;
return vinfo;
}
EXPORT_SYMBOL(get_current_vinfo);
@@ -112,13 +84,16 @@ EXPORT_SYMBOL(get_current_vinfo);
*/
enum vmode_e get_current_vmode(void)
{
const struct vinfo_s *info;
const struct vinfo_s *vinfo;
struct vout_module_s *p_module = NULL;
enum vmode_e mode = VMODE_MAX;
if (vout_module.curr_vout_server) {
if (vout_module.curr_vout_server->op.get_vinfo) {
info = vout_module.curr_vout_server->op.get_vinfo();
mode = info->mode;
p_module = vout_func_get_vout_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo) {
vinfo = p_module->curr_vout_server->op.get_vinfo();
if (vinfo)
mode = vinfo->mode;
}
}
@@ -129,123 +104,46 @@ EXPORT_SYMBOL(get_current_vmode);
const char *get_name_by_vmode(enum vmode_e mode)
{
const char *str = NULL;
const struct vinfo_s *info = NULL;
const struct vinfo_s *vinfo = NULL;
struct vout_module_s *p_module = NULL;
if (vout_module.curr_vout_server) {
if (vout_module.curr_vout_server->op.get_vinfo) {
info = vout_module.curr_vout_server->op.get_vinfo();
str = info->name;
}
p_module = vout_func_get_vout_module();
if (!IS_ERR_OR_NULL(p_module->curr_vout_server)) {
if (p_module->curr_vout_server->op.get_vinfo)
vinfo = p_module->curr_vout_server->op.get_vinfo();
}
if (info == NULL)
info = get_invalid_vinfo();
str = info->name;
if (vinfo == NULL)
vinfo = get_invalid_vinfo(1);
str = vinfo->name;
return str;
}
EXPORT_SYMBOL(get_name_by_vmode);
/* fps = 9600/duration/100 hz */
static int vsource_fps_table[][2] = {
/* duration fps */
{1600, 6000,},
{1601, 5994,},
{1602, 5994,},
{1920, 5000,},
{3200, 3000,},
{3203, 2997,},
{3840, 2500,},
{4000, 2400,},
{4004, 2397,},
};
int get_vsource_fps(int duration)
/*
* interface export to client who want to set current vmode.
*/
int set_current_vmode(enum vmode_e mode)
{
int i;
int fps = 6000;
for (i = 0; i < 9; i++) {
if (duration == vsource_fps_table[i][0]) {
fps = vsource_fps_table[i][1];
break;
}
}
return fps;
return vout_func_set_current_vmode(1, mode);
}
EXPORT_SYMBOL(set_current_vmode);
static struct vframe_match_s vframe_match_table_1[] = {
{5000, 5000, 50, 1},
{2500, 5000, 50, 1},
{6000, 6000, 60, 1},
{3000, 6000, 60, 1},
{2400, 6000, 60, 1},
{2397, 5994, 5994, 100},
{2997, 5994, 5994, 100},
{5994, 5994, 5994, 100},
{0, 6000, 60, 1},
};
static struct vframe_match_s vframe_match_table_2[] = {
{5000, 5000, 50, 1},
{2500, 5000, 50, 1},
{6000, 6000, 60, 1},
{3000, 6000, 60, 1},
{2400, 4800, 48, 1},
{2397, 5994, 5994, 100},
{2997, 5994, 5994, 100},
{5994, 5994, 5994, 100},
{0, 6000, 60, 1},
};
struct vframe_match_s *get_vframe_match(int duration, int fr_policy)
/*
*interface export to client who want to set current vmode.
*/
enum vmode_e validate_vmode(char *name)
{
int i, n, fps;
struct vframe_match_s *vtable;
fps = get_vsource_fps(duration);
switch (fr_policy) {
case 1:
vtable = vframe_match_table_1;
n = ARRAY_SIZE(vframe_match_table_1);
break;
case 2:
vtable = vframe_match_table_2;
n = ARRAY_SIZE(vframe_match_table_2);
break;
default:
VOUTPR("%s: fr_auto_policy = %d, disabled\n",
__func__, fr_policy);
return 0;
}
for (i = 0; i < n; i++) {
if (fps == vtable[i].fps)
break;
}
VOUTPR("%s: policy = %d, duration = %d, fps = %d, frame_rate = %d\n",
__func__, fr_policy, duration, fps, vtable[i].frame_rate);
return &vtable[i];
return vout_func_validate_vmode(1, name);
}
EXPORT_SYMBOL(get_vframe_match);
EXPORT_SYMBOL(validate_vmode);
/*
*interface export to client who want to notify about source frame rate.
*/
int set_vframe_rate_hint(int duration)
{
int r = -1;
struct vout_server_s *p_server = vout_module.curr_vout_server;
if (p_server) {
if ((p_server->op.set_vframe_rate_hint != NULL) &&
(p_server->op.set_vframe_rate_hint(duration) == 0)) {
return 0;
}
}
return r;
return vout_func_set_vframe_rate_hint(1, duration);
}
EXPORT_SYMBOL(set_vframe_rate_hint);
@@ -254,17 +152,7 @@ EXPORT_SYMBOL(set_vframe_rate_hint);
*/
int set_vframe_rate_end_hint(void)
{
int ret = -1;
struct vout_server_s *p_server = vout_module.curr_vout_server;
if (p_server) {
if ((p_server->op.set_vframe_rate_end_hint != NULL) &&
(p_server->op.set_vframe_rate_end_hint() == 0)) {
return 0;
}
}
return ret;
return vout_func_set_vframe_rate_end_hint(1);
}
EXPORT_SYMBOL(set_vframe_rate_end_hint);
@@ -273,17 +161,7 @@ EXPORT_SYMBOL(set_vframe_rate_end_hint);
*/
int set_vframe_rate_policy(int policy)
{
int ret = -1;
struct vout_server_s *p_server = vout_module.curr_vout_server;
if (p_server) {
if ((p_server->op.set_vframe_rate_policy != NULL) &&
(p_server->op.set_vframe_rate_policy(policy) == 0)) {
return 0;
}
}
return ret;
return vout_func_set_vframe_rate_policy(1, policy);
}
EXPORT_SYMBOL(set_vframe_rate_policy);
@@ -292,17 +170,7 @@ EXPORT_SYMBOL(set_vframe_rate_policy);
*/
int get_vframe_rate_policy(void)
{
int ret = -1;
struct vout_server_s *p_server = vout_module.curr_vout_server;
if (p_server) {
if (p_server->op.get_vframe_rate_policy != NULL) {
ret = p_server->op.get_vframe_rate_policy();
return ret;
}
}
return ret;
return vout_func_get_vframe_rate_policy(1);
}
EXPORT_SYMBOL(get_vframe_rate_policy);
@@ -317,7 +185,6 @@ void wakeup_early_suspend_proc(void)
int vout_suspend(void)
{
int ret = 0;
struct vout_server_s *p_server = vout_module.curr_vout_server;
#ifdef CONFIG_SCREEN_ON_EARLY
wake_up_flag = 0;
@@ -332,101 +199,23 @@ int vout_suspend(void)
wake_up_flag = 0;
#endif
mutex_lock(&vout_mutex);
if (p_server) {
if (p_server->op.vout_suspend)
ret = p_server->op.vout_suspend();
}
mutex_unlock(&vout_mutex);
ret = vout_func_vout_suspend(1);
return ret;
}
EXPORT_SYMBOL(vout_suspend);
int vout_resume(void)
{
struct vout_server_s *p_server = vout_module.curr_vout_server;
mutex_lock(&vout_mutex);
if (p_server) {
if (p_server->op.vout_resume) {
/* ignore error when resume. */
p_server->op.vout_resume();
}
}
mutex_unlock(&vout_mutex);
return 0;
return vout_func_vout_resume(1);
}
EXPORT_SYMBOL(vout_resume);
/*
* interface export to client who want to set current vmode.
*/
int set_current_vmode(enum vmode_e mode)
{
int ret = -1;
struct vout_server_s *p_server;
mutex_lock(&vout_mutex);
list_for_each_entry(p_server, &vout_module.vout_server_list, list) {
if (p_server->op.vmode_is_supported == NULL) {
p_server->op.disable(mode);
continue;
}
if (p_server->op.vmode_is_supported(mode) == true) {
vout_module.curr_vout_server = p_server;
ret = p_server->op.set_vmode(mode);
/* break; do not exit , should disable other modules */
} else
p_server->op.disable(mode);
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(set_current_vmode);
/*
*interface export to client who want to set current vmode.
*/
enum vmode_e validate_vmode(char *name)
{
enum vmode_e ret = VMODE_MAX;
struct vout_server_s *p_server;
mutex_lock(&vout_mutex);
list_for_each_entry(p_server, &vout_module.vout_server_list, list) {
if (p_server->op.validate_vmode)
ret = p_server->op.validate_vmode(name);
if (ret != VMODE_MAX) /* valid vmode find. */
break;
}
mutex_unlock(&vout_mutex);
return ret;
}
EXPORT_SYMBOL(validate_vmode);
/*
*interface export to client who want to shutdown.
*/
int vout_shutdown(void)
{
int ret = -1;
struct vout_server_s *p_server;
list_for_each_entry(p_server, &vout_module.vout_server_list, list) {
if (p_server->op.vout_shutdown)
ret = p_server->op.vout_shutdown();
}
return ret;
return vout_func_vout_shutdown(1);
}
EXPORT_SYMBOL(vout_shutdown);
@@ -436,64 +225,14 @@ EXPORT_SYMBOL(vout_shutdown);
*we can ensure TVMOD SET MODULE independent with these two function.
*/
int vout_register_server(struct vout_server_s *mem_server)
{
struct list_head *p_iter;
struct vout_server_s *p_server;
if (mem_server == NULL) {
VOUTERR("%s: server is NULL\n", __func__);
return -1;
}
VOUTPR("%s\n", __func__);
mutex_lock(&vout_mutex);
list_for_each(p_iter, &vout_module.vout_server_list) {
p_server = list_entry(p_iter, struct vout_server_s, list);
if (p_server->name && mem_server->name &&
strcmp(p_server->name, mem_server->name) == 0) {
/* vout server already registered. */
mutex_unlock(&vout_mutex);
return -1;
}
}
list_add(&mem_server->list, &vout_module.vout_server_list);
mutex_unlock(&vout_mutex);
return 0;
return vout_func_vout_register_server(1, mem_server);
}
EXPORT_SYMBOL(vout_register_server);
int vout_unregister_server(struct vout_server_s *mem_server)
{
struct vout_server_s *p_server;
if (mem_server == NULL) {
VOUTERR("%s: server is NULL\n", __func__);
return -1;
}
mutex_lock(&vout_mutex);
list_for_each_entry(p_server, &vout_module.vout_server_list, list) {
if (p_server->name && mem_server->name &&
strcmp(p_server->name, mem_server->name) == 0) {
/*
* We will not move current vout server pointer
* automatically if current vout server pointer
* is the one which will be deleted next.
* So you should change current vout server
* first then remove it
*/
if (vout_module.curr_vout_server == p_server)
vout_module.curr_vout_server = NULL;
list_del(&mem_server->list);
mutex_unlock(&vout_mutex);
return 0;
}
}
mutex_unlock(&vout_mutex);
return 0;
return vout_func_vout_unregister_server(1, mem_server);
}
EXPORT_SYMBOL(vout_unregister_server);

View File

@@ -38,12 +38,9 @@
/* Amlogic Headers */
#include <linux/amlogic/media/vout/vout_notify.h>
#ifdef CONFIG_AMLOGIC_HDMITX
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
#endif
/* Local Headers */
#include "vout_serve.h"
#include "vout_func.h"
#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
#include <linux/amlogic/pm.h>
@@ -60,7 +57,7 @@ static int early_resume_flag;
#define VMODE_NAME_LEN_MAX 64
static struct class *vout_class;
static DEFINE_MUTEX(vout_mutex);
static DEFINE_MUTEX(vout_serve_mutex);
static char vout_mode_uboot[VMODE_NAME_LEN_MAX] __nosavedata;
static char vout_mode[VMODE_NAME_LEN_MAX] __nosavedata;
static char local_name[VMODE_NAME_LEN_MAX] = {0};
@@ -87,13 +84,95 @@ static const unsigned int vout_cable[] = {
EXTCON_NONE,
};
struct vout_cdev_s {
dev_t devno;
struct cdev cdev;
struct device *dev;
static struct vout_cdev_s *vout_cdev;
/* **********************************************************
* null display support
* **********************************************************
*/
static struct vinfo_s nulldisp_vinfo = {
.name = "null",
.mode = VMODE_NULL,
.width = 1920,
.height = 1080,
.field_height = 1080,
.aspect_ratio_num = 16,
.aspect_ratio_den = 9,
.sync_duration_num = 60,
.sync_duration_den = 1,
.video_clk = 148500000,
.htotal = 2200,
.vtotal = 1125,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
};
static struct vout_cdev_s *vout_cdev;
static struct vinfo_s *nulldisp_get_current_info(void)
{
return &nulldisp_vinfo;
}
static int nulldisp_set_current_vmode(enum vmode_e mode)
{
return 0;
}
static enum vmode_e nulldisp_validate_vmode(char *name)
{
if (strncmp(nulldisp_vinfo.name, name,
strlen(nulldisp_vinfo.name)) == 0) {
return nulldisp_vinfo.mode;
}
return VMODE_MAX;
}
static int nulldisp_vmode_is_supported(enum vmode_e mode)
{
if (nulldisp_vinfo.mode == mode)
return true;
return false;
}
static int nulldisp_disable(enum vmode_e cur_vmod)
{
return 0;
}
static int nulldisp_vout_state;
static int nulldisp_vout_set_state(int bit)
{
nulldisp_vout_state |= (1 << bit);
return 0;
}
static int nulldisp_vout_clr_state(int bit)
{
nulldisp_vout_state &= ~(1 << bit);
return 0;
}
static int nulldisp_vout_get_state(void)
{
return nulldisp_vout_state;
}
static struct vout_server_s nulldisp_vout_server = {
.name = "nulldisp_vout_server",
.op = {
.get_vinfo = nulldisp_get_current_info,
.set_vmode = nulldisp_set_current_vmode,
.validate_vmode = nulldisp_validate_vmode,
.vmode_is_supported = nulldisp_vmode_is_supported,
.disable = nulldisp_disable,
.set_state = nulldisp_vout_set_state,
.clr_state = nulldisp_vout_clr_state,
.get_state = nulldisp_vout_get_state,
},
};
/* ********************************************************** */
char *get_vout_mode_internal(void)
{
@@ -249,11 +328,11 @@ static ssize_t vout_mode_store(struct class *class,
{
char mode[64];
mutex_lock(&vout_mutex);
mutex_lock(&vout_serve_mutex);
tvout_monitor_flag = 0;
snprintf(mode, VMODE_NAME_LEN_MAX, "%s", buf);
set_vout_mode(mode);
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
return count;
}
@@ -269,10 +348,10 @@ static ssize_t vout_axis_show(struct class *class,
static ssize_t vout_axis_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
mutex_lock(&vout_mutex);
mutex_lock(&vout_serve_mutex);
snprintf(vout_axis, 64, "%s", buf);
set_vout_axis(vout_axis);
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
return count;
}
@@ -294,17 +373,17 @@ static ssize_t vout_fr_policy_store(struct class *class,
int policy;
int ret = 0;
mutex_lock(&vout_mutex);
mutex_lock(&vout_serve_mutex);
ret = kstrtoint(buf, 10, &policy);
if (ret) {
pr_info("%s: invalid data\n", __func__);
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
return -EINVAL;
}
ret = set_vframe_rate_policy(policy);
if (ret)
pr_info("%s: %d failed\n", __func__, policy);
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
return count;
}
@@ -398,11 +477,13 @@ static int vout_attr_create(void)
/* create vout class attr files */
for (i = 0; i < ARRAY_SIZE(vout_class_attrs); i++) {
if (class_create_file(vout_class, &vout_class_attrs[i])) {
VOUTERR("create attribute %s fail\n",
VOUTERR("create vout attribute %s fail\n",
vout_class_attrs[i].attr.name);
}
}
VOUTPR("create vout attribute OK\n");
return ret;
}
@@ -523,7 +604,7 @@ static int vout_fops_create(void)
ret = alloc_chrdev_region(&vout_cdev->devno, 0, 1, VOUT_CDEV_NAME);
if (ret < 0) {
VOUTERR("failed to alloc devno\n");
VOUTERR("failed to alloc vout devno\n");
goto vout_fops_err1;
}
@@ -531,7 +612,7 @@ static int vout_fops_create(void)
vout_cdev->cdev.owner = THIS_MODULE;
ret = cdev_add(&vout_cdev->cdev, vout_cdev->devno, 1);
if (ret) {
VOUTERR("failed to add cdev\n");
VOUTERR("failed to add vout cdev\n");
goto vout_fops_err2;
}
@@ -539,7 +620,7 @@ static int vout_fops_create(void)
NULL, VOUT_CDEV_NAME);
if (IS_ERR(vout_cdev->dev)) {
ret = PTR_ERR(vout_cdev->dev);
VOUTERR("failed to create device: %d\n", ret);
VOUTERR("failed to create vout device: %d\n", ret);
goto vout_fops_err3;
}
@@ -677,9 +758,7 @@ static int refresh_tvout_mode(void)
if (tvout_monitor_flag == 0)
return 0;
#ifdef CONFIG_AMLOGIC_HDMITX
hpd_state = get_hpd_state();
#endif
hpd_state = vout_get_hpd_state();
if (hpd_state) {
cur_vmode = validate_vmode(hdmimode);
cur_mode_str = hdmimode;
@@ -714,9 +793,9 @@ static void aml_tvout_mode_work(struct work_struct *work)
return;
}
mutex_lock(&vout_mutex);
mutex_lock(&vout_serve_mutex);
refresh_tvout_mode();
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
if (tvout_monitor_flag)
schedule_delayed_work(&tvout_mode_work, 1*HZ/2);
@@ -734,9 +813,9 @@ static void aml_tvout_mode_monitor(void)
tvout_monitor_flag = 1;
INIT_DELAYED_WORK(&tvout_mode_work, aml_tvout_mode_work);
mutex_lock(&vout_mutex);
mutex_lock(&vout_serve_mutex);
refresh_tvout_mode();
mutex_unlock(&vout_mutex);
mutex_unlock(&vout_serve_mutex);
schedule_delayed_work(&tvout_mode_work, 1*HZ/2);
}
@@ -749,7 +828,7 @@ static void aml_vout_extcon_register(struct platform_device *pdev)
/*set display mode*/
edev = extcon_dev_allocate(vout_cable);
if (IS_ERR(edev)) {
VOUTERR("failed to allocate extcon setmode\n");
VOUTERR("failed to allocate vout extcon setmode\n");
return;
}
@@ -758,7 +837,7 @@ static void aml_vout_extcon_register(struct platform_device *pdev)
dev_set_name(&edev->dev, "setmode");
ret = extcon_dev_register(edev);
if (ret) {
VOUTERR("failed to register extcon setmode\n");
VOUTERR("failed to register vout extcon setmode\n");
return;
}
vout_excton_setmode = edev;
@@ -786,16 +865,12 @@ static int aml_vout_probe(struct platform_device *pdev)
register_early_suspend(&early_suspend);
#endif
set_vout_init_mode();
vout_class = NULL;
ret = vout_attr_create();
ret = vout_fops_create();
if (ret == 0)
VOUTPR("create vout attribute OK\n");
else
VOUTERR("create vout attribute FAILED\n");
vout_register_server(&nulldisp_vout_server);
set_vout_init_mode();
aml_vout_extcon_register(pdev);
aml_tvout_mode_monitor();
@@ -813,6 +888,7 @@ static int aml_vout_remove(struct platform_device *pdev)
aml_vout_extcon_free();
vout_attr_remove();
vout_fops_remove();
vout_unregister_server(&nulldisp_vout_server);
return 0;
}

View File

@@ -1,27 +0,0 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout_serve.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 _VOUT_SERVE_H_
#define _VOUT_SERVE_H_
#include <stdarg.h>
#include <linux/printk.h>
#define VOUTPR(fmt, args...) pr_info("vout: "fmt"", ## args)
#define VOUTERR(fmt, args...) pr_err("vout: error: "fmt"", ## args)
#endif

View File

@@ -263,8 +263,6 @@ int get_video0_frame_info(struct vframe_s *vf);
#define AMVIDEO_UPDATE_OSD_MODE 0x00000001
extern enum vmode_e get_logo_vmode(void);
int query_video_status(int type, int *value);
int get_video0_frame_info(struct vframe_s *vf);
int amvideo_notifier_call_chain(unsigned long val, void *v);

View File

@@ -425,6 +425,10 @@ struct aml_lcd_drv_s {
struct lcd_config_s *lcd_config;
struct vinfo_s *lcd_info;
struct class *lcd_debug_class;
struct vout_server_s *vout_server;
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
struct vout_server_s *vout2_server;
#endif
int fr_auto_policy;
struct lcd_duration_s std_duration;

View File

@@ -35,9 +35,9 @@ enum vmode_e {
};
enum viu_mux_e {
VIU_MUX_ENCI = 0,
VIU_MUX_ENCL = 0,
VIU_MUX_ENCI,
VIU_MUX_ENCP,
VIU_MUX_ENCL,
VIU_MUX_MAX,
};

View File

@@ -39,6 +39,9 @@ struct vout_op_s {
enum vmode_e (*validate_vmode)(char *);
int (*vmode_is_supported)(enum vmode_e);
int (*disable)(enum vmode_e);
int (*set_state)(int);
int (*clr_state)(int);
int (*get_state)(void);
int (*set_vframe_rate_hint)(int);
int (*set_vframe_rate_end_hint)(void);
int (*set_vframe_rate_policy)(int);
@@ -61,27 +64,40 @@ struct vout_module_s {
extern int vout_register_client(struct notifier_block *p);
extern int vout_unregister_client(struct notifier_block *p);
extern int vout_notifier_call_chain(unsigned int long, void *p);
extern int vout_register_server(struct vout_server_s *p);
extern int vout_unregister_server(struct vout_server_s *p);
extern int vout_notifier_call_chain(unsigned int long, void *p);
extern struct vinfo_s *get_current_vinfo(void);
extern enum vmode_e get_current_vmode(void);
extern int set_current_vmode(enum vmode_e);
extern enum vmode_e validate_vmode(char *p);
extern int get_vsource_fps(int duration);
extern int set_vframe_rate_hint(int duration);
extern int set_vframe_rate_end_hint(void);
extern int set_vframe_rate_policy(int pol);
extern int get_vframe_rate_policy(void);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
extern int vout2_register_client(struct notifier_block *p);
extern int vout2_unregister_client(struct notifier_block *p);
extern int vout2_notifier_call_chain(unsigned int long, void *p);
extern int vout2_register_server(struct vout_server_s *p);
extern int vout2_unregister_server(struct vout_server_s *p);
extern struct vinfo_s *get_current_vinfo2(void);
extern enum vmode_e get_current_vmode2(void);
extern int set_vframe2_rate_hint(int duration);
extern int set_vframe2_rate_end_hint(void);
extern int set_vframe2_rate_policy(int pol);
extern int get_vframe2_rate_policy(void);
#endif
extern int vout_get_vsource_fps(int duration);
/* vdac ctrl,adc/dac ref signal,cvbs out signal
* module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
*/
extern void vdac_enable(bool on, unsigned int module_sel);
extern int vout_suspend(void);
extern int vout_resume(void);
extern int vout_shutdown(void);
#define VOUT_EVENT_MODE_CHANGE_PRE 0x00010000
#define VOUT_EVENT_MODE_CHANGE 0x00020000
@@ -100,11 +116,7 @@ extern int vout_shutdown(void);
_IOW(VOUT_IOC_TYPE, VOUT_IOC_NR_SET_VINFO, struct vinfo_base_s)
/* ******************************** */
extern void update_vout_mode(char *name);
extern char *get_vout_mode_internal(void);
extern char *get_vout_mode_uboot(void);
extern enum vmode_e get_logo_vmode(void);
#endif /* _VOUT_NOTIFY_H_ */