vout: add dummy_lcd driver support [1/1]

PD#TV-6485

Problem:
need add dummy_lcd for encp

Solution:
add dummy_lcd driver base on encp

Verify:
x301

Change-Id: Id6e289bb3fc95ff94455f31ae2dcd94985baf9ec
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2019-06-06 10:32:39 +08:00
committed by Tao Zeng
parent 775fc0ac6f
commit a425e81dcf
16 changed files with 1022 additions and 110 deletions

View File

@@ -14367,6 +14367,8 @@ 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
F: drivers/amlogic/media/vout/vout_serve/vout_reg.h
F: drivers/amlogic/media/vout/vout_serve/dummy_lcd.c
AMLOGIC GPIO IRQ
M: Xingyu Chen <xingyu.chen@amlogic.com>

View File

@@ -247,6 +247,27 @@
fr_auto_policy = <0>;
};
vout2 {
compatible = "amlogic, vout2";
dev_name = "vout";
status = "disabled";
clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>,
<&clkc CLKID_VPU_CLKC_MUX>;
clock-names = "vpu_clkc0",
"vpu_clkc";
};
dummy_lcd {
compatible = "amlogic, dummy_lcd";
status = "disabled";
clocks = <&clkc CLKID_VCLK2_ENCP
&clkc CLKID_VCLK2_VENCP0
&clkc CLKID_VCLK2_VENCP1>;
clock-names = "encp_top_gate",
"encp_int_gate0",
"encp_int_gate1";
};
/* Audio Related start */
pdm_codec:dummy {
#sound-dai-cells = <0>;

View File

@@ -242,6 +242,27 @@
fr_auto_policy = <0>;
};
vout2 {
compatible = "amlogic, vout2";
dev_name = "vout";
status = "disabled";
clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>,
<&clkc CLKID_VPU_CLKC_MUX>;
clock-names = "vpu_clkc0",
"vpu_clkc";
};
dummy_lcd {
compatible = "amlogic, dummy_lcd";
status = "disabled";
clocks = <&clkc CLKID_VCLK2_ENCP
&clkc CLKID_VCLK2_VENCP0
&clkc CLKID_VCLK2_VENCP1>;
clock-names = "encp_top_gate",
"encp_int_gate0",
"encp_int_gate1";
};
/* Audio Related start */
pdm_codec:dummy {
#sound-dai-cells = <0>;

View File

@@ -244,6 +244,27 @@
fr_auto_policy = <0>;
};
vout2 {
compatible = "amlogic, vout2";
dev_name = "vout";
status = "disabled";
clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>,
<&clkc CLKID_VPU_CLKC_MUX>;
clock-names = "vpu_clkc0",
"vpu_clkc";
};
dummy_lcd {
compatible = "amlogic, dummy_lcd";
status = "disabled";
clocks = <&clkc CLKID_VCLK2_ENCP
&clkc CLKID_VCLK2_VENCP0
&clkc CLKID_VCLK2_VENCP1>;
clock-names = "encp_top_gate",
"encp_int_gate0",
"encp_int_gate1";
};
/* Audio Related start */
pdm_codec:dummy {
#sound-dai-cells = <0>;

View File

@@ -238,6 +238,27 @@
fr_auto_policy = <0>;
};
vout2 {
compatible = "amlogic, vout2";
dev_name = "vout";
status = "disabled";
clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>,
<&clkc CLKID_VPU_CLKC_MUX>;
clock-names = "vpu_clkc0",
"vpu_clkc";
};
dummy_lcd {
compatible = "amlogic, dummy_lcd";
status = "disabled";
clocks = <&clkc CLKID_VCLK2_ENCP
&clkc CLKID_VCLK2_VENCP0
&clkc CLKID_VCLK2_VENCP1>;
clock-names = "encp_top_gate",
"encp_int_gate0",
"encp_int_gate1";
};
/* Audio Related start */
pdm_codec:dummy {
#sound-dai-cells = <0>;

View File

@@ -1065,3 +1065,32 @@ void lcd_if_enable_retry(struct lcd_config_s *pconf)
pconf->retry_enable_cnt = 0;
}
void lcd_vout_notify_mode_change_pre(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
if (lcd_drv->viu_sel == 1) {
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
&lcd_drv->lcd_info->mode);
} else if (lcd_drv->viu_sel == 2) {
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
&lcd_drv->lcd_info->mode);
#endif
}
}
void lcd_vout_notify_mode_change(void)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
if (lcd_drv->viu_sel == 1) {
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
} else if (lcd_drv->viu_sel == 2) {
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
#endif
}
}

View File

@@ -76,6 +76,8 @@ extern int lcd_vmode_change(struct lcd_config_s *pconf);
extern void lcd_clk_change(struct lcd_config_s *pconf);
extern void lcd_venc_change(struct lcd_config_s *pconf);
extern void lcd_if_enable_retry(struct lcd_config_s *pconf);
extern void lcd_vout_notify_mode_change_pre(void);
extern void lcd_vout_notify_mode_change(void);
/* lcd phy */
extern void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status);

