mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
@@ -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>
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
661
drivers/amlogic/media/vout/vout_serve/dummy_lcd.c
Normal file
661
drivers/amlogic/media/vout/vout_serve/dummy_lcd.c
Normal 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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
227
drivers/amlogic/media/vout/vout_serve/vout_reg.h
Normal file
227
drivers/amlogic/media/vout/vout_serve/vout_reg.h
Normal 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
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user