mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
16
MAINTAINERS
16
MAINTAINERS
@@ -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/*
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/* **************************************************
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/* ************************************************** *
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
214
drivers/amlogic/media/vout/vout_serve/vout2_notify.c
Normal file
214
drivers/amlogic/media/vout/vout_serve/vout2_notify.c
Normal 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);
|
||||
821
drivers/amlogic/media/vout/vout_serve/vout2_serve.c
Normal file
821
drivers/amlogic/media/vout/vout_serve/vout2_serve.c
Normal 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(¶ms, " ");
|
||||
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");
|
||||
549
drivers/amlogic/media/vout/vout_serve/vout_func.c
Normal file
549
drivers/amlogic/media/vout/vout_serve/vout_func.c
Normal 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);
|
||||
83
drivers/amlogic/media/vout/vout_serve/vout_func.h
Normal file
83
drivers/amlogic/media/vout/vout_serve/vout_func.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user