View File

@@ -1539,8 +1539,7 @@ static void lcd_vinfo_update(void)
vinfo->htotal = pconf->lcd_basic.h_period;
vinfo->vtotal = pconf->lcd_basic.v_period;
}
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
}
static void lcd_debug_config_update(void)
@@ -1558,8 +1557,8 @@ static void lcd_debug_clk_change(unsigned int pclk)
struct lcd_config_s *pconf;
unsigned int sync_duration;
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change_pre();
pconf = lcd_drv->lcd_config;
sync_duration = pclk / pconf->lcd_basic.h_period;
sync_duration = sync_duration * 100 / pconf->lcd_basic.v_period;
@@ -1589,8 +1588,7 @@ static void lcd_debug_clk_change(unsigned int pclk)
break;
}
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
}
static void lcd_power_interface_ctrl(int state)

View File

@@ -197,8 +197,7 @@ static int lcd_framerate_automation_set_mode(void)
lcd_tablet_config_post_update(lcd_drv->lcd_config);
lcd_venc_change(lcd_drv->lcd_config);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
return 0;
}
@@ -1280,8 +1279,8 @@ static void lcd_set_vinfo(unsigned int sync_duration)
LCDPR("%s: sync_duration=%d\n", __func__, sync_duration);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change_pre();
/* update vinfo */
lcd_drv->lcd_info->sync_duration_num = sync_duration;
lcd_drv->lcd_info->sync_duration_den = 100;
@@ -1298,8 +1297,7 @@ static void lcd_set_vinfo(unsigned int sync_duration)
lcd_tablet_config_post_update(lcd_drv->lcd_config);
lcd_venc_change(lcd_drv->lcd_config);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
}
static int lcd_frame_rate_adjust_notifier(struct notifier_block *nb,

View File

@@ -464,8 +464,7 @@ static int lcd_framerate_automation_set_mode(void)
if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE)
lcd_vbyone_wait_stable();
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
return 0;
}
@@ -1493,8 +1492,8 @@ static void lcd_set_vinfo(unsigned int sync_duration)
LCDPR("%s: sync_duration=%d\n", __func__, sync_duration);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change_pre();
/* update vinfo */
lcd_drv->lcd_info->sync_duration_num = sync_duration;
lcd_drv->lcd_info->sync_duration_den = 100;
@@ -1514,8 +1513,7 @@ static void lcd_set_vinfo(unsigned int sync_duration)
if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE)
lcd_vbyone_wait_stable();
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_drv->lcd_info->mode);
lcd_vout_notify_mode_change();
}
static int lcd_frame_rate_adjust_notifier(struct notifier_block *nb,

View File

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

View File

@@ -0,0 +1,661 @@
/*
* drivers/amlogic/media/vout/vout_serve/dummy_lcd.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/interrupt.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/of.h>
#include <linux/clk.h>
#ifdef CONFIG_AMLOGIC_VPU
#include <linux/amlogic/media/vpu/vpu.h>
#endif
#include <linux/amlogic/media/vout/vout_notify.h>
/* Local Headers */
#include "vout_func.h"
#include "vout_reg.h"
struct dummy_lcd_driver_s {
struct device *dev;
unsigned char status;
unsigned char viu_sel;
unsigned char clk_gate_state;
struct clk *encp_top_gate;
struct clk *encp_int_gate0;
struct clk *encp_int_gate1;
};
static struct dummy_lcd_driver_s *dummy_lcd_drv;
/* **********************************************************
* dummy_lcd support
* **********************************************************
*/
static struct vinfo_s dummy_lcd_vinfo = {
.name = "dummy_panel",
.mode = VMODE_DUMMY_LCD,
.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,
.fr_adj_type = VOUT_FR_ADJ_NONE,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_ENCP,
.vout_device = NULL,
};
static void dummy_lcd_venc_set(void)
{
unsigned int temp;
VOUTPR("%s\n", __func__);
vout_vcbus_write(ENCP_VIDEO_EN, 0);
vout_vcbus_write(ENCP_VIDEO_MODE, 0x8000);
vout_vcbus_write(ENCP_VIDEO_MODE_ADV, 0x0418);
temp = vout_vcbus_read(ENCL_VIDEO_MAX_PXCNT);
vout_vcbus_write(ENCP_VIDEO_MAX_PXCNT, temp);
temp = vout_vcbus_read(ENCL_VIDEO_MAX_LNCNT);
vout_vcbus_write(ENCP_VIDEO_MAX_LNCNT, temp);
temp = vout_vcbus_read(ENCL_VIDEO_HAVON_BEGIN);
vout_vcbus_write(ENCP_VIDEO_HAVON_BEGIN, temp);
temp = vout_vcbus_read(ENCL_VIDEO_HAVON_END);
vout_vcbus_write(ENCP_VIDEO_HAVON_END, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VAVON_BLINE);
vout_vcbus_write(ENCP_VIDEO_VAVON_BLINE, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VAVON_ELINE);
vout_vcbus_write(ENCP_VIDEO_VAVON_ELINE, temp);
temp = vout_vcbus_read(ENCL_VIDEO_HSO_BEGIN);
vout_vcbus_write(ENCP_VIDEO_HSO_BEGIN, temp);
temp = vout_vcbus_read(ENCL_VIDEO_HSO_END);
vout_vcbus_write(ENCP_VIDEO_HSO_END, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VSO_BEGIN);
vout_vcbus_write(ENCP_VIDEO_VSO_BEGIN, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VSO_END);
vout_vcbus_write(ENCP_VIDEO_VSO_END, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VSO_BLINE);
vout_vcbus_write(ENCP_VIDEO_VSO_BLINE, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VSO_ELINE);
vout_vcbus_write(ENCP_VIDEO_VSO_ELINE, temp);
temp = vout_vcbus_read(ENCL_VIDEO_VSO_ELINE);
vout_vcbus_write(ENCP_VIDEO_RGBIN_CTRL, temp);
vout_vcbus_write(ENCP_VIDEO_EN, 1);
}
static void dummy_lcd_clk_ctrl(int flag)
{
unsigned int temp;
if (flag) {
temp = vout_hiu_getb(HHI_VIID_CLK_DIV, ENCL_CLK_SEL, 4);
vout_hiu_setb(HHI_VID_CLK_DIV, temp, ENCP_CLK_SEL, 4);
vout_hiu_setb(HHI_VID_CLK_CNTL2, 1, ENCP_GATE_VCLK, 1);
} else {
vout_hiu_setb(HHI_VID_CLK_CNTL2, 0, ENCP_GATE_VCLK, 1);
}
}
static void dummy_lcd_clk_gate_switch(int flag)
{
if (flag) {
if (dummy_lcd_drv->clk_gate_state)
return;
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_top_gate))
VOUTERR("%s: encp_top_gate\n", __func__);
else
clk_prepare_enable(dummy_lcd_drv->encp_top_gate);
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate0))
VOUTERR("%s: encp_int_gate0\n", __func__);
else
clk_prepare_enable(dummy_lcd_drv->encp_int_gate0);
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate1))
VOUTERR("%s: encp_int_gate1\n", __func__);
else
clk_prepare_enable(dummy_lcd_drv->encp_int_gate1);
dummy_lcd_drv->clk_gate_state = 1;
} else {
if (dummy_lcd_drv->clk_gate_state == 0)
return;
dummy_lcd_drv->clk_gate_state = 0;
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate0))
VOUTERR("%s: encp_int_gate0\n", __func__);
else
clk_disable_unprepare(dummy_lcd_drv->encp_int_gate0);
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate1))
VOUTERR("%s: encp_int_gate1\n", __func__);
else
clk_disable_unprepare(dummy_lcd_drv->encp_int_gate1);
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_top_gate))
VOUTERR("%s: encp_top_gate\n", __func__);
else
clk_disable_unprepare(dummy_lcd_drv->encp_top_gate);
}
}
static void dummy_lcd_vinfo_update(void)
{
unsigned int lcd_viu_sel = 0;
const struct vinfo_s *vinfo = NULL;
if (dummy_lcd_drv->viu_sel == 1) {
vinfo = get_current_vinfo2();
lcd_viu_sel = 2;
} else if (dummy_lcd_drv->viu_sel == 2) {
vinfo = get_current_vinfo();
lcd_viu_sel = 1;
}
if (vinfo) {
if (vinfo->mode != VMODE_LCD) {
VOUTERR("display%d is not panel\n", lcd_viu_sel);
vinfo = NULL;
}
}
if (!vinfo)
return;
dummy_lcd_vinfo.width = vinfo->width;
dummy_lcd_vinfo.height = vinfo->height;
dummy_lcd_vinfo.field_height = vinfo->field_height;
dummy_lcd_vinfo.aspect_ratio_num = vinfo->aspect_ratio_num;
dummy_lcd_vinfo.aspect_ratio_den = vinfo->aspect_ratio_den;
dummy_lcd_vinfo.sync_duration_num = vinfo->sync_duration_num;
dummy_lcd_vinfo.sync_duration_den = vinfo->sync_duration_den;
dummy_lcd_vinfo.video_clk = vinfo->video_clk;
dummy_lcd_vinfo.htotal = vinfo->htotal;
dummy_lcd_vinfo.vtotal = vinfo->vtotal;
dummy_lcd_vinfo.viu_color_fmt = vinfo->viu_color_fmt;
}
static struct vinfo_s *dummy_lcd_get_current_info(void)
{
return &dummy_lcd_vinfo;
}
static int dummy_lcd_set_current_vmode(enum vmode_e mode)
{
dummy_lcd_vinfo_update();
#ifdef CONFIG_AMLOGIC_VPU
request_vpu_clk_vmod(dummy_lcd_vinfo.video_clk, VPU_VENCP);
switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_ON);
#endif
dummy_lcd_clk_gate_switch(1);
dummy_lcd_clk_ctrl(1);
dummy_lcd_venc_set();
dummy_lcd_drv->status = 1;
VOUTPR("%s finished\n", __func__);
return 0;
}
static enum vmode_e dummy_lcd_validate_vmode(char *name)
{
enum vmode_e vmode = VMODE_MAX;
if (strcmp(dummy_lcd_vinfo.name, name) == 0)
vmode = dummy_lcd_vinfo.mode;
return vmode;
}
static int dummy_lcd_vmode_is_supported(enum vmode_e mode)
{
if (dummy_lcd_vinfo.mode == (mode & VMODE_MODE_BIT_MASK))
return true;
return false;
}
static int dummy_lcd_disable(enum vmode_e cur_vmod)
{
dummy_lcd_drv->status = 0;
vout_vcbus_write(ENCP_VIDEO_EN, 0); /* disable encp */
dummy_lcd_clk_ctrl(0);
dummy_lcd_clk_gate_switch(0);
#ifdef CONFIG_AMLOGIC_VPU
switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_DOWN);
release_vpu_clk_vmod(VPU_VENCP);
#endif
VOUTPR("%s finished\n", __func__);
return 0;
}
#ifdef CONFIG_PM
static int dummy_lcd_lcd_suspend(void)
{
dummy_lcd_disable(VMODE_DUMMY_LCD);
return 0;
}
static int dummy_lcd_lcd_resume(void)
{
dummy_lcd_set_current_vmode(VMODE_DUMMY_LCD);
return 0;
}
#endif
static int dummy_lcd_vout_state;
static int dummy_lcd_vout_set_state(int bit)
{
dummy_lcd_vout_state |= (1 << bit);
dummy_lcd_drv->viu_sel = bit;
return 0;
}
static int dummy_lcd_vout_clr_state(int bit)
{
dummy_lcd_vout_state &= ~(1 << bit);
if (dummy_lcd_drv->viu_sel == bit)
dummy_lcd_drv->viu_sel = 0;
return 0;
}
static int dummy_lcd_vout_get_state(void)
{
return dummy_lcd_vout_state;
}
static struct vout_server_s dummy_lcd_vout_server = {
.name = "dummy_lcd_vout_server",
.op = {
.get_vinfo = dummy_lcd_get_current_info,
.set_vmode = dummy_lcd_set_current_vmode,
.validate_vmode = dummy_lcd_validate_vmode,
.vmode_is_supported = dummy_lcd_vmode_is_supported,
.disable = dummy_lcd_disable,
.set_state = dummy_lcd_vout_set_state,
.clr_state = dummy_lcd_vout_clr_state,
.get_state = dummy_lcd_vout_get_state,
.set_bist = NULL,
#ifdef CONFIG_PM
.vout_suspend = dummy_lcd_lcd_suspend,
.vout_resume = dummy_lcd_lcd_resume,
#endif
},
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct vout_server_s dummy_lcd_vout2_server = {
.name = "dummy_lcd_vout2_server",
.op = {
.get_vinfo = dummy_lcd_get_current_info,
.set_vmode = dummy_lcd_set_current_vmode,
.validate_vmode = dummy_lcd_validate_vmode,
.vmode_is_supported = dummy_lcd_vmode_is_supported,
.disable = dummy_lcd_disable,
.set_state = dummy_lcd_vout_set_state,
.clr_state = dummy_lcd_vout_clr_state,
.get_state = dummy_lcd_vout_get_state,
.set_bist = NULL,
#ifdef CONFIG_PM
.vout_suspend = dummy_lcd_lcd_suspend,
.vout_resume = dummy_lcd_lcd_resume,
#endif
},
};
#endif
static void dummy_lcd_vout_server_init(void)
{
vout_register_server(&dummy_lcd_vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_register_server(&dummy_lcd_vout2_server);
#endif
}
static void dummy_lcd_vout_server_remove(void)
{
vout_unregister_server(&dummy_lcd_vout_server);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_unregister_server(&dummy_lcd_vout2_server);
#endif
}
/* ********************************************************* */
static int dummy_lcd_vout_mode_update(void)
{
enum vmode_e mode = VMODE_DUMMY_LCD;
VOUTPR("%s\n", __func__);
if (dummy_lcd_drv->viu_sel == 1)
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
else if (dummy_lcd_drv->viu_sel == 2)
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
dummy_lcd_set_current_vmode(mode);
if (dummy_lcd_drv->viu_sel == 1)
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
else if (dummy_lcd_drv->viu_sel == 2)
vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
return 0;
}
static int dummy_lcd_vout_notify_callback(struct notifier_block *block,
unsigned long cmd, void *para)
{
const struct vinfo_s *vinfo;
switch (cmd) {
case VOUT_EVENT_MODE_CHANGE:
vinfo = get_current_vinfo();
if (!vinfo)
break;
if (vinfo->mode != VMODE_LCD)
break;
dummy_lcd_vout_mode_update();
break;
default:
break;
}
return 0;
}
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static int dummy_lcd_vout2_notify_callback(struct notifier_block *block,
unsigned long cmd, void *para)
{
const struct vinfo_s *vinfo;
switch (cmd) {
case VOUT_EVENT_MODE_CHANGE:
vinfo = get_current_vinfo2();
if (!vinfo)
break;
if (vinfo->mode != VMODE_LCD)
break;
dummy_lcd_vout_mode_update();
break;
default:
break;
}
return 0;
}
#endif
static struct notifier_block dummy_lcd_vout_notifier = {
.notifier_call = dummy_lcd_vout_notify_callback,
};
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
static struct notifier_block dummy_lcd_vout2_notifier = {
.notifier_call = dummy_lcd_vout2_notify_callback,
};
#endif
/* ********************************************************* */
static const char *dummy_lcd_debug_usage_str = {
"Usage:\n"
" echo test <index> > /sys/class/dummy_lcd/debug ; test pattern for encp\n"
" echo reg > /sys/class/dummy_lcd/debug ; dump regs for encp\n"
};
static ssize_t dummy_lcd_debug_show(struct class *class,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", dummy_lcd_debug_usage_str);
}
static unsigned int dummy_lcd_reg_dump_encp[] = {
VPU_VIU_VENC_MUX_CTRL,
ENCP_VIDEO_EN,
ENCP_VIDEO_MODE,
ENCP_VIDEO_MODE_ADV,
ENCP_VIDEO_MAX_PXCNT,
ENCP_VIDEO_MAX_LNCNT,
ENCP_VIDEO_HAVON_BEGIN,
ENCP_VIDEO_HAVON_END,
ENCP_VIDEO_VAVON_BLINE,
ENCP_VIDEO_VAVON_ELINE,
ENCP_VIDEO_HSO_BEGIN,
ENCP_VIDEO_HSO_END,
ENCP_VIDEO_VSO_BEGIN,
ENCP_VIDEO_VSO_END,
ENCP_VIDEO_VSO_BLINE,
ENCP_VIDEO_VSO_ELINE,
ENCP_VIDEO_RGBIN_CTRL,
0xffff,
};
static ssize_t dummy_lcd_debug_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
unsigned int ret;
unsigned int val, i;
switch (buf[0]) {
case 't':
ret = sscanf(buf, "test %d", &val);
if (ret == 1) {
pr_info("todo bist pattern\n");
} else {
pr_info("invalid data\n");
return -EINVAL;
}
break;
case 'r':
pr_info("dummy_lcd register dump:\n");
i = 0;
while (i < ARRAY_SIZE(dummy_lcd_reg_dump_encp)) {
if (dummy_lcd_reg_dump_encp[i] == 0xffff)
break;
pr_info("vcbus [0x%04x] = 0x%08x\n",
dummy_lcd_reg_dump_encp[i],
vout_vcbus_read(dummy_lcd_reg_dump_encp[i]));
i++;
}
break;
default:
pr_info("invalid data\n");
break;
}
return count;
}
static struct class_attribute dummy_lcd_class_attrs[] = {
__ATTR(debug, 0644,
dummy_lcd_debug_show, dummy_lcd_debug_store),
};
static struct class *debug_class;
static int dummy_lcd_creat_class(void)
{
int i;
debug_class = class_create(THIS_MODULE, "dummy_lcd");
if (IS_ERR(debug_class)) {
VOUTERR("create debug class failed\n");
return -1;
}
for (i = 0; i < ARRAY_SIZE(dummy_lcd_class_attrs); i++) {
if (class_create_file(debug_class, &dummy_lcd_class_attrs[i])) {
VOUTERR("create debug attribute %s failed\n",
dummy_lcd_class_attrs[i].attr.name);
}
}
return 0;
}
static int dummy_lcd_remove_class(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(dummy_lcd_class_attrs); i++)
class_remove_file(debug_class, &dummy_lcd_class_attrs[i]);
class_destroy(debug_class);
debug_class = NULL;
return 0;
}
/* ********************************************************* */
static void dummy_lcd_clktree_probe(void)
{
dummy_lcd_drv->clk_gate_state = 0;
dummy_lcd_drv->encp_top_gate = devm_clk_get(dummy_lcd_drv->dev,
"encp_top_gate");
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_top_gate))
VOUTERR("%s: get encp_top_gate error\n", __func__);
dummy_lcd_drv->encp_int_gate0 = devm_clk_get(dummy_lcd_drv->dev,
"encp_int_gate0");
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate0))
VOUTERR("%s: get encp_int_gate0 error\n", __func__);
dummy_lcd_drv->encp_int_gate1 = devm_clk_get(dummy_lcd_drv->dev,
"encp_int_gate1");
if (IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate1))
VOUTERR("%s: get encp_int_gate1 error\n", __func__);
}
static void dummy_lcd_clktree_remove(void)
{
if (!IS_ERR_OR_NULL(dummy_lcd_drv->encp_top_gate))
devm_clk_put(dummy_lcd_drv->dev, dummy_lcd_drv->encp_top_gate);
if (!IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate0))
devm_clk_put(dummy_lcd_drv->dev, dummy_lcd_drv->encp_int_gate0);
if (!IS_ERR_OR_NULL(dummy_lcd_drv->encp_int_gate1))
devm_clk_put(dummy_lcd_drv->dev, dummy_lcd_drv->encp_int_gate1);
}
#ifdef CONFIG_OF
static const struct of_device_id dummy_lcd_dt_match_table[] = {
{
.compatible = "amlogic, dummy_lcd",
},
{},
};
#endif
static int dummy_lcd_probe(struct platform_device *pdev)
{
dummy_lcd_drv = kzalloc(sizeof(struct dummy_lcd_driver_s), GFP_KERNEL);
if (!dummy_lcd_drv) {
VOUTERR("%s: dummy_lcd driver no enough memory\n", __func__);
return -ENOMEM;
}
dummy_lcd_drv->dev = &pdev->dev;
dummy_lcd_clktree_probe();
dummy_lcd_vout_server_init();
vout_register_client(&dummy_lcd_vout_notifier);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_register_client(&dummy_lcd_vout2_notifier);
#endif
dummy_lcd_creat_class();
VOUTPR("%s OK\n", __func__);
return 0;
}
static int dummy_lcd_remove(struct platform_device *pdev)
{
if (dummy_lcd_drv == NULL)
return 0;
dummy_lcd_remove_class();
vout_unregister_client(&dummy_lcd_vout_notifier);
#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
vout2_unregister_client(&dummy_lcd_vout2_notifier);
#endif
dummy_lcd_vout_server_remove();
dummy_lcd_clktree_remove();
kfree(dummy_lcd_drv);
dummy_lcd_drv = NULL;
VOUTPR("%s\n", __func__);
return 0;
}
static void dummy_lcd_shutdown(struct platform_device *pdev)
{
if (dummy_lcd_drv == NULL)
return;
if (dummy_lcd_drv->status)
dummy_lcd_disable(VMODE_DUMMY_LCD);
}
static struct platform_driver dummy_lcd_platform_driver = {
.probe = dummy_lcd_probe,
.remove = dummy_lcd_remove,
.shutdown = dummy_lcd_shutdown,
.driver = {
.name = "dummy_lcd",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = dummy_lcd_dt_match_table,
#endif
},
};
static int __init dummy_lcd_init(void)
{
if (platform_driver_register(&dummy_lcd_platform_driver)) {
VOUTERR("failed to register dummy_lcd driver module\n");
return -ENODEV;
}
return 0;
}
static void __exit dummy_lcd_exit(void)
{
platform_driver_unregister(&dummy_lcd_platform_driver);
}
subsys_initcall(dummy_lcd_init);
module_exit(dummy_lcd_exit);

View File

@@ -22,11 +22,11 @@
#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"
#include "vout_reg.h"
static DEFINE_MUTEX(vout_mutex);
@@ -111,24 +111,6 @@ struct vout_module_s *vout_func_get_vout2_module(void)
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)
{
@@ -239,24 +221,11 @@ void vout_func_update_viu(int index)
}
if (mux_bit < 0xff) {
vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL,
vout_vcbus_setb(VPU_VIU_VENC_MUX_CTRL,
mux_sel, mux_bit, 2);
}
if (clk_bit < 0xff)
vout_func_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1);
/* special setting for dummy mode */
if (index == 1) {
if (vinfo->mode == VMODE_DUMMY_LCD) {
/* viu1 use encl_vsync */
vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 4, 2);
vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 1, 20, 1);
vout_func_vcbus_setb(VPP_WRBAK_CTRL, 1, 11, 1);
} else {
vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 20, 1);
vout_func_vcbus_setb(VPP_WRBAK_CTRL, 0, 11, 1);
}
}
vout_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1);
#if 0
VOUTPR("%s: %d, mux_sel=%d, clk_sel=%d\n",

View File

@@ -0,0 +1,227 @@
/*
* drivers/amlogic/media/vout/vout_serve/vout_reg.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_REG_H_
#define _VOUT_REG_H_
#include <linux/amlogic/iomap.h>
/* [3: 2] cntl_viu2_sel_venc:
* 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT.
* [1: 0] cntl_viu1_sel_venc:
* 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT.
*/
#define VPU_VIU_VENC_MUX_CTRL 0x271a
/* [2] Enci_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm
* [1] Encl_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm
* [0] Encp_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm
*/
#define VPU_VENCX_CLK_CTRL 0x2785
#define VPP_POSTBLEND_H_SIZE 0x1d21
#define VPP2_POSTBLEND_H_SIZE 0x1921
#define VPP_WRBAK_CTRL 0x1df9
/* ENCL registers */
#define ENCL_VIDEO_EN 0x1ca0
#define ENCL_VIDEO_Y_SCL 0x1ca1
#define ENCL_VIDEO_PB_SCL 0x1ca2
#define ENCL_VIDEO_PR_SCL 0x1ca3
#define ENCL_VIDEO_Y_OFFST 0x1ca4
#define ENCL_VIDEO_PB_OFFST 0x1ca5
#define ENCL_VIDEO_PR_OFFST 0x1ca6
/* ----- Video mode */
#define ENCL_VIDEO_MODE 0x1ca7
#define ENCL_VIDEO_MODE_ADV 0x1ca8
/* --------------- Debug pins */
#define ENCL_DBG_PX_RST 0x1ca9
#define ENCL_DBG_LN_RST 0x1caa
#define ENCL_DBG_PX_INT 0x1cab
#define ENCL_DBG_LN_INT 0x1cac
/* ----------- Video Advanced setting */
#define ENCL_VIDEO_YFP1_HTIME 0x1cad
#define ENCL_VIDEO_YFP2_HTIME 0x1cae
#define ENCL_VIDEO_YC_DLY 0x1caf
#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
#define ENCL_VIDEO_HAVON_END 0x1cb1
#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
#define ENCL_VIDEO_HSO_END 0x1cb6
#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
#define ENCL_VIDEO_VSO_END 0x1cb8
#define ENCL_VIDEO_VSO_BLINE 0x1cb9
#define ENCL_VIDEO_VSO_ELINE 0x1cba
#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
#define ENCL_VIDEO_HOFFST 0x1cbf
#define ENCL_VIDEO_VOFFST 0x1cc0
#define ENCL_VIDEO_RGB_CTRL 0x1cc1
#define ENCL_VIDEO_FILT_CTRL 0x1cc2
#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
#define ENCL_VIDEO_MATRIX_CB 0x1cc5
#define ENCL_VIDEO_MATRIX_CR 0x1cc6
#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
#define ENCL_DACSEL_0 0x1cc9
#define ENCL_DACSEL_1 0x1cca
/* ENCP registers */
#define ENCP_VIDEO_EN 0x1b80
#define ENCP_VIDEO_SYNC_MODE 0x1b81
#define ENCP_MACV_EN 0x1b82
#define ENCP_VIDEO_Y_SCL 0x1b83
#define ENCP_VIDEO_PB_SCL 0x1b84
#define ENCP_VIDEO_PR_SCL 0x1b85
#define ENCP_VIDEO_SYNC_SCL 0x1b86
#define ENCP_VIDEO_MACV_SCL 0x1b87
#define ENCP_VIDEO_Y_OFFST 0x1b88
#define ENCP_VIDEO_PB_OFFST 0x1b89
#define ENCP_VIDEO_PR_OFFST 0x1b8a
#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
#define ENCP_VIDEO_MACV_OFFST 0x1b8c
//----- Video mode
#define ENCP_VIDEO_MODE 0x1b8d
#define ENCP_VIDEO_MODE_ADV 0x1b8e
//--------------- Debug pins
#define ENCP_DBG_PX_RST 0x1b90
#define ENCP_DBG_LN_RST 0x1b91
#define ENCP_DBG_PX_INT 0x1b92
#define ENCP_DBG_LN_INT 0x1b93
//----------- Video Advanced setting
#define ENCP_VIDEO_YFP1_HTIME 0x1b94
#define ENCP_VIDEO_YFP2_HTIME 0x1b95
#define ENCP_VIDEO_YC_DLY 0x1b96
#define ENCP_VIDEO_MAX_PXCNT 0x1b97
#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
#define ENCP_VIDEO_HSPULS_END 0x1b99
#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
#define ENCP_VIDEO_VSPULS_END 0x1b9c
#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
#define ENCP_VIDEO_EQPULS_END 0x1ba0
#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
#define ENCP_VIDEO_HAVON_END 0x1ba3
#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
#define ENCP_VIDEO_VAVON_ELINE 0x1baf
#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
#define ENCP_VIDEO_HSO_END 0x1ba8
#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
#define ENCP_VIDEO_VSO_END 0x1baa
#define ENCP_VIDEO_VSO_BLINE 0x1bab
#define ENCP_VIDEO_VSO_ELINE 0x1bac
#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
#define ENCP_VIDEO_MAX_LNCNT 0x1bae
#define ENCP_VIDEO_SY_VAL 0x1bb0
#define ENCP_VIDEO_SY2_VAL 0x1bb1
#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
#define ENCP_VIDEO_HOFFST 0x1bb5
#define ENCP_VIDEO_VOFFST 0x1bb6
#define ENCP_VIDEO_RGB_CTRL 0x1bb7
#define ENCP_VIDEO_FILT_CTRL 0x1bb8
#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
#define ENCP_VIDEO_MATRIX_CB 0x1bbb
#define ENCP_VIDEO_MATRIX_CR 0x1bbc
#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
/* HIU */
#define HHI_VIID_CLK_DIV 0x4a
#define DAC0_CLK_SEL 28
#define DAC1_CLK_SEL 24
#define DAC2_CLK_SEL 20
#define VCLK2_XD_RST 17
#define VCLK2_XD_EN 16
#define ENCL_CLK_SEL 12
#define VCLK2_XD 0
#define HHI_VID_CLK_DIV 0x59
#define ENCI_CLK_SEL 28
#define ENCP_CLK_SEL 24
#define ENCT_CLK_SEL 20
#define VCLK_XD_RST 17
#define VCLK_XD_EN 16
#define ENCL_CLK_SEL 12
#define VCLK_XD1 8
#define VCLK_XD0 0
#define HHI_VID_CLK_CNTL2 0x65
#define HDMI_TX_PIXEL_GATE_VCLK 5
#define VDAC_GATE_VCLK 4
#define ENCL_GATE_VCLK 3
#define ENCP_GATE_VCLK 2
#define ENCT_GATE_VCLK 1
#define ENCI_GATE_VCLK 0
static inline unsigned int vout_vcbus_read(unsigned int _reg)
{
return aml_read_vcbus(_reg);
};
static inline void vout_vcbus_write(unsigned int _reg, unsigned int _value)
{
aml_write_vcbus(_reg, _value);
};
static inline void vout_vcbus_setb(unsigned int _reg, unsigned int _value,
unsigned int _start, unsigned int _len)
{
vout_vcbus_write(_reg, ((vout_vcbus_read(_reg) &
~(((1L << (_len)) - 1) << (_start))) |
(((_value) & ((1L << (_len)) - 1)) << (_start))));
}
static inline unsigned int vout_vcbus_getb(unsigned int reg,
unsigned int _start, unsigned int _len)
{
return (vout_vcbus_read(reg) >> _start) & ((1L << _len) - 1);
}
static inline unsigned int vout_hiu_read(unsigned int _reg)
{
return aml_read_hiubus(_reg);
};
static inline void vout_hiu_write(unsigned int _reg, unsigned int _value)
{
aml_write_hiubus(_reg, _value);
};
static inline void vout_hiu_setb(unsigned int _reg, unsigned int _value,
unsigned int _start, unsigned int _len)
{
vout_hiu_write(_reg, ((vout_hiu_read(_reg) &
~(((1L << (_len)) - 1) << (_start))) |
(((_value) & ((1L << (_len)) - 1)) << (_start))));
}
static inline unsigned int vout_hiu_getb(unsigned int _reg,
unsigned int _start, unsigned int _len)
{
return (vout_hiu_read(_reg) >> (_start)) & ((1L << (_len)) - 1);
}
#endif

View File

@@ -129,24 +129,6 @@ static struct vinfo_s nulldisp_vinfo[] = {
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
},
{
.name = "dummy_panel",
.mode = VMODE_DUMMY_LCD,
.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,
.fr_adj_type = VOUT_FR_ADJ_NONE,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_MAX,
.vout_device = NULL,
},
};
static struct vinfo_s *nulldisp_get_current_info(void)
@@ -397,43 +379,6 @@ static ssize_t vout_mode_store(struct class *class,
return count;
}
static ssize_t vout_dummy_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
unsigned int tmp[4], sync_duration;
enum vmode_e mode;
int ret;
mutex_lock(&vout_serve_mutex);
mode = VMODE_DUMMY_LCD;
ret = sscanf(buf, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
if (ret == 2) {
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
nulldisp_vinfo[2].width = tmp[0];
nulldisp_vinfo[2].height = tmp[1];
nulldisp_vinfo[2].field_height = tmp[1];
VOUTPR("set dummy size: %d x %d\n", tmp[0], tmp[1]);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
} else if (ret == 4) {
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode);
nulldisp_vinfo[2].width = tmp[0];
nulldisp_vinfo[2].height = tmp[1];
nulldisp_vinfo[2].field_height = tmp[1];
nulldisp_vinfo[2].sync_duration_num = tmp[2];
nulldisp_vinfo[2].sync_duration_den = tmp[3];
sync_duration = (tmp[2] * 100) / tmp[3];
VOUTPR("set dummy size: %d x %d, frame_rate: %d.%02dHz\n",
tmp[0], tmp[1],
(sync_duration / 100), (sync_duration % 100));
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
} else {
VOUTERR("invalid data\n");
}
mutex_unlock(&vout_serve_mutex);
return count;
}
static ssize_t vout_axis_show(struct class *class,
struct class_attribute *attr, char *buf)
{
@@ -610,7 +555,6 @@ static ssize_t vout_vinfo_show(struct class *class,
static struct class_attribute vout_class_attrs[] = {
__ATTR(mode, 0644, vout_mode_show, vout_mode_store),
__ATTR(dummy, 0644, NULL, vout_dummy_store),
__ATTR(axis, 0644, vout_axis_show, vout_axis_store),
__ATTR(fr_policy, 0644,
vout_fr_policy_show, vout_fr_policy_store),

View File

@@ -23,7 +23,7 @@
/* the MSB is represent vmode set by vmode_init */
#define VMODE_INIT_BIT_MASK 0x8000
#define VMODE_MODE_BIT_MASK 0xff
#define VMODE_NULL_DISP_MAX 3
#define VMODE_NULL_DISP_MAX 2
enum vmode_e {
VMODE_HDMI = 0,