lcd: add lcd driver for axg

PD#142470: lcd: add lcd driver for axg

Change-Id: I58e2a2af474bafbbe3718f51493c9b46cb07cf31
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2017-06-09 10:46:09 +08:00
committed by Jianxin Pan
parent 8b769d45af
commit c966c5d0b7
76 changed files with 27085 additions and 29 deletions

View File

@@ -13948,3 +13948,11 @@ F: include/linux/amlogic/unifykey/*
AMLOGIC AXG ADD OSD DRIVER
M: Pengcheng Chen <pengcheng.chen@amlogic.com>
F: drivers/amlogic/media/osd/osd_io.c
AMLOGIC LCD driver
M: Weiming Liu <weiming.liu@amlogic.com>
F: drivers/amlogic/media/vout/backlight/*
F: drivers/amlogic/media/vout/lcd/*
F: include/linux/amlogic/media/vout/lcd/*
F: arch/arm64/boot/dts/amlogic/mesongxm_q200-panel.dtsi
F: arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi

View File

@@ -18,7 +18,7 @@
/dts-v1/;
#include "mesonaxg.dtsi"
#include "mesonaxg_s400-panel.dtsi"
/ {
model = "Amlogic";
compatible = "amlogic, axg";
@@ -399,6 +399,12 @@
/* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */
};
vout {
compatible = "amlogic, vout";
dev_name = "vout";
status = "okay";
};
/* Sound iomap */
aml_snd_iomap {
compatible = "amlogic, snd_iomap";
@@ -975,6 +981,13 @@
function = "pdm";
};
};
bl_pwm_on_pins: bl_pwm_on_pin {
mux {
groups = "GPIOZ_4";
function = "pwm_b";
};
};
}; /* end of pinctrl_periphs */
/* Audio Related End */

View File

@@ -0,0 +1,159 @@
/*
* arch/arm64/boot/dts/amlogic/mesongxm_q200-panel.dtsi
*
* Copyright (C) 2016 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.
*
*/
/ {
lcd{
compatible = "amlogic, lcd";
dev_name = "lcd";
mode = "tablet";
status = "okay";
key_valid = <0>;
clocks = <&clkc CLKID_MIPI_DSI_HOST
&clkc CLKID_MIPI_DSI_PHY
&clkc CLKID_DSI_MEAS_COMP>;
clock-names = "dsi_host",
"dsi_phy",
"dsi_meas";
pinctrl_version = <1>; /* for uboot */
/* power type:
* (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending)
* power index:
* (point gpios_index, or extern_index,0xff=invalid)
* power value:(0=output low, 1=output high, 2=input)
* power delay:(unit in ms)
*/
lcd_cpu-gpios = <&gpio GPIOZ_6 GPIO_ACTIVE_HIGH>;
lcd_cpu_gpio_names = "GPIOZ_6";
lcd_0{
model_name = "B080XAN01";
/*interface(ttl,lvds,mipi)*/
interface = "mipi";
/* basic_setting:
* h_active,v_active,h_period,v_period,
* lcd_bits,screen_widht,screen_height
*/
basic_setting = <768 1024 948 1140 8 119 159>;
/* lcd_timing:
* hs_width,hs_bp,hs_pol,vs_width,vs_bp,vs_pol
*/
lcd_timing = <64 56 0 50 30 0>;
/* clk_attr:
* fr_adj_type(0=clock,1=htotal,2=vtotal),
* clk_ss_level,clk_auto_generate,
* pixel_clk(unit in Hz)
*/
clk_attr = <0 0 1 64843200>;
/* mipi_attr:
* lane_num, bit_rate_max(MHz),
* factor(*100, default 0 for auto),
* operation_mode_init(0=video, 1=command),
* operation_mode_display(0=video, 1=command),
* video_mode_type
* (0=sync_pulse,1=sync_event,2=burst),
* clk_lp_continuous(0=stop,1=continue),
* phy_stop_wait(0=auto,1=standard,2=slow)
*/
mipi_attr = <4 550 0 1 0 2 1 0>;
/* dsi_init: data_type, num, data... */
dsi_init_on = <0x05 1 0x11
0xff 20 /* delay(ms) */
0x05 1 0x29
0xff 20 /* delay(ms) */
0xff 0xff>; /* ending flag */
dsi_init_off = <0x05 1 0x28
0xff 10 /* delay(ms) */
0x05 1 0x10
0xff 10 /* delay(ms) */
0xff 0xff>; /* ending flag */
/* extern_init: 0xff for invalid */
extern_init = <0xff>;
/* power step: type,index,value,delay(ms) */
power_on_step = <0 0 1 10
0 0 0 20
0 0 1 20
2 0 0 0
0xff 0 0 0>;
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>;
backlight_index = <0>;
};
};
lcd_extern{
compatible = "amlogic, lcd_extern";
dev_name = "lcd_extern";
status = "okay";
key_valid = <0>;
extern_1{
index = <1>;
extern_name = "mipi_KD080D13";
status = "disabled";
type = <2>; /* 0=i2c, 1=spi, 2=mipi */
};
};
backlight{
compatible = "amlogic, backlight";
dev_name = "backlight";
status = "okay";
key_valid = <0>;
pinctrl-names = "pwm_on";
pinctrl-0 = <&bl_pwm_on_pins>;
pinctrl_version = <1>; /* for uboot */
/* power index:(point gpios_index, 0xff=invalid)
* power value:(0=output low, 1=output high, 2=input)
* power delay:(unit in ms)
*/
bl-gpios = <&gpio GPIOZ_4 GPIO_ACTIVE_HIGH
&gpio GPIOZ_5 GPIO_ACTIVE_HIGH>;
bl_gpio_names = "GPIOZ_4","GPIOZ_5";
backlight_0{
index = <0>;
bl_name = "backlight_pwm";
bl_level_default_uboot_kernel = <100 100>;
/* level_attr: max, min, mid, mid_mapping */
bl_level_attr = <255 10 128 102>;
bl_ctrl_method = <1>; /* 1=pwm, 2=pwm_combo, 3=extern */
/* power_attr:
* en_gpio_index, on_value, off_value,
* on_delay(ms), off_delay(ms)
*/
bl_power_attr = <1 1 0 200 200>;
/* pwm_port: PWM_A,PWM_B,PWM_C,PWM_D,PWM_VS */
bl_pwm_port = "PWM_B";
/* pwm_attr:
* pwm_method: 0=negative, 1=positive
* pwm_freq: pwm_vs: 1~4(vfreq multiple),
* other pwm: real freq(Hz)
* duty_max(%), duty_min(%)
*/
bl_pwm_attr = <0 180 100 25>;
/* pwm_power:
* pwm_gpio_index, pwm_gpio_off,
* pwm_on_delay(ms), pwm_off_delay(ms)
*/
bl_pwm_power = <0 0 10 10>;
};
};
};/* end of panel */

View File

@@ -1051,6 +1051,50 @@
};
};
lcd_ttl_rgb_6bit_pins_on:lcd_ttl_rgb_6bit_on{
mux {
groups = "lcd_r2_7",
"lcd_g2_7",
"lcd_b2_7";
function = "lcd_ttl";
};
};
lcd_ttl_rgb_8bit_pins_on:lcd_ttl_rgb_8bit_on{
mux {
groups = "lcd_r0_1", "lcd_r2_7",
"lcd_g0_1", "lcd_g2_7",
"lcd_b0_1", "lcd_b2_7";
function = "lcd_ttl";
};
};
/* DE + clk */
lcd_ttl_de_on_pins:lcd_ttl_de_on_pin{
mux {
groups = "tcon_cph", /* clk */
"tcon_oeh"; /* DE */
function = "lcd_ttl";
};
};
/* hvsync + clk */
lcd_ttl_hvsync_on_pins:lcd_ttl_hvsync_on_pin{
mux {
groups = "tcon_cph", /* clk */
"tcon_stv1", /* vs */
"tcon_sth1"; /* hs */
function = "lcd_ttl";
};
};
/* DE + hvsync + clk */
lcd_ttl_de_hvsync_on_pins:lcd_ttl_de_hvsync_on_pin{
mux {
groups = "tcon_cph", /* clk */
"tcon_oeh", /* DE */
"tcon_stv1", /* vs */
"tcon_sth1"; /* hs */
function = "lcd_ttl";
};
};
}; /* end of pinctrl_periphs */
&periphs {

View File

@@ -0,0 +1,131 @@
/*
* arch/arm64/boot/dts/amlogic/mesongxm_q200-panel.dtsi
*
* Copyright (C) 2016 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.
*
*/
/ {
lcd{
compatible = "amlogic, lcd";
dev_name = "lcd";
mode = "tablet";
status = "okay";
key_valid = <0>;
/* clocks = <&clkc CLKID_VCLK2_ENCL
* &clkc CLKID_VCLK2_VENCL>;
* clock-names = "vencl_top",
* "vencl_int";
*/
pinctrl_version = <1>; /* for uboot */
pinctrl-names = "ttl_6bit_hvsync_de_on","ttl_6bit_hvsync_on",
"ttl_6bit_de_on","ttl_8bit_hvsync_de_on",
"ttl_8bit_hvsync_on","ttl_8bit_de_on";
pinctrl-0 = <&lcd_ttl_rgb_6bit_pins_on
&lcd_ttl_de_hvsync_on_pins>;
pinctrl-1 = <&lcd_ttl_rgb_6bit_pins_on
&lcd_ttl_hvsync_on_pins>;
pinctrl-2 = <&lcd_ttl_rgb_6bit_pins_on
&lcd_ttl_de_on_pins>;
pinctrl-3 = <&lcd_ttl_rgb_8bit_pins_on
&lcd_ttl_de_hvsync_on_pins>;
pinctrl-4 = <&lcd_ttl_rgb_8bit_pins_on
&lcd_ttl_hvsync_on_pins>;
pinctrl-5 = <&lcd_ttl_rgb_8bit_pins_on
&lcd_ttl_de_on_pins>;
/* power type:
* (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending)
* power index:
* (point gpios_index, or extern_index,0xff=invalid)
* power value:(0=output low, 1=output high, 2=input)
* power delay:(unit in ms)
*/
/*lcd_cpu-gpios = <&gpio GPIOX_3 1>;*/
/*lcd_cpu_gpio_names = "GPIOX_3";*/
lcd_0{
model_name = "LCD720P";
/*interface(ttl,lvds,mipi)*/
interface = "ttl";
/* basic_setting:
* h_active,v_active,h_period,v_period,
* lcd_bits,screen_widht,screen_height
*/
basic_setting = <1280 720 1650 750 8 16 9>;
/* lcd_timing:
* hs_width,hs_bp,hs_pol,vs_width,vs_bp,vs_pol
*/
lcd_timing = <40 220 1 5 20 1>;
/* clk_attr:
* fr_adj_type(0=clock,1=htotal,2=vtotal),
* clk_ss_level,clk_auto_generate,
* pixel_clk(unit in Hz)
*/
clk_attr = <0 0 1 74250000>;
/* ttl_attr:
* clk_pol, de_valid, hvsync_valid,
* rb_swap, bit_swap
*/
ttl_attr = <0 1 1 0 0>;
/* power step: type,index,value,delay(ms) */
power_on_step = <2 0 0 0
0xff 0 0 0>;
power_off_step = <2 0 0 50
0xff 0 0 0>;
backlight_index = <0xff>;
};
};
lcd_extern{
compatible = "amlogic, lcd_extern";
dev_name = "lcd_extern";
status = "okay";
key_valid = <0>;
extern_0{
index = <0>;
extern_name = "ext_default";
status = "disabled";
type = <0>; /* 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x1c>; /* 7bit i2c address */
i2c_second_address = <0xff>; /* 7bit i2c address, 0xff for none */
i2c_bus = "i2c_bus_d";
cmd_size = <9>;
/* init on/off: (type, value..., delay), must match cmd_size for every group */
/* type: 0x00=cmd(bit[3:0]=1 for second_addr), 0x10=gpio, 0xff=ending*/
/* value: i2c or spi cmd, or gpio index & level, fill 0x0 for no use */
/* delay: unit ms */
init_on = <0x00 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 0x00
0x00 0x80 0x02 0x00 0x40 0x62 0x51 0x73 0x00
0x00 0x61 0x06 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 0x00
0x00 0x13 0x01 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 0x00
0x00 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 0x00
0x00 0x23 0x02 0x00 0x00 0x00 0x00 0x00 0x0A
0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00>;
init_off = <0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00>;
};
extern_1{
index = <2>;
extern_name = "i2c_DLPC3439";
status = "disabled";
type = <0>; /* 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x1b>; /* 7bit i2c address */
i2c_bus = "i2c_bus_d";
};
};
};/* end of panel */

View File

@@ -248,6 +248,12 @@ CONFIG_AMLOGIC_CVBS_OUTPUT=y
CONFIG_AMLOGIC_WSS=y
CONFIG_AMLOGIC_VDAC=y
CONFIG_AMLOGIC_HDMITX=y
CONFIG_AMLOGIC_LCD=y
CONFIG_AMLOGIC_LCD_TV=y
CONFIG_AMLOGIC_LCD_TABLET=y
CONFIG_AMLOGIC_LCD_EXTERN=y
CONFIG_AMLOGIC_LCD_EXTERN_MIPI_KD080D13=y
CONFIG_AMLOGIC_BACKLIGHT=y
CONFIG_AMLOGIC_VOUT_SERVE=y
CONFIG_AMLOGIC_MEDIA_FB=y
CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE=y
@@ -365,6 +371,8 @@ CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_FB=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_USB_AUDIO=y

View File

@@ -57,7 +57,8 @@
#define GXL_GP0_CNTL4 0xc000004d
#define GXL_GP0_CNTL5 0x00078000
/* AXG */
#define AXG_MIPI_CNTL0 0xa5b80000
#define AXG_MIPI_CNTL0_ENABLE BIT(29)
#define AXG_MIPI_CNTL0_BANDGAP BIT(26)
#define AXG_PCIE_PLL_CNTL 0x40010242
#define AXG_PCIE_PLL_CNTL1 0xc084b2ab
#define AXG_PCIE_PLL_CNTL2 0xb75020be
@@ -188,7 +189,9 @@ static int meson_axg_pll_set_rate(struct clk_hw *hw, unsigned long rate,
void *cntlbase = pll->base + p->reg_off;
if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) {
writel(AXG_MIPI_CNTL0, pll->base);
reg = readl(pll->base);
reg |= (AXG_MIPI_CNTL0_ENABLE | AXG_MIPI_CNTL0_BANDGAP);
writel(reg, pll->base);
writel(AXG_PCIE_PLL_CNTL, cntlbase + (u64)(0*4));
writel(AXG_PCIE_PLL_CNTL1, cntlbase + (u64)(1*4));
writel(AXG_PCIE_PLL_CNTL2, cntlbase + (u64)(2*4));

View File

@@ -39,8 +39,8 @@
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/io.h>
#ifdef CONFIG_AML_LCD
#include <linux/amlogic/media/vout/lcd_notify.h>
#ifdef CONFIG_AMLOGIC_LCD
#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
#endif
#include "arch/vpp_regs.h"
@@ -2923,7 +2923,7 @@ static void aml_vecm_dt_parse(struct platform_device *pdev)
/* WRITE_VPP_REG_BITS(VPP_MISC, cm_en, 28, 1); */
}
#ifdef CONFIG_AML_LCD
#ifdef CONFIG_AMLOGIC_LCD
static int aml_lcd_gamma_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
@@ -2983,7 +2983,7 @@ static int aml_vecm_probe(struct platform_device *pdev)
}
spin_lock_init(&vpp_lcd_gamma_lock);
#ifdef CONFIG_AML_LCD
#ifdef CONFIG_AMLOGIC_LCD
ret = aml_lcd_notifier_register(&aml_lcd_gamma_nb);
if (ret)
pr_info("register aml_lcd_gamma_notifier failed\n");
@@ -3047,7 +3047,7 @@ static int __exit aml_vecm_remove(struct platform_device *pdev)
class_destroy(devp->clsp);
unregister_chrdev_region(devp->devno, 1);
kfree(devp);
#ifdef CONFIG_AML_LCD
#ifdef CONFIG_AMLOGIC_LCD
aml_lcd_notifier_unregister(&aml_lcd_gamma_nb);
#endif
probe_ok = 0;

View File

@@ -1553,7 +1553,7 @@ void vdin_set_def_wr_canvas(struct vdin_dev_s *devp)
wr(offset, VDIN_WR_CTRL, (0x0bc01000 | def_canvas));
}
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
void vdin_set_ldim_max_init(unsigned int offset,
int pic_h, int pic_v, int blk_vnum, int blk_hnum)
{
@@ -1660,7 +1660,7 @@ void vdin_set_vframe_prop_info(struct vframe_s *vf,
{
unsigned int offset = devp->addr_offset;
struct vframe_bbar_s bbar = {0};
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
/*int i;*/
#endif
/* fetch hist info */
@@ -1854,7 +1854,7 @@ void vdin_set_vframe_prop_info(struct vframe_s *vf,
vf->prop.meas.vs_stamp = devp->stamp;
vf->prop.meas.vs_cycle = devp->cycle;
#if 0
/*#ifdef CONFIG_AML_LOCAL_DIMMING*/
/*#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING*/
/* get ldim max */
if (vdin_ldim_max_en && is_meson_gxtvbb_cpu()) {
wr_bits(offset, VDIN_LDIM_STTS_HIST_REGION_IDX, 0,
@@ -1884,7 +1884,7 @@ void vdin_set_all_regs(struct vdin_dev_s *devp)
/* bbar sub-module */
vdin_set_bbar(devp->addr_offset, devp->v_active, devp->h_active);
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
/* ldim sub-module */
/* vdin_set_ldim_max_init(devp->addr_offset, 1920, 1080, 8, 2); */
vdin_set_ldim_max_init(devp->addr_offset, devp->h_active,

View File

@@ -97,7 +97,7 @@ struct vdin_stat_s {
unsigned int sum_pixel; /* VDIN_HIST_PIX_CNT_REG */
};
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
struct ldim_max_s {
/* general parameters */
int ld_pic_rowmax;

View File

@@ -360,7 +360,7 @@ static void vdin_write_mem(struct vdin_dev_s *devp, char *type, char *path)
NULL);
}
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
static void vdin_dump_histgram_ldim(struct vdin_dev_s *devp,
unsigned int hnum, unsigned int vnum)
@@ -682,7 +682,7 @@ start_chk:
} else if (!strcmp(parm[0], "histgram")) {
vdin_dump_histgram(devp);
}
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
else if (!strcmp(parm[0], "histgram_ldim")) {
unsigned int hnum, vnum;

View File

@@ -1443,7 +1443,7 @@ irqreturn_t vdin_isr_simple(int irq, void *dev_id)
return IRQ_HANDLED;
}
#if 0
/*#ifdef CONFIG_AML_LOCAL_DIMMING*/
/*#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING*/
unsigned int vdin_ldim_max_global[100] = {0};
static void vdin_backup_histgram_ldim(struct vframe_s *vf,
struct vdin_dev_s *devp)
@@ -1696,7 +1696,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
vdin_set_drm_data(devp, curr_wr_vf);
vdin_set_vframe_prop_info(curr_wr_vf, devp);
vdin_backup_histgram(curr_wr_vf, devp);
#ifdef CONFIG_AML_LOCAL_DIMMING
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
/*vdin_backup_histgram_ldim(curr_wr_vf, devp);*/
#endif
if ((devp->parm.port >= TVIN_PORT_HDMI0) &&

View File

@@ -17,6 +17,8 @@ if AMLOGIC_VOUT
source "drivers/amlogic/media/vout/cvbs/Kconfig"
source "drivers/amlogic/media/vout/vdac/Kconfig"
source "drivers/amlogic/media/vout/hdmitx/Kconfig"
source "drivers/amlogic/media/vout/lcd/Kconfig"
source "drivers/amlogic/media/vout/backlight/Kconfig"
source "drivers/amlogic/media/vout/vout_serve/Kconfig"
endif

View File

@@ -1,4 +1,7 @@
obj-$(CONFIG_AMLOGIC_CVBS_OUTPUT) += cvbs/
obj-$(CONFIG_AMLOGIC_VDAC) += vdac/
obj-$(CONFIG_AMLOGIC_HDMITX) += hdmitx/
obj-$(CONFIG_AMLOGIC_LCD) += lcd/
obj-$(CONFIG_AMLOGIC_BACKLIGHT) += backlight/
obj-$(CONFIG_AMLOGIC_VOUT_SERVE) += vout_serve/

View File

@@ -0,0 +1,19 @@
menu "Amlogic Backlight Support"
config AMLOGIC_BACKLIGHT
bool "Amlogic backlight support"
depends on BACKLIGHT_LCD_SUPPORT
depends on BACKLIGHT_CLASS_DEVICE
default n
help
Say Y here if you want to use the Amlogic backlight management.
Backlight have five ways, including gpio, pwm, pwm_combo,
local dimming, extern.
if AMLOGIC_BACKLIGHT
source "drivers/amlogic/media/vout/backlight/bl_extern/Kconfig"
source "drivers/amlogic/media/vout/backlight/aml_ldim/Kconfig"
endif
endmenu

View File

@@ -0,0 +1,2 @@
obj-$(CONFIG_AMLOGIC_BACKLIGHT) += aml_bl.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN) += bl_extern/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,144 @@
/*
* drivers/amlogic/media/vout/backlight/aml_bl.dts
*
* 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.
*
*/
backlight{
compatible = "amlogic, backlight";
dev_name = "backlight";
status = "okay";
pinctrl-names = "pwm_on","pwm_off","pwm_vs_on","pwm_vs_off",
"pwm_combo_on", "pwm_combo_off";
pinctrl-0 = <&bl_pwm_on_pins>;
pinctrl-1 = <&bl_pwm_off_pins>;
pinctrl-2 = <&bl_pwm_vs_on_pins>;
pinctrl-3 = <&bl_pwm_vs_off_pins>;
pinctrl-4 = <&bl_pwm_combo_on_pins>;
pinctrl-5 = <&bl_pwm_combo_off_pins>;
/* power index:(point gpios_index, 0xff=invalid) */
/* power value:(0=output low, 1=output high, 2=input) */
/* power delay:(unit in ms) */
bl-gpios = <&gpio GPIOAO_4 GPIO_ACTIVE_HIGH
&gpio GPIOY_13 GPIO_ACTIVE_HIGH
&gpio GPIOY_8 GPIO_ACTIVE_HIGH>;
bl_gpio_names = "GPIOAO_4","GPIOY_13","GPIOY_8";
backlight_0{
index = <0>;
bl_name = "backlight_0";
bl_level_default_uboot_kernel = <100 100>;
bl_level_attr = <255 10 128 102>;
/* max, min, mid, mid_mapping */
bl_ctrl_method = <1>;
/* 0=gpio, 1=pwm, 2=pwm_combo, 3=ldim, 4=extern */
bl_power_attr = <0 1 0 200 200>;
/* en_gpio_index, on_value, off_value,
* on_delay, off_delay
*/
/* pwm_method:(0=negative, 1=positive) */
/* pwm_freq:(pwm_vs: 1~4 vfreq multiple,
* other pwm: real freq unit: Hz)
*/
/* pwm_duty:(unit in %) */
bl_pwm_port = "PWM_B";
/* PWM_A, PWM_B, PWM_C, PWM_D, PWM_VS */
bl_pwm_attr = <1 180 100 25>;
/* pwm_method, pwm_freq, duty_max, duty_min */
bl_pwm_power = <1 0 10 10>;
/* pwm_gpio_index, pwm_gpio_off,
* pwm_on_delay, pwm_off_delay
*/
};
backlight_1{
index = <1>;
bl_name = "backlight_1";
bl_level_default_uboot_kernel = <100 100>;
bl_level_attr = <255 10 128 102>;
/* max, min, mid, mid_mapping */
bl_ctrl_method = <1>;
/* 0=gpio, 1=pwm, 2=pwm_combo, 3=ldim, 4=extern */
bl_power_attr = <0 1 0 200 200>;
/* en_gpio_index, on_value, off_value,
* on_delay, off_delay
*/
/* pwm_method: 0=negative, 1=positive */
/* pwm_freq: pwm_vs: 1~4(vfreq multiple),
* other pwm: real freq(unit: Hz)
*/
/* duty_max, duty_min: unit in % */
bl_pwm_port = "PWM_VS";
/* PWM_A, PWM_B, PWM_C, PWM_D, PWM_VS */
bl_pwm_attr = <1 2 100 25>;
/* pwm_method, pwm_freq, duty_max, duty_min */
bl_pwm_power = <1 0 10 10>;
/* pwm_gpio_index, pwm_off_value,
* pwm_on_delay, pwm_off_delay
*/
};
backlight_2{
index = <2>;
bl_name = "backlight_2";
bl_level_attr = <255 10 128 102>;
/* max, min, mid, mid_mapping */
bl_ctrl_method = <3>;
/* 0=gpio, 1=pwm, 2=pwm_combo, 3=ldim, 4=extern */
bl_power_attr = <0 1 0 200 200>;
/* en_gpio_index, on_value,
* off_value, on_delay, off_delay
*/
};
backlight_3{
index = <3>;
bl_name = "backlight_3";
bl_level_default_uboot_kernel = <100 100>;
bl_level_attr = <255 10 128 102>;
/* max, min, mid, mid_mapping */
bl_ctrl_method = <2>;
/* 0=gpio, 1=pwm, 2=pwm_combo, 3=ldim, 4=extern */
bl_power_attr = <0 1 0 200 200>;
/* en_gpio_index, on_value,
* off_value, on_delay, off_delay
*/
/* pwm_method: 0=negative, 1=positive */
/* pwm_freq: pwm_vs: 1~4(vfreq multiple),
* other pwm: real freq(unit: Hz)
*/
/* duty_max, duty_min: unit in % */
bl_pwm_combo_level_mapping = <255 128 128 10>;
/* level_max, level_min */
bl_pwm_combo_port = "PWM_B","PWM_D";
/* PWM_A, PWM_B, PWM_C, PWM_D, PWM_VS */
bl_pwm_combo_attr = <1 180 100 25
0 18000 100 25>;
/* pwm_method, pwm_freq, duty_max, duty_min */
bl_pwm_combo_power = <1 0 2 0 10 10>;
/* pwm0_gpio_index, pwm0_gpio_off,
* pwm1_gpio_index, pwm1_gpio_off,
* pwm_on_delay, pwm_off_delay
*/
};
};

View File

@@ -0,0 +1,91 @@
/*
* drivers/amlogic/media/vout/backlight/aml_bl_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 __AML_BL_REG_H__
#define __AML_BL_REG_H__
#include <linux/amlogic/iomap.h>
/* normal pwm reg: cbus */
#define PWM_PWM_A 0x2154
#define PWM_PWM_B 0x2155
#define PWM_MISC_REG_AB 0x2156
#define PWM_PWM_C 0x2190
#define PWM_PWM_D 0x2191
#define PWM_MISC_REG_CD 0x2192
#define PWM_PWM_E 0x21b0
#define PWM_PWM_F 0x21b1
#define PWM_MISC_REG_EF 0x21b2
/* normal pwm reg: cbus, txlx */
#define PWM_PWM_A_TXLX 0x6c00
#define PWM_PWM_B_TXLX 0x6c01
#define PWM_MISC_REG_AB_TXLX 0x6c02
#define PWM_PWM_C_TXLX 0x6800
#define PWM_PWM_D_TXLX 0x6801
#define PWM_MISC_REG_CD_TXLX 0x6802
#define PWM_PWM_E_TXLX 0x6400
#define PWM_PWM_F_TXLX 0x6401
#define PWM_MISC_REG_EF_TXLX 0x6402
/* pwm_vs reg: vcbus */
#define VPU_VPU_PWM_V0 0x2730
#define VPU_VPU_PWM_V1 0x2731
#define VPU_VPU_PWM_V2 0x2732
#define VPU_VPU_PWM_V3 0x2733
#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
static inline unsigned int bl_cbus_read(unsigned int reg)
{
return aml_read_cbus(reg);
};
static inline void bl_cbus_write(unsigned int reg, unsigned int value)
{
aml_write_cbus(reg, value);
};
static inline void bl_cbus_setb(unsigned int reg, unsigned int value,
unsigned int _start, unsigned int _len)
{
bl_cbus_write(reg, ((bl_cbus_read(reg) &
(~(((1L << _len)-1) << _start))) |
((value & ((1L << _len)-1)) << _start)));
}
static inline unsigned int bl_vcbus_read(unsigned int reg)
{
return aml_read_vcbus(reg);
};
static inline void bl_vcbus_write(unsigned int reg, unsigned int value)
{
aml_write_vcbus(reg, value);
};
static inline void bl_vcbus_setb(unsigned int reg, unsigned int value,
unsigned int _start, unsigned int _len)
{
bl_vcbus_write(reg, ((bl_vcbus_read(reg) &
(~(((1L << _len)-1) << _start))) |
((value & ((1L << _len)-1)) << _start)));
}
#endif

View File

@@ -0,0 +1,12 @@
#
# LDIM Device Driver Configuration
#
config AMLOGIC_LOCAL_DIMMING
bool "Amlogic Local dimming"
default n
help
Say Y if you want to use Amlogic Local dimming.
The role of local dimming is according to each
image information, calculate the corresponding
brightness values, to improve the effect of image quality,

View File

@@ -0,0 +1,40 @@
config AMLOGIC_BL_EXTERN
bool "Amlogic backlight extern driver support"
default n
help
Say Y if you want to use Amlogic backlight external controller.
Amlogic backlight external driver support,
such as i2c or mipi initial
According to choose the corresponding bl_extern inside index bl_extern driver
config AMLOGIC_BL_EXTERN_PMU_AML1218
bool "Amlogic backlight pmu aml1218"
depends on AMLOGIC_BL_EXTERN
default n
help
pmu aml1218 backlight controller support.
Once the backlight power on, according to the timing requirements,
through the aml1218 to write data to the backlight,
make its initialization
config AMLOGIC_BL_EXTERN_I2C_LP8556
bool "Amlogic backlight i2c lp8556"
depends on AMLOGIC_BL_EXTERN
default n
help
i2c lp8556 backlight controller support.
Once the backlight power on, according to the timing requirements,
through the i2c_lp8556 to write data to the backlight,
make its initialization
config AMLOGIC_BL_EXTERN_MIPI_LT070ME05
bool "Amlogic backlight mipi LT070ME05"
depends on AMLOGIC_BL_EXTERN
default n
help
mipi LT070ME05 backlight controller support.
Once the backlight power on, according to the timing requirements,
through the mipi_LT070ME05 to write data to the backlight,
make its initialization

View File

@@ -0,0 +1,6 @@
obj-$(CONFIG_AMLOGIC_BL_EXTERN) += bl_extern.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN_I2C_LP8556) += i2c_lp8556.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN_PMU_AML1218) += pmu_aml1218.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN_MIPI_LT070ME05) += mipi_LT070ME05.o

View File

@@ -0,0 +1,59 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/aml_bl_extern.dts
*
* 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.
*
*/
bl_extern_pmu_aml1218{
compatible = "amlogic, bl_pmu_aml1218";
dev_name ="bl_pmu_aml1218";
status = "disabled"; /** "disabled" or "okay" */
GPIODV_28-gpios = <&gpio GPIODV_28 0>;
gpio_enable_on_off = "GPIODV_28","1","0";
/* gpio("n"for none),
* on/off(1=output high, 0=output low, 2=input)
*/
type = <2>; /** bl_extern_driver type: 0=i2c, 1=spi, 2=other */
dim_max_min = <0x1 0x1b>;
};
bl_extern_i2c_lp8556{
compatible = "amlogic, bl_i2c_lp8556";
dev_name ="bl_i2c_lp8556";
status = "disabled"; /** "disabled" or "okay" */
GPIODV_28-gpios = <&gpio GPIODV_28 0>;
gpio_enable_on_off = "GPIODV_28","1","0";
/* gpio("n"for none),
* on/off(1=output high, 0=output low, 2=input)
*/
type = <0>; /** bl_extern_driver type: 0=i2c, 1=spi, 2=other */
i2c_address = <0x2c>; /** 7bit i2c address */
i2c_bus = "i2c_bus_b";
dim_max_min = <255 10>;
};
bl_extern_mipi_LT070ME05{
compatible = "amlogic, bl_mipi_LT070ME05";
dev_name ="bl_mipi_LT070ME056";
status = "disabled"; /** "disabled" or "okay" */
GPIODV_28-gpios = <&gpio GPIODV_28 0>;
gpio_enable_on_off = "GPIODV_28","1","0";
/* gpio("n"for none),
* on/off(1=output high, 0=output low, 2=input)
*/
type = <2>; /** bl_extern_driver type: 0=i2c, 1=spi, 2=other */
dim_max_min = <255 10>;
};

View File

@@ -0,0 +1,234 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/aml_bl_extern.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#ifdef BL_EXT_DEBUG_INFO
#define DBG_PRINT(...) pr_info(__VA_ARGS__)
#else
#define DBG_PRINT(...)
#endif
static struct aml_bl_extern_driver_t bl_ext_driver = {
.type = BL_EXTERN_MAX,
.name = NULL,
.power_on = NULL,
.power_off = NULL,
.set_level = NULL,
};
struct aml_bl_extern_driver_t *aml_bl_extern_get_driver(void)
{
return &bl_ext_driver;
}
int bl_extern_driver_check(void)
{
struct aml_bl_extern_driver_t *bl_ext;
bl_ext = aml_bl_extern_get_driver();
if (bl_ext) {
if (bl_ext->type < BL_EXTERN_MAX) {
pr_err("[warning]: bl_extern has already exist (%s)\n",
bl_ext->name);
return -1;
}
} else {
pr_err("get bl_extern_driver failed\n");
}
return 0;
}
int get_bl_extern_dt_data(struct device dev, struct bl_extern_config_t *pdata)
{
int ret;
struct device_node *of_node = dev.of_node;
u32 bl_para[2];
const char *str;
struct gpio_desc *bl_extern_gpio;
ret = of_property_read_string(of_node, "dev_name",
(const char **)&pdata->name);
if (ret) {
pdata->name = "aml_bl_extern";
pr_err("warning: get dev_name failed\n");
}
ret = of_property_read_u32(of_node, "type", &pdata->type);
if (ret) {
pdata->type = BL_EXTERN_MAX;
pr_err("%s warning: get type failed, exit\n", pdata->name);
return -1;
}
pdata->gpio_used = 0;
ret = of_property_read_string_index(of_node,
"gpio_enable_on_off", 0, &str);
if (ret) {
pr_warn("%s warning: get gpio_enable failed\n", pdata->name);
} else {
if (strncmp(str, "G", 1) == 0) {
pdata->gpio_used = 1;
bl_extern_gpio = gpiod_get(&dev, str);
if (bl_extern_gpio) {
pr_warn("%s warning:failed to alloc gpio (%s)\n",
pdata->name, str);
}
pdata->gpio = bl_extern_gpio;
}
DBG_PRINT("%s: gpio_enable %s\n",
pdata->name, ((pdata->gpio_used) ? str:"none"));
}
ret = of_property_read_string_index(of_node,
"gpio_enable_on_off", 1, &str);
if (ret) {
pr_warn("%s warning: get gpio_enable_on failed\n", pdata->name);
} else {
if (strncmp(str, "2", 1) == 0)
pdata->gpio_on = LCD_POWER_GPIO_INPUT;
else if (strncmp(str, "0", 1) == 0)
pdata->gpio_on = LCD_POWER_GPIO_OUTPUT_LOW;
else
pdata->gpio_on = LCD_POWER_GPIO_OUTPUT_HIGH;
}
ret = of_property_read_string_index(of_node,
"gpio_enable_on_off", 2, &str);
if (ret) {
pr_warn("%s warning:get gpio_enable_off failed\n", pdata->name);
} else {
if (strncmp(str, "2", 1) == 0)
pdata->gpio_off = LCD_POWER_GPIO_INPUT;
else if (strncmp(str, "1", 1) == 0)
pdata->gpio_off = LCD_POWER_GPIO_OUTPUT_HIGH;
else
pdata->gpio_off = LCD_POWER_GPIO_OUTPUT_LOW;
}
DBG_PRINT("%s: gpio_on = %d,", pdata->name, pdata->gpio_on);
DBG_PRINT("gpio_off = %d\n", pdata->gpio_off);
switch (pdata->type) {
case BL_EXTERN_I2C:
ret = of_property_read_u32(of_node, "i2c_address",
&pdata->i2c_addr);
if (ret) {
pr_warn("%s warning: get i2c_address failed\n",
pdata->name);
pdata->i2c_addr = 0;
}
DBG_PRINT("%s: i2c_address=", pdata->name);
DBG_PRINT("0x%02x\n", pdata->i2c_addr);
ret = of_property_read_string(of_node, "i2c_bus", &str);
if (ret) {
pr_warn("%s warning: get i2c_bus failed,", pdata->name);
pr_warn("use default i2c bus\n");
pdata->i2c_bus = AML_I2C_MASTER_A;
} else {
if (strncmp(str, "i2c_bus_a", 9) == 0)
pdata->i2c_bus = AML_I2C_MASTER_A;
else if (strncmp(str, "i2c_bus_b", 9) == 0)
pdata->i2c_bus = AML_I2C_MASTER_B;
else if (strncmp(str, "i2c_bus_c", 9) == 0)
pdata->i2c_bus = AML_I2C_MASTER_C;
else if (strncmp(str, "i2c_bus_d", 9) == 0)
pdata->i2c_bus = AML_I2C_MASTER_D;
else if (strncmp(str, "i2c_bus_ao", 10) == 0)
pdata->i2c_bus = AML_I2C_MASTER_AO;
else
pdata->i2c_bus = AML_I2C_MASTER_A;
}
DBG_PRINT("%s: i2c_bus=%s[%d]\n", pdata->name,
str, pdata->i2c_bus);
break;
case BL_EXTERN_SPI:
ret = of_property_read_string(of_node, "gpio_spi_cs", &str);
if (ret) {
pr_warn("%s warning: get spi gpio_spi_cs failed\n",
pdata->name);
pdata->spi_cs = NULL;
} else {
bl_extern_gpio = gpiod_get(&dev, str);
if (bl_extern_gpio) {
pdata->spi_cs = bl_extern_gpio;
DBG_PRINT("spi_cs gpio = %s\n", str);
} else {
pr_warn("%s warning:failed to alloc gpio (%s)\n",
pdata->name, str);
pdata->spi_cs = NULL;
}
}
ret = of_property_read_string(of_node, "gpio_spi_clk", &str);
if (ret) {
pr_warn("%s warning: get spi gpio_spi_clk failed\n",
pdata->name);
pdata->spi_clk = NULL;
} else {
bl_extern_gpio = gpiod_get(&dev, str);
if (bl_extern_gpio) {
pdata->spi_clk = bl_extern_gpio;
DBG_PRINT("spi_cs gpio = %s\n", str);
} else {
pdata->spi_clk = NULL;
pr_warn("%s warning:failed to alloc gpio (%s)\n",
pdata->name, str);
}
}
ret = of_property_read_string(of_node, "gpio_spi_data", &str);
if (ret) {
pr_warn("%s warning: get spi gpio_spi_data failed\n",
pdata->name);
pdata->spi_data = NULL;
} else {
bl_extern_gpio = gpiod_get(&dev, str);
if (bl_extern_gpio) {
pdata->spi_data = bl_extern_gpio;
DBG_PRINT("spi_cs gpio = %s\n", str);
} else {
pdata->spi_data = NULL;
pr_warn("%s warning:failed to alloc gpio (%s)\n",
pdata->name, str);
}
}
break;
case BL_EXTERN_OTHER:
break;
default:
break;
}
ret = of_property_read_u32_array(of_node, "dim_max_min",
&bl_para[0], 2);
if (ret) {
pr_warn("%s warning: get dim_max_min failed\n", pdata->name);
pdata->dim_max = 0;
pdata->dim_min = 0;
} else {
pdata->dim_max = bl_para[0];
pdata->dim_min = bl_para[1];
}
DBG_PRINT("%s dim_min = %d, dim_max = %d\n", pdata->name,
pdata->dim_min, pdata->dim_max);
return 0;
}

View File

@@ -0,0 +1,370 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.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.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/sysctl.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/vout/lcd/aml_bl_extern.h>
static struct bl_extern_config_t *bl_ext_config;
static struct i2c_client *aml_lp8556_i2c_client;
#ifdef BL_EXT_DEBUG_INFO
#define DBG_PRINT(...) pr_info(__VA_ARGS__)
#else
#define DBG_PRINT(...)
#endif
#define BL_EXTERN_NAME "bl_i2c_lp8556"
static unsigned int bl_status = 1;
static unsigned int bl_level;
static unsigned char i2c_init_table[][2] = {
{0xa1, 0x76}, /* hight bit(8~11)(0~0X66e set backlight) */
{0xa0, 0x66}, /* low bit(0~7) 20mA */
{0x16, 0x1F}, /* 5channel LED enable 0x1F */
{0xa9, 0xA0}, /* VBOOST_MAX 25V */
{0x9e, 0x12},
{0xa2, 0x23},
{0x01, 0x05}, /* 0x03 pwm+I2c set brightness,0x5 I2c set brightness */
{0xff, 0xff}, /* ending flag */
};
static int aml_i2c_write(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int res = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
}
};
res = i2c_transfer(i2client->adapter, msg, 1);
if (res < 0)
pr_err("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
return res;
}
#if 0
static int aml_i2c_read(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int res = 0;
struct i2c_msg msgs[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = 1,
.buf = buff,
},
{
.addr = i2client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buff,
}
};
res = i2c_transfer(i2client->adapter, msgs, 2);
if (res < 0)
pr_err("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
return res;
}
#endif
static int bl_extern_set_level(unsigned int level)
{
unsigned char tData[3];
int ret = 0;
struct aml_bl_drv_s *bl_drv = aml_bl_get_driver();
unsigned int level_max, level_min;
unsigned int dim_max, dim_min;
bl_level = level;
if (bl_ext_config == NULL) {
pr_err("no %s driver\n", BL_EXTERN_NAME);
return -1;
}
if (bl_drv == NULL)
return -1;
level_max = bl_drv->bconf->level_max;
level_min = bl_drv->bconf->level_min;
dim_max = bl_ext_config->dim_max;
dim_min = bl_ext_config->dim_min;
level = dim_min - ((level - level_min) * (dim_min - dim_max)) /
(level_max - level_min);
level &= 0xff;
if (bl_status) {
tData[0] = 0x0;
tData[1] = level;
ret = aml_i2c_write(aml_lp8556_i2c_client, tData, 2);
}
return ret;
}
static int bl_extern_power_on(void)
{
unsigned char tData[3];
int i = 0, ending_flag = 0;
int ret = 0;
if (bl_ext_config->gpio) {
if (bl_ext_config->gpio_on == 2) {
bl_gpio_input(bl_ext_config->gpio);
} else {
bl_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_on);
}
}
while (ending_flag == 0) {
if (i2c_init_table[i][0] == 0xff) {
if (i2c_init_table[i][1] == 0xff)
ending_flag = 1;
else
mdelay(i2c_init_table[i][1]);
} else {
tData[0] = i2c_init_table[i][0];
tData[1] = i2c_init_table[i][1];
ret = aml_i2c_write(aml_lp8556_i2c_client, tData, 2);
}
i++;
}
bl_status = 1;
bl_extern_set_level(bl_level);
BLPR("%s\n", __func__);
return ret;
}
static int bl_extern_power_off(void)
{
bl_status = 0;
if (bl_ext_config->gpio) {
if (bl_ext_config->gpio_off == 2) {
bl_gpio_input(bl_ext_config->gpio);
} else {
bl_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_off);
}
}
BLPR("%s\n", __func__);
return 0;
}
static int get_bl_extern_config(struct device dev,
struct bl_extern_config_t *bl_ext_cfg)
{
int ret = 0;
struct aml_bl_extern_driver_t *bl_ext;
ret = get_bl_extern_dt_data(dev, bl_ext_cfg);
if (ret) {
BLPR("error %s: failed to get dt data\n", BL_EXTERN_NAME);
return ret;
}
if (bl_ext_cfg->dim_min > 0xff)
bl_ext_cfg->dim_min = 0xff;
if (bl_ext_cfg->dim_max > 0xff)
bl_ext_cfg->dim_max = 0xff;
bl_ext = aml_bl_extern_get_driver();
if (bl_ext) {
bl_ext->type = bl_ext_cfg->type;
bl_ext->name = bl_ext_cfg->name;
bl_ext->power_on = bl_extern_power_on;
bl_ext->power_off = bl_extern_power_off;
bl_ext->set_level = bl_extern_set_level;
} else {
BLPR("error %s get bl_extern_driver failed\n",
bl_ext_cfg->name);
ret = -1;
}
return ret;
}
static int aml_lp8556_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
BLPR("error %s: functionality check failed\n",
__func__);
else
aml_lp8556_i2c_client = client;
BLPR("%s OK\n", __func__);
return 0;
}
static int aml_lp8556_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_lp8556_i2c_id[] = {
{BL_EXTERN_NAME, 0},
{ }
};
static struct i2c_driver aml_lp8556_i2c_driver = {
.probe = aml_lp8556_i2c_probe,
.remove = aml_lp8556_i2c_remove,
.id_table = aml_lp8556_i2c_id,
.driver = {
.name = BL_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
static int aml_lp8556_probe(struct platform_device *pdev)
{
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int ret = 0;
if (bl_extern_driver_check())
return -1;
if (bl_ext_config == NULL)
bl_ext_config = kzalloc(sizeof(*bl_ext_config), GFP_KERNEL);
if (bl_ext_config == NULL) {
BLPR("error %s probe: failed to alloc data\n", BL_EXTERN_NAME);
return -1;
}
pdev->dev.platform_data = bl_ext_config;
ret = get_bl_extern_config(pdev->dev, bl_ext_config);
if (ret)
goto bl_extern_probe_failed;
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(bl_ext_config->i2c_bus);
if (!adapter) {
BLPR("error %s£ºfailed get i2c adapter\n", BL_EXTERN_NAME);
goto bl_extern_probe_failed;
}
strncpy(i2c_info.type, bl_ext_config->name, I2C_NAME_SIZE);
i2c_info.addr = bl_ext_config->i2c_addr;
i2c_info.platform_data = bl_ext_config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f)
i2c_info.flags = 0x10;
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
BLPR("error %s :failed new i2c device\n", BL_EXTERN_NAME);
goto bl_extern_probe_failed;
} else{
DBG_PRINT("error %s: new i2c device succeed\n",
((struct bl_extern_data_t *)(bl_ext_config))->name);
}
if (!aml_lp8556_i2c_client) {
ret = i2c_add_driver(&aml_lp8556_i2c_driver);
if (ret) {
BLPR("error %s probe: add i2c_driver failed\n",
BL_EXTERN_NAME);
goto bl_extern_probe_failed;
}
}
BLPR("%s ok\n", __func__);
return ret;
bl_extern_probe_failed:
kfree(bl_ext_config);
bl_ext_config = NULL;
return -1;
}
static int aml_lp8556_remove(struct platform_device *pdev)
{
kfree(pdev->dev.platform_data);
return 0;
}
#ifdef CONFIG_USE_OF
static const struct of_device_id aml_lp8556_dt_match[] = {
{
.compatible = "amlogic, bl_i2c_lp8556",
},
{},
};
#else
#define aml_lp8556_dt_match NULL
#endif
static struct platform_driver aml_lp8556_driver = {
.probe = aml_lp8556_probe,
.remove = aml_lp8556_remove,
.driver = {
.name = BL_EXTERN_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_USE_OF
.of_match_table = aml_lp8556_dt_match,
#endif
},
};
static int __init aml_lp8556_init(void)
{
int ret;
BLPR("%s\n", __func__);
ret = platform_driver_register(&aml_lp8556_driver);
if (ret) {
BLPR("error %s failed to register bl extern driver\n",
__func__);
return -ENODEV;
}
return ret;
}
static void __exit aml_lp8556_exit(void)
{
platform_driver_unregister(&aml_lp8556_driver);
}
module_init(aml_lp8556_init);
module_exit(aml_lp8556_exit);
MODULE_AUTHOR("AMLOGIC");
MODULE_DESCRIPTION("BL Extern driver for LP8556");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,221 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/mipi_LT070ME05.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.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/sysctl.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/vout/lcd/aml_bl_extern.h>
#ifdef CONFIG_LCD_IF_MIPI_VALID
static struct bl_extern_config_t *bl_ext_config;
#ifdef BL_EXT_DEBUG_INFO
#define DBG_PRINT(...) pr_info(__VA_ARGS__)
#else
#define DBG_PRINT(...)
#endif
#define BL_EXTERN_NAME "bl_mipi_LT070ME05"
static unsigned int bl_status = 1;
static unsigned int bl_level;
/******************** mipi command ********************
* format: data_type, num, data....
* special: data_type=0xff, num<0xff means delay ms, num=0xff means ending.
*/
static int bl_extern_set_level(unsigned int level)
{
unsigned char payload[] = {0x15, 2, 0x51, 0xe6, 0xff, 0xff};
bl_level = level;
if (bl_ext_config == NULL) {
pr_err("no %s driver\n", BL_EXTERN_NAME);
return -1;
}
get_bl_ext_level(bl_ext_config);
level = bl_ext_config->dim_min -
((level - bl_ext_config->level_min) *
(bl_ext_config->dim_min - bl_ext_config->dim_max)) /
(bl_ext_config->level_max - bl_ext_config->level_min);
level &= 0xff;
if (bl_status) {
payload[3] = level;
dsi_write_cmd(payload);
}
return 0;
}
static int bl_extern_power_on(void)
{
if (bl_ext_config->gpio_used > 0) {
if (bl_ext_config->gpio_on == 2) {
bl_extern_gpio_input(bl_ext_config->gpio);
} else {
bl_extern_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_on);
}
}
bl_status = 1;
bl_extern_set_level(bl_level);
pr_info("%s\n", __func__);
return 0;
}
static int bl_extern_power_off(void)
{
if (bl_ext_config->gpio_used > 0) {
if (bl_ext_config->gpio_off == 2) {
bl_extern_gpio_input(bl_ext_config->gpio);
} else {
bl_extern_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_off);
}
}
pr_info("%s\n", __func__);
return 0;
}
static int get_bl_extern_config(struct device dev,
struct bl_extern_config_t *bl_ext_cfg)
{
int ret = 0;
struct aml_bl_extern_driver_t *bl_ext;
ret = get_bl_extern_dt_data(dev, bl_ext_cfg);
if (ret) {
pr_err("[error] %s: failed to get dt data\n", BL_EXTERN_NAME);
return ret;
}
if (bl_ext_cfg->dim_min > 0xff)
bl_ext_cfg->dim_min = 0xff;
if (bl_ext_cfg->dim_max > 0xff)
bl_ext_cfg->dim_max = 0xff;
bl_ext = aml_bl_extern_get_driver();
if (bl_ext) {
bl_ext->type = bl_ext_cfg->type;
bl_ext->name = bl_ext_cfg->name;
bl_ext->power_on = bl_extern_power_on;
bl_ext->power_off = bl_extern_power_off;
bl_ext->set_level = bl_extern_set_level;
} else {
pr_err("[error] %s get bl_extern_driver failed\n",
bl_ext_cfg->name);
ret = -1;
}
return ret;
}
static int aml_LT070ME05_probe(struct platform_device *pdev)
{
int ret = 0;
if (bl_extern_driver_check())
return -1;
if (bl_ext_config == NULL)
bl_ext_config = kzalloc(sizeof(*bl_ext_config), GFP_KERNEL);
if (bl_ext_config == NULL) {
pr_err("[error] %s probe: failed to alloc data\n",
BL_EXTERN_NAME);
return -1;
}
pdev->dev.platform_data = bl_ext_config;
ret = get_bl_extern_config(pdev->dev, bl_ext_config);
if (ret)
goto bl_extern_probe_failed;
pr_info("%s ok\n", __func__);
return ret;
bl_extern_probe_failed:
kfree(bl_ext_config);
bl_ext_config = NULL;
return -1;
}
static int aml_LT070ME05_remove(struct platform_device *pdev)
{
kfree(pdev->dev.platform_data);
return 0;
}
#ifdef CONFIG_USE_OF
static const struct of_device_id aml_LT070ME05_dt_match[] = {
{
.compatible = "amlogic, bl_mipi_LT070ME05",
},
{},
};
#else
#define aml_LT070ME05_dt_match NULL
#endif
static struct platform_driver aml_LT070ME05_driver = {
.probe = aml_LT070ME05_probe,
.remove = aml_LT070ME05_remove,
.driver = {
.name = BL_EXTERN_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_USE_OF
.of_match_table = aml_LT070ME05_dt_match,
#endif
},
};
static int __init aml_LT070ME05_init(void)
{
int ret;
DBG_PRINT("%s\n", __func__);
ret = platform_driver_register(&aml_LT070ME05_driver);
if (ret) {
pr_err("[error] %s failed to register bl extern driver\n",
__func__);
return -ENODEV;
}
return ret;
}
static void __exit aml_LT070ME05_exit(void)
{
platform_driver_unregister(&aml_LT070ME05_driver);
}
rootfs_initcall(aml_LT070ME05_init);
module_exit(aml_LT070ME05_exit);
MODULE_AUTHOR("AMLOGIC");
MODULE_DESCRIPTION("BL Extern driver for LT070ME05");
MODULE_LICENSE("GPL");
#endif

View File

@@ -0,0 +1,328 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/pmu_aml1218.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.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/sysctl.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/vout/lcd/aml_bl_extern.h>
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
#include <linux/amlogic/aml_pmu_common.h>
#endif
static struct bl_extern_config_t *bl_ext_config;
#ifdef BL_EXT_DEBUG_INFO
#define DBG_PRINT(...) pr_info(__VA_ARGS__)
#else
#define DBG_PRINT(...)
#endif
#define BL_EXTERN_NAME "bl_pmu_aml1218"
static int bl_extern_set_level(unsigned int level)
{
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
struct aml_pmu_driver *pmu_driver;
unsigned char temp;
#endif
int ret = 0;
if (bl_ext_config == NULL) {
pr_err("no %s driver\n", BL_EXTERN_NAME);
return -1;
}
get_bl_ext_level(bl_ext_config);
level = bl_ext_config->dim_min -
((level - bl_ext_config->level_min) *
(bl_ext_config->dim_min - bl_ext_config->dim_max)) /
(bl_ext_config->level_max - bl_ext_config->level_min);
level &= 0x1f;
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
pmu_driver = aml_pmu_get_driver();
if (pmu_driver == NULL) {
pr_err("no pmu driver\n");
} else {
if ((pmu_driver->pmu_reg_write) && (pmu_driver->pmu_reg_read)) {
ret = pmu_driver->pmu_reg_read(0x005f, &temp);
temp &= ~(0x3f << 2);
temp |= (level << 2);
ret = pmu_driver->pmu_reg_write(0x005f, temp);
} else {
pr_err("no pmu_reg_read/write\n");
return -1;
}
}
#endif
return ret;
}
static int bl_extern_power_on(void)
{
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
struct aml_pmu_driver *pmu_driver;
unsigned char temp;
#endif
int ret = 0;
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
pmu_driver = aml_pmu_get_driver();
if (pmu_driver == NULL) {
pr_err("no pmu driver\n");
} else {
if ((pmu_driver->pmu_reg_write) && (pmu_driver->pmu_reg_read)) {
ret = pmu_driver->pmu_reg_read(0x005e, &temp);
temp |= (1 << 7);
ret = pmu_driver->pmu_reg_write(0x005e, temp);
} else {
pr_err("no pmu_reg_read/write\n");
return -1;
}
}
#endif
if (bl_ext_config->gpio_used > 0) {
if (bl_ext_config->gpio_on == 2)
bl_extern_gpio_input(bl_ext_config->gpio);
else
bl_extern_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_on);
}
pr_info("%s\n", __func__);
return ret;
}
static int bl_extern_power_off(void)
{
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
struct aml_pmu_driver *pmu_driver;
unsigned char temp;
#endif
int ret = 0;
if (bl_ext_config->gpio_used > 0) {
if (bl_ext_config->gpio_off == 2)
bl_extern_gpio_input(bl_ext_config->gpio);
else
bl_extern_gpio_output(bl_ext_config->gpio,
bl_ext_config->gpio_off);
}
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
pmu_driver = aml_pmu_get_driver();
if (pmu_driver == NULL) {
pr_err("no pmu driver\n");
} else {
if ((pmu_driver->pmu_reg_write) && (pmu_driver->pmu_reg_read)) {
ret = pmu_driver->pmu_reg_read(0x005e, &temp);
temp &= ~(1 << 7);
ret = pmu_driver->pmu_reg_write(0x005e, temp);
} else {
pr_err("no pmu_reg_read/write\n");
return -1;
}
}
#endif
pr_info("%s\n", __func__);
return ret;
}
static ssize_t bl_extern_debug(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
struct aml_pmu_driver *pmu_driver;
unsigned char temp;
unsigned int t[2];
#endif
int ret = 0;
#ifdef CONFIG_AMLOGIC_BOARD_HAS_PMU
pmu_driver = aml_pmu_get_driver();
if (pmu_driver == NULL) {
pr_err("no pmu driver\n");
return -EINVAL;
}
switch (buf[0]) {
case 'r':
ret = sscanf(buf, "r %x", &t[0]);
if ((pmu_driver->pmu_reg_write) && (pmu_driver->pmu_reg_read)) {
ret = pmu_driver->pmu_reg_read(t[0], &temp);
pr_info("read pmu reg: 0x%x=0x%x\n", t[0], temp);
}
break;
case 'w':
ret = sscanf(buf, "w %x %x", &t[0], &t[1]);
if ((pmu_driver->pmu_reg_write) && (pmu_driver->pmu_reg_read)) {
ret = pmu_driver->pmu_reg_write(t[0], t[1]);
ret = pmu_driver->pmu_reg_read(t[0], &temp);
pr_info("write pmu reg 0x%x: 0x%x, readback: 0x%x\n",
t[0], t[1], temp);
}
break;
default:
pr_err("wrong format of command.\n");
break;
}
#endif
if (ret != 1 || ret != 2)
return -EINVAL;
return count;
}
static struct class_attribute bl_extern_debug_class_attrs[] = {
__ATTR(debug, 0644, NULL, bl_extern_debug),
__ATTR_NULL
};
static struct class bl_extern_debug_class = {
.name = "bl_ext",
.class_attrs = bl_extern_debug_class_attrs,
};
static int get_bl_extern_config(struct device dev,
struct bl_extern_config_t *bl_ext_cfg)
{
int ret = 0;
struct aml_bl_extern_driver_t *bl_ext;
ret = get_bl_extern_dt_data(dev, bl_ext_cfg);
if (ret) {
pr_err("[error] %s: failed to get dt data\n", BL_EXTERN_NAME);
return ret;
}
if (bl_ext_cfg->dim_min > 0x1f)
bl_ext_cfg->dim_min = 0x1f;
if (bl_ext_cfg->dim_max > 0x1f)
bl_ext_cfg->dim_max = 0x1f;
bl_ext = aml_bl_extern_get_driver();
if (bl_ext) {
bl_ext->type = bl_ext_cfg->type;
bl_ext->name = bl_ext_cfg->name;
bl_ext->power_on = bl_extern_power_on;
bl_ext->power_off = bl_extern_power_off;
bl_ext->set_level = bl_extern_set_level;
} else {
pr_err("[error] %s get bl_extern_driver failed\n",
bl_ext_cfg->name);
ret = -1;
}
return ret;
}
static int aml_aml1218_probe(struct platform_device *pdev)
{
int ret = 0;
if (bl_extern_driver_check())
return -1;
if (bl_ext_config == NULL)
bl_ext_config = kzalloc(sizeof(*bl_ext_config), GFP_KERNEL);
if (bl_ext_config == NULL) {
pr_err("[error] %s probe: failed to alloc data\n",
BL_EXTERN_NAME);
return -1;
}
pdev->dev.platform_data = bl_ext_config;
ret = get_bl_extern_config(pdev->dev, bl_ext_config);
if (ret)
goto bl_extern_probe_failed;
ret = class_register(&bl_extern_debug_class);
if (ret)
pr_err("class register bl_extern_debug_class fail!\n");
pr_err("%s ok\n", __func__);
return ret;
bl_extern_probe_failed:
kfree(bl_ext_config);
bl_ext_config = NULL;
return -1;
}
static int aml_aml1218_remove(struct platform_device *pdev)
{
kfree(pdev->dev.platform_data);
return 0;
}
#ifdef CONFIG_USE_OF
static const struct of_device_id aml_aml1218_dt_match[] = {
{
.compatible = "amlogic, bl_pmu_aml1218",
},
{},
};
#else
#define aml_aml1218_dt_match NULL
#endif
static struct platform_driver aml_aml1218_driver = {
.probe = aml_aml1218_probe,
.remove = aml_aml1218_remove,
.driver = {
.name = BL_EXTERN_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_USE_OF
.of_match_table = aml_aml1218_dt_match,
#endif
},
};
static int __init aml_aml1218_init(void)
{
int ret;
DBG_PRINT("%s\n", __func__);
ret = platform_driver_register(&aml_aml1218_driver);
if (ret) {
pr_err("[error] %s failed to register bl extern driver\n",
__func__);
return -ENODEV;
}
return ret;
}
static void __exit aml_aml1218_exit(void)
{
platform_driver_unregister(&aml_aml1218_driver);
}
rootfs_initcall(aml_aml1218_init);
module_exit(aml_aml1218_exit);
MODULE_AUTHOR("AMLOGIC");
MODULE_DESCRIPTION("BL Extern driver for aml1218");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,37 @@
#
# Video output configuration
#
menu "Amlogic LCD Output Module"
config AMLOGIC_LCD
bool "LCD Output Module"
default n
help
LCD output module
support tv mode and tablet mode
Through the inside of the DTS file "mode" is
to choose a TV mode or tablet mode
config AMLOGIC_LCD_TV
bool "LCD TV Output Module"
default n
depends on AMLOGIC_LCD
help
LCD TV output module
Configure the LCD output model for TV output
TV mode mainly includes vbyone and an LVDS interface display
Through the environment variable is to choose panel_type lcd_index
config AMLOGIC_LCD_TABLET
bool "LCD Tablet Output Module"
default n
depends on AMLOGIC_LCD
help
LCD Tablet output module
Configure the LCD output model for Tablet output
if AMLOGIC_LCD
source "drivers/amlogic/media/vout/lcd/lcd_extern/Kconfig"
endif
endmenu

View File

@@ -0,0 +1,4 @@
obj-$(CONFIG_AMLOGIC_LCD) += lcd_vout.o lcd_reg.o lcd_common.o lcd_notify.o lcd_debug.o lcd_clk_config.o lcd_unifykey.o
obj-$(CONFIG_AMLOGIC_LCD_TV) += lcd_tv/
obj-$(CONFIG_AMLOGIC_LCD_TABLET) += lcd_tablet/
obj-$(CONFIG_AMLOGIC_LCD_EXTERN) += lcd_extern/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_clk_config.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 _LCD_CLK_CONFIG_H
#define _LCD_CLK_CONFIG_H
#include <linux/types.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
/* clk config */
struct lcd_clk_config_s { /* unit: kHz */
/* IN-OUT parameters */
unsigned int fin;
unsigned int fout;
/* pll parameters */
unsigned int od_fb;
unsigned int pll_m;
unsigned int pll_n;
unsigned int pll_fvco;
unsigned int pll_od1_sel;
unsigned int pll_od2_sel;
unsigned int pll_od3_sel;
unsigned int pll_level;
unsigned int pll_frac;
unsigned int pll_fout;
unsigned int ss_level;
unsigned int edp_div0;
unsigned int edp_div1;
unsigned int div_pre; /* m6, m8, m8b */
unsigned int div_post; /* m6, m8, m8b */
unsigned int div_sel; /* g9tv, g9bb, gxbb */
unsigned int xd;
/* clk path node parameters */
unsigned int ss_level_max;
unsigned int pll_m_max;
unsigned int pll_m_min;
unsigned int pll_n_max;
unsigned int pll_n_min;
unsigned int pll_frac_range;
unsigned int pll_od_sel_max;
unsigned int div_pre_sel_max; /* m6, m8, m8b */
unsigned int div_post_sel_max; /* m6, m8, m8b */
unsigned int div_sel_max; /* g9tv, g9bb, gxbb */
unsigned int xd_max;
unsigned int pll_ref_fmax;
unsigned int pll_ref_fmin;
unsigned int pll_vco_fmax;
unsigned int pll_vco_fmin;
unsigned int pll_out_fmax;
unsigned int pll_out_fmin;
unsigned int div_post_out_fmax; /* m6, m8, m8b */
unsigned int div_in_fmax; /* g9tv, g9bb, gxbb */
unsigned int div_out_fmax; /* g9tv, g9bb, gxbb */
unsigned int xd_out_fmax;
unsigned int err_fmin;
};
/* pll & clk parameter */
/* ******** clk calculation ******** */
#define PLL_WAIT_LOCK_CNT 200
/* frequency unit: kHz */
#define FIN_FREQ (24 * 1000)
/* clk max error */
#define MAX_ERROR (2 * 1000)
/* ******** register bit ******** */
/* divider */
#define CRT_VID_DIV_MAX 255
#define DIV_PRE_SEL_MAX 6
#define EDP_DIV0_SEL_MAX 15
#define EDP_DIV1_SEL_MAX 8
/* g9tv, g9bb, gxbb divider */
#define CLK_DIV_I2O 0
#define CLK_DIV_O2I 1
enum div_sel_e {
CLK_DIV_SEL_1 = 0,
CLK_DIV_SEL_2, /* 1 */
CLK_DIV_SEL_3, /* 2 */
CLK_DIV_SEL_3p5, /* 3 */
CLK_DIV_SEL_3p75, /* 4 */
CLK_DIV_SEL_4, /* 5 */
CLK_DIV_SEL_5, /* 6 */
CLK_DIV_SEL_6, /* 7 */
CLK_DIV_SEL_6p25, /* 8 */
CLK_DIV_SEL_7, /* 9 */
CLK_DIV_SEL_7p5, /* 10 */
CLK_DIV_SEL_12, /* 11 */
CLK_DIV_SEL_14, /* 12 */
CLK_DIV_SEL_15, /* 13 */
CLK_DIV_SEL_2p5, /* 14 */
CLK_DIV_SEL_MAX,
};
/* GXTVBB */
/* ******** register bit ******** */
/* PLL_CNTL 0x10c8 */
#define LCD_PLL_LOCK_GXTVBB 31
#define LCD_PLL_EN_GXTVBB 30
#define LCD_PLL_RST_GXTVBB 28
#define LCD_PLL_N_GXTVBB 9
#define LCD_PLL_M_GXTVBB 0
#define LCD_PLL_OD3_GXTVBB 18
#define LCD_PLL_OD2_GXTVBB 22
#define LCD_PLL_OD1_GXTVBB 16
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXTVBB 0
#define SS_LEVEL_MAX_GXTVBB 5
#define PLL_M_MIN_GXTVBB 2
#define PLL_M_MAX_GXTVBB 511
#define PLL_N_MIN_GXTVBB 1
#define PLL_N_MAX_GXTVBB 1
#define PLL_FRAC_RANGE_GXTVBB (1 << 10)
#define PLL_OD_SEL_MAX_GXTVBB 3
#define PLL_FREF_MIN_GXTVBB (5 * 1000)
#define PLL_FREF_MAX_GXTVBB (25 * 1000)
#define PLL_VCO_MIN_GXTVBB (3000 * 1000)
#define PLL_VCO_MAX_GXTVBB (6000 * 1000)
/* video */
#define CLK_DIV_IN_MAX_GXTVBB (3100 * 1000)
#define CRT_VID_CLK_IN_MAX_GXTVBB (3100 * 1000)
#define ENCL_CLK_IN_MAX_GXTVBB (620 * 1000)
/* GXL */
/* ******** register bit ******** */
/* PLL_CNTL 0x10c8 */
#define LCD_PLL_LOCK_GXL 31
#define LCD_PLL_EN_GXL 30
#define LCD_PLL_RST_GXL 28
#define LCD_PLL_N_GXL 9
#define LCD_PLL_M_GXL 0
#define LCD_PLL_OD3_GXL 19
#define LCD_PLL_OD2_GXL 23
#define LCD_PLL_OD1_GXL 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXL 1
#define SS_LEVEL_MAX_GXL 5
#define PLL_M_MIN_GXL 2
#define PLL_M_MAX_GXL 511
#define PLL_N_MIN_GXL 1
#define PLL_N_MAX_GXL 1
#define PLL_FRAC_RANGE_GXL (1 << 10)
#define PLL_OD_SEL_MAX_GXL 3
#define PLL_FREF_MIN_GXL (5 * 1000)
#define PLL_FREF_MAX_GXL (25 * 1000)
#define PLL_VCO_MIN_GXL (3000 * 1000)
#define PLL_VCO_MAX_GXL (6000 * 1000)
/* video */
#define CLK_DIV_IN_MAX_GXL (3100 * 1000)
#define CRT_VID_CLK_IN_MAX_GXL (3100 * 1000)
#define ENCL_CLK_IN_MAX_GXL (620 * 1000)
/* GXM */
/* ******** register bit ******** */
/* PLL_CNTL 0x10c8 */
#define LCD_PLL_LOCK_GXM 31
#define LCD_PLL_EN_GXM 30
#define LCD_PLL_RST_GXM 28
#define LCD_PLL_N_GXM 9
#define LCD_PLL_M_GXM 0
#define LCD_PLL_OD3_GXM 19
#define LCD_PLL_OD2_GXM 23
#define LCD_PLL_OD1_GXM 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXM 1
#define SS_LEVEL_MAX_GXM 5
#define PLL_M_MIN_GXM 2
#define PLL_M_MAX_GXM 511
#define PLL_N_MIN_GXM 1
#define PLL_N_MAX_GXM 1
#define PLL_FRAC_RANGE_GXM (1 << 10)
#define PLL_OD_SEL_MAX_GXM 3
#define PLL_FREF_MIN_GXM (5 * 1000)
#define PLL_FREF_MAX_GXM (25 * 1000)
#define PLL_VCO_MIN_GXM (3000 * 1000)
#define PLL_VCO_MAX_GXM (6000 * 1000)
/* video */
#define CLK_DIV_IN_MAX_GXM (3100 * 1000)
#define CRT_VID_CLK_IN_MAX_GXM (3100 * 1000)
#define ENCL_CLK_IN_MAX_GXM (620 * 1000)
/* TXL */
/* ******** register bit ******** */
/* PLL_CNTL 0x10c8 */
#define LCD_PLL_LOCK_TXL 31
#define LCD_PLL_EN_TXL 30
#define LCD_PLL_RST_TXL 28
#define LCD_PLL_N_TXL 9
#define LCD_PLL_M_TXL 0
#define LCD_PLL_OD3_TXL 19
#define LCD_PLL_OD2_TXL 23
#define LCD_PLL_OD1_TXL 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_TXL 1
#define SS_LEVEL_MAX_TXL 5
#define PLL_M_MIN_TXL 2
#define PLL_M_MAX_TXL 511
#define PLL_N_MIN_TXL 1
#define PLL_N_MAX_TXL 1
#define PLL_FRAC_RANGE_TXL (1 << 10)
#define PLL_OD_SEL_MAX_TXL 3
#define PLL_FREF_MIN_TXL (5 * 1000)
#define PLL_FREF_MAX_TXL (25 * 1000)
#define PLL_VCO_MIN_TXL (3000 * 1000)
#define PLL_VCO_MAX_TXL (6000 * 1000)
/* video */
#define CLK_DIV_IN_MAX_TXL (3100 * 1000)
#define CRT_VID_CLK_IN_MAX_TXL (3100 * 1000)
#define ENCL_CLK_IN_MAX_TXL (620 * 1000)
/* TXLX */
/* ******** register bit ******** */
/* PLL_CNTL 0x10c8 */
#define LCD_PLL_LOCK_TXLX 31
#define LCD_PLL_EN_TXLX 30
#define LCD_PLL_RST_TXLX 28
#define LCD_PLL_N_TXLX 9
#define LCD_PLL_M_TXLX 0
#define LCD_PLL_OD3_TXLX 19
#define LCD_PLL_OD2_TXLX 23
#define LCD_PLL_OD1_TXLX 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_TXLX 0
#define SS_LEVEL_MAX_TXLX 6
#define PLL_M_MIN_TXLX 2
#define PLL_M_MAX_TXLX 511
#define PLL_N_MIN_TXLX 1
#define PLL_N_MAX_TXLX 1
#define PLL_FRAC_RANGE_TXLX (1 << 10)
#define PLL_OD_SEL_MAX_TXLX 3
#define PLL_FREF_MIN_TXLX (5 * 1000)
#define PLL_FREF_MAX_TXLX (25 * 1000)
#define PLL_VCO_MIN_TXLX (3000 * 1000)
#define PLL_VCO_MAX_TXLX (6000 * 1000)
/* video */
#define CLK_DIV_IN_MAX_TXLX (3100 * 1000)
#define CRT_VID_CLK_IN_MAX_TXLX (3100 * 1000)
#define ENCL_CLK_IN_MAX_TXLX (620 * 1000)
/* AXG */
/* ******** register bit ******** */
/* PLL_CNTL */
#define LCD_PLL_LOCK_AXG 31
#define LCD_PLL_EN_AXG 30
#define LCD_PLL_RST_AXG 29
#define LCD_PLL_OD_AXG 16
#define LCD_PLL_N_AXG 9
#define LCD_PLL_M_AXG 0
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_AXG 0
#define SS_LEVEL_MAX_AXG 5
#define PLL_M_MIN_AXG 2
#define PLL_M_MAX_AXG 511
#define PLL_N_MIN_AXG 1
#define PLL_N_MAX_AXG 1
#define PLL_FRAC_RANGE_AXG (1 << 10)
#define PLL_OD_SEL_MAX_AXG 3
#define PLL_FREF_MIN_AXG (5 * 1000)
#define PLL_FREF_MAX_AXG (25 * 1000)
#define PLL_VCO_MIN_AXG (1500 * 1000)
#define PLL_VCO_MAX_AXG (3000 * 1000)
/* video */
#define CRT_VID_CLK_IN_MAX_AXG (3000 * 1000)
#define ENCL_CLK_IN_MAX_AXG (200 * 1000)
extern int meson_clk_measure(unsigned int clk_mux);
extern struct lcd_clk_config_s *get_lcd_clk_config(void);
extern void lcd_clk_config_print(void);
extern int lcd_encl_clk_msr(void);
extern void lcd_pll_reset(void);
extern char *lcd_get_spread_spectrum(void);
extern void lcd_set_spread_spectrum(void);
extern void lcd_clk_update(struct lcd_config_s *pconf);
extern void lcd_clk_set(struct lcd_config_s *pconf);
extern void lcd_clk_disable(void);
extern void lcd_clk_generate_parameter(struct lcd_config_s *pconf);
extern void lcd_clk_config_probe(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_common.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 __AML_LCD_COMMON_H__
#define __AML_LCD_COMMON_H__
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#include "lcd_clk_config.h"
/* 20170505: add a113 support to linux4.9 */
#define LCD_DRV_VERSION "20170505"
#define VPP_OUT_SATURATE (1 << 0)
extern struct mutex lcd_power_mutex;
extern struct mutex lcd_vout_mutex;
extern unsigned char lcd_resume_flag;
extern int lcd_vout_serve_bypass;
/* lcd common */
extern int lcd_type_str_to_type(const char *str);
extern char *lcd_type_type_to_str(int type);
extern unsigned char lcd_mode_str_to_mode(const char *str);
extern char *lcd_mode_mode_to_str(int mode);
extern void lcd_cpu_gpio_register(unsigned int index);
extern void lcd_cpu_gpio_set(unsigned int index, int value);
extern unsigned int lcd_cpu_gpio_get(unsigned int index);
extern void lcd_ttl_pinmux_set(int status);
extern void lcd_vbyone_pinmux_set(int status);
extern unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf);
extern int lcd_power_load_from_dts(struct lcd_config_s *pconf,
struct device_node *child);
extern int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
unsigned char *buf, int key_len, int len);
extern void lcd_hdr_vinfo_update(void);
extern void lcd_tcon_config(struct lcd_config_s *pconf);
extern int lcd_vmode_change(struct lcd_config_s *pconf);
extern void lcd_venc_change(struct lcd_config_s *pconf);
extern void lcd_clk_gate_switch(int status);
extern void lcd_clktree_probe(void);
/* lcd debug */
extern int lcd_class_creat(void);
extern int lcd_class_remove(void);
/* lcd driver */
#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
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
menuconfig AMLOGIC_LCD_EXTERN
bool "LCD external driver support"
default n
help
Amlogic LCD external driver support, such as i2c initial
config AMLOGIC_LCD_EXTERN_I2C_T5800Q
bool "lcd external i2c T5800Q init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external i2c_T5800Q init driver support
Once the power on, according to the timing requirements,
through the i2c interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_I2C_DLPC3439
bool "lcd external i2c DLPC3439 init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external i2c_DLPC3439 init driver support
Once the power on, according to the timing requirements,
through the i2c interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_I2C_ANX6345
bool "lcd external i2c ANX6345 init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external i2c_ANX6345 init driver support
Once the power on, according to the timing requirements,
through the i2c interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_I2C_TC101
bool "lcd external i2c TC101 init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external i2c_TC101 init driver support
Once the power on, according to the timing requirements,
through the i2c interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_SPI_LD070WS2
bool "lcd external spi LD070WS2 init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external spi_LD070WS2 init driver support
Once the power on, according to the timing requirements,
through the spi interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_MIPI_KD080D13
bool "lcd external mipi KD080D13 init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external mipi_KD080D13 init driver support
Once the power on, according to the timing requirements,
through the mipi interface to write data to the LCD,
make its initialization
config AMLOGIC_LCD_EXTERN_MIPI_N070ICN
bool "lcd external mipi N070ICN init driver"
default n
depends on AMLOGIC_LCD_EXTERN
help
Amlogic LCD external mipi_N070ICN init driver support
Once the power on, according to the timing requirements,
through the mipi interface to write data to the LCD,
make its initialization

View File

@@ -0,0 +1,6 @@
obj-$(CONFIG_AMLOGIC_LCD_EXTERN) += lcd_extern.o ext_default.o
obj-$(CONFIG_AMLOGIC_LCD_EXTERN_I2C_T5800Q) += i2c_T5800Q.o
obj-$(CONFIG_AMLOGIC_LCD_EXTERN_SPI_LD070WS2) += spi_LD070WS2.o
obj-$(CONFIG_AMLOGIC_LCD_EXTERN_I2C_DLPC3439) += i2c_DLPC3439.o
obj-$(CONFIG_AMLOGIC_LCD_EXTERN_MIPI_KD080D13) += mipi_KD080D13.o

View File

@@ -0,0 +1,453 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#define LCD_EXTERN_INDEX 0
#define LCD_EXTERN_NAME "ext_default"
#define LCD_EXTERN_TYPE LCD_EXTERN_I2C
#define LCD_EXTERN_I2C_ADDR (0x1c) /* 7bit address */
#define LCD_EXTERN_I2C_ADDR2 (0xff) /* 7bit address */
#define LCD_EXTERN_I2C_BUS AML_I2C_MASTER_A
#define SPI_GPIO_CS 0 /* index */
#define SPI_GPIO_CLK 1 /* index */
#define SPI_GPIO_DATA 2 /* index */
#define SPI_CLK_FREQ 10000 /* Hz */
#define SPI_CLK_POL 1
static struct i2c_client *aml_default_i2c_client;
static struct i2c_client *aml_default_i2c2_client;
static struct lcd_extern_config_s *ext_config;
#define LCD_EXTERN_CMD_SIZE 9
static unsigned char init_on_table[] = {
0x00, 0x20, 0x01, 0x02, 0x00, 0x40, 0xFF, 0x00, 0x00,
0x00, 0x80, 0x02, 0x00, 0x40, 0x62, 0x51, 0x73, 0x00,
0x00, 0x61, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC1, 0x05, 0x0F, 0x00, 0x08, 0x70, 0x00, 0x00,
0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3D, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xED, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x23, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, /* delay 10ms */
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ending */
};
static unsigned char init_off_table[] = {
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ending */
};
static int lcd_extern_i2c_write(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int ret = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
}
};
ret = i2c_transfer(i2client->adapter, msg, 1);
if (ret < 0)
EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
return ret;
}
static int lcd_extern_reg_read(unsigned char reg, unsigned char *buf)
{
int ret = 0;
return ret;
}
static int lcd_extern_reg_write(unsigned char reg, unsigned char value)
{
int ret = 0;
return ret;
}
static int lcd_extern_spi_write(unsigned char *buf, int len)
{
EXTPR("to do\n");
return 0;
}
static int lcd_extern_power_cmd(unsigned char *init_table)
{
int i = 0, len;
int ret = 0;
len = ext_config->cmd_size;
if (len < 1) {
EXTERR("%s: cmd_size %d is invalid\n", __func__, len);
return -1;
}
if (len == LCD_EXTERN_DYNAMIC_LEN) {
switch (ext_config->type) {
case LCD_EXTERN_I2C:
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] ==
LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
if (init_table[i+1] > 0)
mdelay(init_table[i+1]);
i += 2;
} else if (init_table[i] ==
LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(
init_table[i+1],
init_table[i+2]);
}
if (init_table[i+3] > 0)
mdelay(init_table[i+3]);
i += 4;
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_i2c_write(
aml_default_i2c_client,
&init_table[i+2],
init_table[i+1]-1);
if (init_table[i+init_table[i+1]+1] > 0)
mdelay(init_table[i+
init_table[i+1]+1]);
i += (init_table[i+1] + 2);
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD2) {
ret = lcd_extern_i2c_write(
aml_default_i2c2_client,
&init_table[i+2],
init_table[i+1]-1);
if (init_table[i+init_table[i+1]+1] > 0)
mdelay(init_table[i+
init_table[i+1]+1]);
i += (init_table[i+1] + 2);
} else {
EXTERR("%s(%d: %s): type %d invalid\n",
__func__, ext_config->index,
ext_config->name,
ext_config->type);
}
}
break;
case LCD_EXTERN_SPI:
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] ==
LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
if (init_table[i+1] > 0)
mdelay(init_table[i+1]);
i += 2;
} else if (init_table[i] ==
LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(
init_table[i+1],
init_table[i+2]);
}
if (init_table[i+3] > 0)
mdelay(init_table[i+3]);
i += 4;
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_spi_write(
&init_table[i+2],
init_table[i+1]-1);
if (init_table[i+init_table[i+1]+1] > 0)
mdelay(init_table[i+
init_table[i+1]+1]);
i += (init_table[i+1] + 2);
} else {
EXTERR("%s(%d: %s): type %d invalid\n",
__func__, ext_config->index,
ext_config->name,
ext_config->type);
}
}
break;
default:
EXTERR("%s(%d: %s): extern_type %d is not support\n",
__func__, ext_config->index,
ext_config->name, ext_config->type);
break;
}
} else {
switch (ext_config->type) {
case LCD_EXTERN_I2C:
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] ==
LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
} else if (init_table[i] ==
LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(
init_table[i+1],
init_table[i+2]);
}
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_i2c_write(
aml_default_i2c_client,
&init_table[i+1], (len-2));
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD2) {
ret = lcd_extern_i2c_write(
aml_default_i2c2_client,
&init_table[i+1], (len-2));
} else {
EXTERR("%s(%d: %s): type %d invalid\n",
__func__, ext_config->index,
ext_config->name,
ext_config->type);
}
if (init_table[i+len-1] > 0)
mdelay(init_table[i+len-1]);
i += len;
}
break;
case LCD_EXTERN_SPI:
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] ==
LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
} else if (init_table[i] ==
LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(
init_table[i+1],
init_table[i+2]);
}
} else if (init_table[i] ==
LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_spi_write(
&init_table[i+1], (len-1));
} else {
EXTERR("%s(%d: %s): type %d invalid\n",
__func__, ext_config->index,
ext_config->name,
ext_config->type);
}
if (init_table[i+len-1] > 0)
mdelay(init_table[i+len-1]);
i += len;
}
break;
default:
EXTERR("%s(%d: %s): extern_type %d is not support\n",
__func__, ext_config->index,
ext_config->name, ext_config->type);
break;
}
}
return ret;
}
static int lcd_extern_power_ctrl(int flag)
{
int ret = 0;
if (flag)
ret = lcd_extern_power_cmd(ext_config->table_init_on);
else
ret = lcd_extern_power_cmd(ext_config->table_init_off);
EXTPR("%s(%d: %s): %d\n",
__func__, ext_config->index, ext_config->name, flag);
return ret;
}
static int lcd_extern_power_on(void)
{
int ret;
ret = lcd_extern_power_ctrl(1);
return ret;
}
static int lcd_extern_power_off(void)
{
int ret;
ret = lcd_extern_power_ctrl(0);
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
if (ext_drv == NULL) {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
return -1;
}
if (ext_drv->config.type == LCD_EXTERN_MAX) { /* default for no dts */
ext_drv->config.index = LCD_EXTERN_INDEX;
ext_drv->config.type = LCD_EXTERN_TYPE;
strcpy(ext_drv->config.name, LCD_EXTERN_NAME);
ext_drv->config.cmd_size = LCD_EXTERN_CMD_SIZE;
switch (ext_drv->config.type) {
case LCD_EXTERN_I2C:
ext_drv->config.i2c_addr = LCD_EXTERN_I2C_ADDR;
ext_drv->config.i2c_addr2 = LCD_EXTERN_I2C_ADDR2;
ext_drv->config.i2c_bus = LCD_EXTERN_I2C_BUS;
break;
case LCD_EXTERN_SPI:
ext_drv->config.spi_gpio_cs = SPI_GPIO_CS;
ext_drv->config.spi_gpio_clk = SPI_GPIO_CLK;
ext_drv->config.spi_gpio_data = SPI_GPIO_DATA;
ext_drv->config.spi_clk_freq = SPI_CLK_FREQ;
ext_drv->config.spi_clk_pol = SPI_CLK_POL;
break;
default:
break;
}
}
if (ext_drv->config.table_init_loaded == 0) {
ext_drv->config.table_init_on = init_on_table;
ext_drv->config.table_init_off = init_off_table;
}
ext_drv->reg_read = lcd_extern_reg_read;
ext_drv->reg_write = lcd_extern_reg_write;
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
return 0;
}
static int aml_default_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_default_i2c_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_default_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_default_i2c_id[] = {
{LCD_EXTERN_NAME, 0},
{ }
};
/* MODULE_DEVICE_TABLE(i2c, aml_T5800Q_id); */
static struct i2c_driver aml_default_i2c_driver = {
.probe = aml_default_i2c_probe,
.remove = aml_default_i2c_remove,
.id_table = aml_default_i2c_id,
.driver = {
.name = LCD_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
int aml_lcd_extern_default_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int ret = 0;
ext_config = &ext_drv->config;
switch (ext_drv->config.type) {
case LCD_EXTERN_I2C:
aml_default_i2c_client = NULL;
aml_default_i2c2_client = NULL;
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(ext_drv->config.i2c_bus);
if (!adapter) {
EXTERR("%s failed to get i2c adapter\n",
ext_drv->config.name);
return -1;
}
strncpy(i2c_info.type, ext_drv->config.name, I2C_NAME_SIZE);
i2c_info.addr = ext_drv->config.i2c_addr;
i2c_info.platform_data = &ext_drv->config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f) {
EXTERR("%s invalid i2c address: 0x%02x\n",
ext_drv->config.name, ext_drv->config.i2c_addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
EXTERR("%s failed to new i2c device\n",
ext_drv->config.name);
} else {
if (lcd_debug_print_flag) {
EXTPR("%s new i2c device succeed\n",
ext_drv->config.name);
}
}
if (!aml_default_i2c_client) {
ret = i2c_add_driver(&aml_default_i2c_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
break;
case LCD_EXTERN_SPI:
break;
default:
break;
}
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,198 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/i2c_DLPC3439.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#define LCD_EXTERN_NAME "i2c_DLPC3439"
static struct i2c_client *aml_DLPC3439_i2c_client;
static struct lcd_extern_config_s *ext_config;
/* Write: ImageCrop: 1920x1080
* W 36 10 00 00 00 00 80 07 38 04
*/
static unsigned char data_1[] = {0x10, 0x00, 0x00, 0x00, 0x00,
0x80, 0x07, 0x38, 0x04};
/* Write: DisplaySize: 1920x1080
* W 36 12 80 07 38 04
*/
static unsigned char data_2[] = {0x12, 0x80, 0x07, 0x38, 0x04};
/* Write: InputImageSize: 1920x1080
* W 36 2e 80 07 38 04
*/
static unsigned char data_3[] = {0x2e, 0x80, 0x07, 0x38, 0x04};
/* Write: InputSourceSelect; 0 = External Video Port
* W 36 05 00
*/
static unsigned char data_4[] = {0x05, 0x00};
/* Write: VideoSourceFormatSelect: 0x43=RGB888
* W 36 07 43
*/
static unsigned char data_5[] = {0x07, 0x43};
static int lcd_extern_i2c_write(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int ret = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
}
};
ret = i2c_transfer(i2client->adapter, msg, 1);
if (ret < 0)
EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
return ret;
}
static int lcd_extern_power_on(void)
{
int ret = 0;
lcd_extern_i2c_write(aml_DLPC3439_i2c_client, data_1, 9);
lcd_extern_i2c_write(aml_DLPC3439_i2c_client, data_2, 5);
lcd_extern_i2c_write(aml_DLPC3439_i2c_client, data_3, 5);
lcd_extern_i2c_write(aml_DLPC3439_i2c_client, data_4, 2);
lcd_extern_i2c_write(aml_DLPC3439_i2c_client, data_5, 2);
EXTPR("%s\n", __func__);
return ret;
}
static int lcd_extern_power_off(void)
{
int ret = 0;
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
if (ext_drv) {
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
} else {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
ret = -1;
}
return ret;
}
static int aml_DLPC3439_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_DLPC3439_i2c_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_DLPC3439_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_DLPC3439_i2c_id[] = {
{LCD_EXTERN_NAME, 0},
{ }
};
/* MODULE_DEVICE_TABLE(i2c, aml_DLPC3439_id); */
static struct i2c_driver aml_DLPC3439_i2c_driver = {
.probe = aml_DLPC3439_i2c_probe,
.remove = aml_DLPC3439_i2c_remove,
.id_table = aml_DLPC3439_i2c_id,
.driver = {
.name = LCD_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
int aml_lcd_extern_i2c_DLPC3439_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int ret = 0;
ext_config = &ext_drv->config;
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(ext_drv->config.i2c_bus);
if (!adapter) {
EXTERR("%s failed to get i2c adapter\n", ext_drv->config.name);
return -1;
}
strncpy(i2c_info.type, ext_drv->config.name, I2C_NAME_SIZE);
i2c_info.addr = ext_drv->config.i2c_addr;
i2c_info.platform_data = &ext_drv->config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f) {
EXTERR("%s invalid i2c address: 0x%02x\n",
ext_drv->config.name, ext_drv->config.i2c_addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
EXTERR("%s failed to new i2c device\n", ext_drv->config.name);
} else {
if (lcd_debug_print_flag) {
EXTPR("%s new i2c device succeed\n",
ext_drv->config.name);
}
}
if (!aml_DLPC3439_i2c_client) {
ret = i2c_add_driver(&aml_DLPC3439_i2c_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,365 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#define LCD_EXTERN_NAME "i2c_T5800Q"
static struct i2c_client *aml_T5800Q_i2c_client;
static struct lcd_extern_config_s *ext_config;
#define LCD_EXTERN_CMD_SIZE 9
static unsigned char init_on_table[] = {
0x00, 0x20, 0x01, 0x02, 0x00, 0x40, 0xFF, 0x00, 0x00,
0x00, 0x80, 0x02, 0x00, 0x40, 0x62, 0x51, 0x73, 0x00,
0x00, 0x61, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC1, 0x05, 0x0F, 0x00, 0x08, 0x70, 0x00, 0x00,
0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3D, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xED, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x23, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, /* delay 10ms */
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ending */
};
static unsigned char init_off_table[] = {
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ending */
};
static int lcd_extern_i2c_write(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int ret = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
}
};
ret = i2c_transfer(i2client->adapter, msg, 1);
if (ret < 0)
EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
return ret;
}
#if 0
static int lcd_extern_i2c_read(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
{
int ret = 0;
struct i2c_msg msgs[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = 1,
.buf = buff,
},
{
.addr = i2client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buff,
}
};
ret = i2c_transfer(i2client->adapter, msgs, 2);
if (ret < 0)
EXTERR("i2c read failed [addr 0x%02x]\n", i2client->addr);
return ret;
}
#endif
static int lcd_extern_reg_read(unsigned char reg, unsigned char *buf)
{
int ret = 0;
return ret;
}
static int lcd_extern_reg_write(unsigned char reg, unsigned char value)
{
int ret = 0;
return ret;
}
static int lcd_extern_power_cmd(unsigned char *init_table)
{
int i = 0, len;
int ret = 0;
len = ext_config->cmd_size;
if (len < 1) {
EXTERR("%s: cmd_size %d is invalid\n", __func__, len);
return -1;
}
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] == LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
} else if (init_table[i] == LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(init_table[i+1],
init_table[i+2]);
}
} else if (init_table[i] == LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_i2c_write(aml_T5800Q_i2c_client,
&init_table[i+1], (len-2));
} else {
EXTERR("%s(%d: %s): power_type %d is invalid\n",
__func__, ext_config->index,
ext_config->name, ext_config->type);
}
if (init_table[i+len-1] > 0)
mdelay(init_table[i+len-1]);
i += len;
}
return ret;
}
static int lcd_extern_power_ctrl(int flag)
{
int ret = 0;
if (flag)
ret = lcd_extern_power_cmd(ext_config->table_init_on);
else
ret = lcd_extern_power_cmd(ext_config->table_init_off);
EXTPR("%s(%d: %s): %d\n",
__func__, ext_config->index, ext_config->name, flag);
return ret;
}
static int lcd_extern_power_on(void)
{
int ret;
ret = lcd_extern_power_ctrl(1);
return ret;
}
static int lcd_extern_power_off(void)
{
int ret;
ret = lcd_extern_power_ctrl(0);
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
if (ext_drv == NULL) {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
return -1;
}
if (ext_drv->config.table_init_loaded == 0) {
ext_drv->config.table_init_on = init_on_table;
ext_drv->config.table_init_off = init_off_table;
}
ext_drv->reg_read = lcd_extern_reg_read;
ext_drv->reg_write = lcd_extern_reg_write;
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
return 0;
}
/* debug function */
static const char *lcd_extern_debug_usage_str = {
"Usage:\n"
" echo <reg> <> ... <> > write ; T5800Q i2c command write, 7 parameters without address\n"
};
static ssize_t lcd_extern_debug_help(struct class *class,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", lcd_extern_debug_usage_str);
}
static ssize_t lcd_extern_debug_write(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
unsigned int ret;
unsigned int temp[8];
unsigned char data[8];
int i;
memset(temp, 0, (sizeof(unsigned int) * 8));
ret = sscanf(buf, "%x %x %x %x %x %x %x",
&temp[0], &temp[1], &temp[2], &temp[3],
&temp[4], &temp[5], &temp[6]);
EXTPR("T5800Q i2c write:\n");
for (i = 0; i < 7; i++) {
data[i] = (unsigned char)temp[i];
pr_info("0x%02x ", data[i]);
}
pr_info("\n");
lcd_extern_i2c_write(aml_T5800Q_i2c_client, data, 7);
if (ret != 1 || ret != 2)
return -EINVAL;
return count;
}
static struct class_attribute lcd_extern_class_attrs[] = {
__ATTR(write, 0644,
lcd_extern_debug_help, lcd_extern_debug_write),
};
static struct class *debug_class;
static int creat_lcd_extern_class(void)
{
int i;
debug_class = class_create(THIS_MODULE, LCD_EXTERN_NAME);
if (IS_ERR(debug_class)) {
EXTERR("create debug class failed\n");
return -1;
}
for (i = 0; i < ARRAY_SIZE(lcd_extern_class_attrs); i++) {
if (class_create_file(debug_class,
&lcd_extern_class_attrs[i])) {
EXTERR("create debug attribute %s failed\n",
lcd_extern_class_attrs[i].attr.name);
}
}
return 0;
}
#if 0
static int remove_lcd_extern_class(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(lcd_extern_class_attrs); i++)
class_remove_file(debug_class, &lcd_extern_class_attrs[i]);
class_destroy(debug_class);
debug_class = NULL;
return 0;
}
#endif
/* ********************************************************* */
static int aml_T5800Q_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_T5800Q_i2c_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_T5800Q_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_T5800Q_i2c_id[] = {
{LCD_EXTERN_NAME, 0},
{ }
};
/* MODULE_DEVICE_TABLE(i2c, aml_T5800Q_id); */
static struct i2c_driver aml_T5800Q_i2c_driver = {
.probe = aml_T5800Q_i2c_probe,
.remove = aml_T5800Q_i2c_remove,
.id_table = aml_T5800Q_i2c_id,
.driver = {
.name = LCD_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
int aml_lcd_extern_i2c_T5800Q_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int ret = 0;
ext_config = &ext_drv->config;
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(ext_drv->config.i2c_bus);
if (!adapter) {
EXTERR("%s failed to get i2c adapter\n", ext_drv->config.name);
return -1;
}
strncpy(i2c_info.type, ext_drv->config.name, I2C_NAME_SIZE);
i2c_info.addr = ext_drv->config.i2c_addr;
i2c_info.platform_data = &ext_drv->config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f) {
EXTERR("%s invalid i2c address: 0x%02x\n",
ext_drv->config.name, ext_drv->config.i2c_addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
EXTERR("%s failed to new i2c device\n", ext_drv->config.name);
} else {
if (lcd_debug_print_flag) {
EXTPR("%s new i2c device succeed\n",
ext_drv->config.name);
}
}
if (!aml_T5800Q_i2c_client) {
ret = i2c_add_driver(&aml_T5800Q_i2c_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
ret = lcd_extern_driver_update(ext_drv);
creat_lcd_extern_class();
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,497 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/i2c_anx6345.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#include "i2c_anx6345.h"
static struct lcd_extern_config_s *ext_config;
static struct i2c_client *aml_anx6345_70_client;
static struct i2c_client *aml_anx6345_72_client;
const char *anx_addr_name[2] = {"anx6345_70", "anx6345_72"};
static unsigned int edp_tx_lane = 1;
#define LCD_EXTERN_NAME "lcd_anx6345"
static int aml_i2c_write(struct i2c_client *i2client, unsigned char *buff,
unsigned int len)
{
int ret = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
},
};
ret = i2c_transfer(i2client->adapter, msg, 1);
if (ret < 0) {
EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
}
return ret;
}
static int aml_i2c_read(struct i2c_client *i2client, unsigned char *buff,
unsigned int len)
{
int ret = 0;
struct i2c_msg msgs[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = 1,
.buf = buff,
},
{
.addr = i2client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buff,
},
};
ret = i2c_transfer(i2client->adapter, msgs, 2);
if (ret < 0) {
EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
}
return ret;
}
#if 0
static int i2c_reg_read(unsigned char reg, unsigned char *buf)
{
int ret = 0;
return ret;
}
static int i2c_reg_write(unsigned char reg, unsigned char value)
{
int ret = 0;
return ret;
}
#endif
static int SP_TX_Write_Reg(unsigned char addr, unsigned char reg,
unsigned char data)
{
struct i2c_client *client = aml_anx6345_70_client;
unsigned char buff[2];
int ret;
buff[0] = reg;
buff[1] = data;
if (addr == 0x70)
client = aml_anx6345_70_client;
else if (addr == 0x72)
client = aml_anx6345_72_client;
ret = aml_i2c_write(client, buff, 1);
return ret;
}
static int SP_TX_Read_Reg(unsigned char addr, unsigned char reg,
unsigned char *data)
{
struct i2c_client *client = aml_anx6345_70_client;
int ret;
*data = reg;
if (addr == 0x70)
client = aml_anx6345_70_client;
else if (addr == 0x72)
client = aml_anx6345_72_client;
ret = aml_i2c_read(client, data, 1);
return ret;
}
static int SP_TX_Wait_AUX_Finished(void)
{
unsigned char c;
unsigned char cCnt;
cCnt = 0;
SP_TX_Read_Reg(0x70, SP_TX_AUX_STATUS, &c);
while (c & 0x10) {/* aux busy */
cCnt++;
SP_TX_Read_Reg(0x70, SP_TX_AUX_STATUS, &c);
if (cCnt > 100)
return -1; /* aux fail */
}
return 0; /* aux ok */
}
static int SP_TX_AUX_DPCDRead_Bytes(unsigned char addrh, unsigned char addrm,
unsigned char addrl, unsigned char cCount, unsigned char *pBuf)
{
unsigned char c, i;
/* clr buffer */
SP_TX_Write_Reg(0x70, SP_TX_BUF_DATA_COUNT_REG, 0x80);
/* set read cmd and count */
SP_TX_Write_Reg(0x70, SP_TX_AUX_CTRL_REG, (((cCount-1) << 4) | 0x09));
/* set aux address15:0 */
SP_TX_Write_Reg(0x70, SP_TX_AUX_ADDR_7_0_REG, addrl);
SP_TX_Write_Reg(0x70, SP_TX_AUX_ADDR_15_8_REG, addrm);
/* set address19:16 and enable aux */
SP_TX_Read_Reg(0x70, SP_TX_AUX_ADDR_19_16_REG, &c);
SP_TX_Write_Reg(0x70, SP_TX_AUX_ADDR_19_16_REG, ((c & 0xf0) | addrh));
/* Enable Aux */
SP_TX_Read_Reg(0x70, SP_TX_AUX_CTRL_REG2, &c);
SP_TX_Write_Reg(0x70, SP_TX_AUX_CTRL_REG2, (c | 0x01));
mdelay(5);
if (SP_TX_Wait_AUX_Finished())
return -1;
for (i = 0; i < cCount; i++) {
SP_TX_Read_Reg(0x70, SP_TX_BUF_DATA_0_REG+i, &c);
*(pBuf+i) = c;
if (i >= MAX_BUF_CNT)
break;
}
return 0; /* aux ok */
}
static int lcd_extern_power_on(void)
{
unsigned int lane_num;
unsigned int link_rate;
unsigned char bits;
unsigned char device_id;
unsigned char temp;
unsigned char temp1;
unsigned int count = 0;
unsigned int count1 = 0;
lane_num = edp_tx_lane; /* 1 lane */
link_rate = VAL_EDP_TX_LINK_BW_SET_270; /* 2.7G */
bits = 0; /* 0x00: 6bit; 0x10:8bit */
SP_TX_Write_Reg(0x72, 0x05, 0x00);
SP_TX_Read_Reg(0x72, 0x01, &device_id);
if (device_id == 0xaa) {
EXTPR("ANX6345 Chip found\n\n");
} else {
EXTERR("ANX6345 Chip not found\n\n");
return -1;
}
temp = device_id;
/* if aux read fail, do h/w reset */
while (SP_TX_AUX_DPCDRead_Bytes(0x00, 0x00, 0x00, 1, &temp1) &&
(count < 200)) {
/* read fail, h/w reset */
SP_TX_Write_Reg(0x72, 0x06, 0x01);
SP_TX_Write_Reg(0x72, 0x06, 0x00);
SP_TX_Write_Reg(0x72, 0x05, 0x00);
mdelay(10);
count++;
}
/* software reset */
SP_TX_Read_Reg(0x72, SP_TX_RST_CTRL_REG, &temp);
SP_TX_Write_Reg(0x72, SP_TX_RST_CTRL_REG, (temp | SP_TX_RST_SW_RST));
SP_TX_Write_Reg(0x72, SP_TX_RST_CTRL_REG, (temp & ~SP_TX_RST_SW_RST));
/* EDID address for AUX access */
SP_TX_Write_Reg(0x70, SP_TX_EXTRA_ADDR_REG, 0x50);
/* disable HDCP polling mode. */
SP_TX_Write_Reg(0x70, SP_TX_HDCP_CTRL, 0x00);
/* Enable HDCP polling mode. */
/* SP_TX_Write_Reg(0x70, SP_TX_HDCP_CTRL, 0x02); */
/* enable M value read out */
SP_TX_Write_Reg(0x70, SP_TX_LINK_DEBUG_REG, 0x30);
/* SP_TX_Read_Reg(0x70, SP_TX_DEBUG_REG1, &temp); */
SP_TX_Write_Reg(0x70, SP_TX_DEBUG_REG1, 0x00); /*disable polling HPD */
SP_TX_Read_Reg(0x70, SP_TX_HDCP_CONTROL_0_REG, &temp);
/* set KSV valid */
SP_TX_Write_Reg(0x70, SP_TX_HDCP_CONTROL_0_REG, (temp | 0x03));
SP_TX_Read_Reg(0x70, SP_TX_AUX_CTRL_REG2, &temp);
/* set double AUX output */
SP_TX_Write_Reg(0x70, SP_TX_AUX_CTRL_REG2, (temp | 0x08));
/* unmask pll change int */
SP_TX_Write_Reg(0x72, SP_COMMON_INT_MASK1, 0xbf);
SP_TX_Write_Reg(0x72, SP_COMMON_INT_MASK2, 0xff);/* mask all int */
SP_TX_Write_Reg(0x72, SP_COMMON_INT_MASK3, 0xff);/* mask all int */
SP_TX_Write_Reg(0x72, SP_COMMON_INT_MASK4, 0xff);/* mask all int */
/* reset AUX */
SP_TX_Read_Reg(0x72, SP_TX_RST_CTRL2_REG, &temp);
SP_TX_Write_Reg(0x72, SP_TX_RST_CTRL2_REG, temp | SP_TX_AUX_RST);
SP_TX_Write_Reg(0x72, SP_TX_RST_CTRL2_REG, temp & (~SP_TX_AUX_RST));
/* Chip initialization */
SP_TX_Write_Reg(0x70, SP_TX_SYS_CTRL1_REG, 0x00);
mdelay(10);
SP_TX_Write_Reg(0x72, SP_TX_VID_CTRL2_REG, bits);
/* ANX6345 chip analog setting */
SP_TX_Write_Reg(0x70, SP_TX_PLL_CTRL_REG, 0x00);/* UPDATE: 0x07->0x00 */
/* ANX chip analog setting */
/* UPDATE: 0xF0->0X70 */
/* SP_TX_Write_Reg(0x72, ANALOG_DEBUG_REG1, 0x70); */
SP_TX_Write_Reg(0x70, SP_TX_LINK_DEBUG_REG, 0x30);
/* force HPD */
SP_TX_Write_Reg(0x70, SP_TX_SYS_CTRL3_REG, 0x30);
/* enable ssc function */
SP_TX_Write_Reg(0x70, 0xA7, 0x00); /* disable SSC first */
SP_TX_Write_Reg(0x70, 0xD0, 0x5f); /* ssc d 0.4%, f0/4 mode */
SP_TX_Write_Reg(0x70, 0xD1, 0x00);
SP_TX_Write_Reg(0x70, 0xD2, 0x75); /* ctrl_th */
SP_TX_Read_Reg(0x70, 0xA7, &temp);
SP_TX_Write_Reg(0x70, 0xA7, (temp | 0x10)); /* enable SSC */
SP_TX_Read_Reg(0x72, 0x07, &temp); /* reset SSC */
SP_TX_Write_Reg(0x72, 0x07, (temp | 0x80));
SP_TX_Write_Reg(0x72, 0x07, (temp & (~0x80)));
/* Select 2.7G */
/* 2.7g:0x0a; 1.62g:0x06 */
SP_TX_Write_Reg(0x70, SP_TX_LINK_BW_SET_REG, link_rate);
/* Select 2 lanes */
SP_TX_Write_Reg(0x70, 0xa1, lane_num);
SP_TX_Write_Reg(0x70, SP_TX_LINK_TRAINING_CTRL_REG,
SP_TX_LINK_TRAINING_CTRL_EN);
mdelay(5);
SP_TX_Read_Reg(0x70, SP_TX_LINK_TRAINING_CTRL_REG, &temp);
/* UPDATE: FROM 0X01 TO 0X80 */
while ((temp & 0x80) != 0) {
/* debug_puts("Waiting...\n"); */
mdelay(5);
count1++;
if (count1 > 100) {
EXTERR("ANX6345 Link training fail\n");
break;
}
SP_TX_Read_Reg(0x70, SP_TX_LINK_TRAINING_CTRL_REG, &temp);
}
SP_TX_Write_Reg(0x72, 0x12, 0x2c);
SP_TX_Write_Reg(0x72, 0x13, 0x06);
SP_TX_Write_Reg(0x72, 0x14, 0x00);
SP_TX_Write_Reg(0x72, 0x15, 0x06);
SP_TX_Write_Reg(0x72, 0x16, 0x02);
SP_TX_Write_Reg(0x72, 0x17, 0x04);
SP_TX_Write_Reg(0x72, 0x18, 0x26);
SP_TX_Write_Reg(0x72, 0x19, 0x50);
SP_TX_Write_Reg(0x72, 0x1a, 0x04);
SP_TX_Write_Reg(0x72, 0x1b, 0x00);
SP_TX_Write_Reg(0x72, 0x1c, 0x04);
SP_TX_Write_Reg(0x72, 0x1d, 0x18);
SP_TX_Write_Reg(0x72, 0x1e, 0x00);
SP_TX_Write_Reg(0x72, 0x1f, 0x10);
SP_TX_Write_Reg(0x72, 0x20, 0x00);
SP_TX_Write_Reg(0x72, 0x21, 0x28);
SP_TX_Write_Reg(0x72, 0x11, 0x03);
/* enable BIST. In normal mode, don't need to config this reg
* if want to open BIST, must setting
* right dat 0x11-0x21 base lcd timing.
*/
/* SP_TX_Write_Reg(0x72, 0x0b, 0x09); //colorbar:08,graystep:09 */
SP_TX_Write_Reg(0x72, 0x08, 0x81); /* SDR:0x81;DDR:0x8f */
/* force HPD and stream valid */
SP_TX_Write_Reg(0x70, 0x82, 0x33);
EXTPR("%s\n", __func__);
return 0;
}
static int lcd_extern_power_off(void)
{
int ret = 0;
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
if (ext_drv) {
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
} else {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
ret = -1;
}
return ret;
}
static int aml_anx6345_70_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_anx6345_70_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_anx6345_72_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_anx6345_72_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_anx6345_70_remove(struct i2c_client *client)
{
return 0;
}
static int aml_anx6345_72_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_anx6345_70_id[] = {
{"anx6345_70", 0},
{ }
};
static const struct i2c_device_id aml_anx6345_72_id[] = {
{"anx6345_72", 0},
{ }
};
/* MODULE_DEVICE_TABLE(i2c, aml_tc101_id); */
static struct i2c_driver aml_anx6345_70_driver = {
.probe = aml_anx6345_70_probe,
.remove = aml_anx6345_70_remove,
.id_table = aml_anx6345_70_id,
.driver = {
.name = "anx6345_70",
.owner = THIS_MODULE,
},
};
static struct i2c_driver aml_anx6345_72_driver = {
.probe = aml_anx6345_72_probe,
.remove = aml_anx6345_72_remove,
.id_table = aml_anx6345_72_id,
.driver = {
.name = "anx6345_72",
.owner = THIS_MODULE,
},
};
int aml_lcd_extern_i2c_anx6345_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
struct i2c_board_info i2c_info[2];
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int i = 0;
int ret = 0;
ext_config = &ext_drv->config;
for (i = 0; i < 2; i++)
memset(&i2c_info[i], 0, sizeof(i2c_info[i]));
adapter = i2c_get_adapter(ext_config->i2c_bus);
if (!adapter) {
EXTERR("%s failed to get i2c adapter\n", ext_drv->config.name);
return -1;
}
i2c_info[0].addr = 0x38; /* 0x70 >> 1; */
i2c_info[1].addr = 0x39; /* 0x72 >> 1; */
for (i = 0; i < 2; i++) {
strncpy(i2c_info[i].type, anx_addr_name[i], I2C_NAME_SIZE);
/* i2c_info[i].platform_data = &ext_drv->config; */
i2c_info[i].flags = 0;
if (i2c_info[i].addr > 0x7f) {
EXTERR("%s invalid i2c address: 0x%02x\n",
ext_drv->config.name, i2c_info[i].addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info[i]);
if (!i2c_client) {
EXTERR("%s failed to new i2c device\n",
ext_drv->config.name);
} else {
if (lcd_debug_print_flag) {
EXTPR("%s new i2c device succeed\n",
ext_drv->config.name);
}
}
}
if (!aml_anx6345_70_client) {
ret = i2c_add_driver(&aml_anx6345_70_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
if (!aml_anx6345_72_client) {
ret = i2c_add_driver(&aml_anx6345_72_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,716 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/i2c_anx6345.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 EDP_ANX6345_H
#define EDP_ANX6345_H
/* ************************************************************* */
#define SP_TX_PORT0_ADDR 0x70
#define SP_TX_PORT1_ADDR 0x74
#define SP_TX_PORT2_ADDR 0x72
#define MIPI_RX_PORT1_ADDR 0x7A
#define MAX_BUF_CNT 6
#define CR_LOOP_TIME 5
#define EQ_LOOP_TIME 5
#define SP_TX_AVI_SEL 0x01
#define SP_TX_SPD_SEL 0x02
#define SP_TX_MPEG_SEL 0x04
#define VAL_EDP_TX_LINK_BW_SET_162 0x06
#define VAL_EDP_TX_LINK_BW_SET_270 0x0a
#define VAL_EDP_TX_LINK_BW_SET_540 0x14
/* End for DEV_addr 0x7A/0x7E */
/* ************************************************************* */
/* DEV_ADDR = 0x70 or 0x78 , Displayport mode and HDCP registers */
#define SP_TX_HDCP_STATUS 0x00
/* bit position */
#define SP_TX_HDCP_AUTH_PASS 0x02
#define SP_TX_HDCP_CONTROL_0_REG 0x01
/* bit position */
#define SP_TX_HDCP_CONTROL_0_STORE_AN 0x80
#define SP_TX_HDCP_CONTROL_0_RX_REPEATER 0x40
#define SP_TX_HDCP_CONTROL_0_RE_AUTH 0x20
#define SP_TX_HDCP_CONTROL_0_SW_AUTH_OK 0x10
#define SP_TX_HDCP_CONTROL_0_HARD_AUTH_EN 0x08
#define SP_TX_HDCP_CONTROL_0_HDCP_ENC_EN 0x04
#define SP_TX_HDCP_CONTROL_0_BKSV_SRM_PASS 0x02
#define SP_TX_HDCP_CONTROL_0_KSVLIST_VLD 0x01
#define SP_TX_HDCP_CONTROL_1_REG 0x02
/* bit position */
#define SP_TX_HDCP_CONTROL_1_DDC_NO_STOP 0x20
#define SP_TX_HDCP_CONTROL_1_DDC_NO_ACK 0x10
#define SP_TX_HDCP_CONTROL_1_EDDC_NO_ACK 0x08
/* #define SP_TX_HDCP_CONTROL_1_HDCP_EMB_SCREEN_EN 0x04 */
#define SP_TX_HDCP_CONTROL_1_RCV_11_EN 0x02
#define SP_TX_HDCP_CONTROL_1_HDCP_11_EN 0x01
#define SP_TX_HDCP_LINK_CHK_FRAME_NUM 0x03
#define SP_TX_HDCP_CONTROL_2_REG 0x04
#define SP_TX_HDCP_AKSV0 0x05
#define SP_TX_HDCP_AKSV1 0x06
#define SP_TX_HDCP_AKSV2 0x07
#define SP_TX_HDCP_AKSV3 0x08
#define SP_TX_HDCP_AKSV4 0x09
/* AKSV */
#define SP_TX_HDCP_AN0 0x0A
#define SP_TX_HDCP_AN1 0x0B
#define SP_TX_HDCP_AN2 0x0C
#define SP_TX_HDCP_AN3 0x0D
#define SP_TX_HDCP_AN4 0x0E
#define SP_TX_HDCP_AN5 0x0F
#define SP_TX_HDCP_AN6 0x10
#define SP_TX_HDCP_AN7 0x11
/* BKSV */
#define SP_TX_HDCP_BKSV0 0x12
#define SP_TX_HDCP_BKSV1 0x13
#define SP_TX_HDCP_BKSV2 0x14
#define SP_TX_HDCP_BKSV3 0x15
#define SP_TX_HDCP_BKSV4 0x16
#define SP_TX_HDCP_R0_L 0x17
#define SP_TX_HDCP_R0_H 0x18
#ifndef M_VID_0
#define M_VID_0 0xC0
#define M_VID_1 0xC1
#define M_VID_2 0xC2
#define N_VID_0 0xC3
#define N_VID_1 0xC4
#define N_VID_2 0xC5
#endif
#define SP_TX_HDCP_R0_WAIT_Timer 0x40
#define SP_TX_SYS_CTRL1_REG 0x80
/* bit position */
/* #define SP_TX_SYS_CTRL1_PD_IO 0x80 */
/* #define SP_TX_SYS_CTRL1_PD_VID 0x40 */
/* #define SP_TX_SYS_CTRL1_PD_LINK 0x20 */
/* #define SP_TX_SYS_CTRL1_PD_TOTAL 0x10 */
/* #define SP_TX_SYS_CTRL1_MODE_SEL 0x08 */
#define SP_TX_SYS_CTRL1_DET_STA 0x04
#define SP_TX_SYS_CTRL1_FORCE_DET 0x02
#define SP_TX_SYS_CTRL1_DET_CTRL 0x01
#define SP_TX_SYS_CTRL2_REG 0x81
/* bit position */
/* #define SP_TX_SYS_CTRL2_ENHANCED 0x08 */
#define SP_TX_SYS_CTRL2_CHA_STA 0x04
#define SP_TX_SYS_CTRL2_FORCE_CHA 0x02
#define SP_TX_SYS_CTRL2_CHA_CTRL 0x01
#define SP_TX_SYS_CTRL3_REG 0x82
/* bit position */
#define SP_TX_SYS_CTRL3_HPD_STATUS 0x40
#define SP_TX_SYS_CTRL3_F_HPD 0x20
#define SP_TX_SYS_CTRL3_HPD_CTRL 0x10
#define SP_TX_SYS_CTRL3_STRM_VALID 0x04
#define SP_TX_SYS_CTRL3_F_VALID 0x02
#define SP_TX_SYS_CTRL3_VALID_CTRL 0x01
#define SP_TX_SYS_CTRL4_REG 0x83
/* bit position */
#define SP_TX_SYS_CTRL4_ENHANCED 0x08
#define SP_TX_VID_CTRL 0x84
#define SP_TX_AUD_CTRL 0x87
/* bit position */
#define SP_TX_AUD_CTRL_AUD_EN 0x01
#define SP_TX_PKT_EN_REG 0x90
/* bit position */
#define SP_TX_PKT_AUD_UP 0x80
#define SP_TX_PKT_AVI_UD 0x40
#define SP_TX_PKT_MPEG_UD 0x20
#define SP_TX_PKT_SPD_UD 0x10
#define SP_TX_PKT_AUD_EN 0x08
#define SP_TX_PKT_AVI_EN 0x04
#define SP_TX_PKT_MPEG_EN 0x02
#define SP_TX_PKT_SPD_EN 0x01
#define SP_TX_HDCP_CTRL 0x92
#define SP_TX_LINK_BW_SET_REG 0xA0
#define SP_TX_LANE_COUNT_SET_REG 0xA1
#define SP_TX_TRAINING_PTN_SET_REG 0xA2
/* bit position */
#define SP_TX_SCRAMBLE_DISABLE 0x20
#define SP_TX_TRAINING_LANE0_SET_REG 0xA3
/* bit position */
#define SP_TX_TRAINING_LANE0_SET_MAX_PRE_REACH 0x20
#define SP_TX_TRAINING_LANE0_SET_MAX_DRIVE_REACH 0x04
#define SP_TX_TRAINING_LANE1_SET_REG 0xA4
#define SSC_CTRL_REG1 0xA7
/* bit position */
#define SPREAD_AMP 0x10
#define MODULATION_FREQ 0x01
#define SP_TX_LINK_TRAINING_CTRL_REG 0xA8
/* bit position */
#define SP_TX_LINK_TRAINING_CTRL_EN 0x01
#define SP_TX_DEBUG_REG1 0xB0
/* bit position */
#define SP_TX_DEBUG_HPD_POLLING_DET 0x40
#define SP_TX_DEBUG_HPD_POLLING_EN 0x20
#define SP_TX_DEBUG_PLL_LOCK 0x10
#define SP_TX_LINK_DEBUG_REG 0xB8
/* bit position */
#define SP_TX_LINK_DEBUG_INSERT_ER 0x02
#define SP_TX_LINK_DEBUG_PRBS31_EN 0x01
#define SP_TX_SINK_COUNT_REG 0xB9
#define SP_TX_LINK_STATUS_REG1 0xBB
#define SP_TX_SINK_STATUS_REG 0xBE
/* bit position */
#define SP_TX_SINK_STATUS_SINK_STATUS_1 0x02
#define SP_TX_SINK_STATUS_SINK_STATUS_0 0x01
/* #define SP_TX_LINK_TEST_COUNT 0xC0 */
#define SP_TX_PLL_CTRL_REG 0xC7
/* bit position */
#define SP_TX_PLL_CTRL_PLL_PD 0x80
#define SP_TX_PLL_CTRL_PLL_RESET 0x40
/* #define SP_TX_PLL_CTRL_CPREG_BLEED 0x08 */
#define SP_TX_ANALOG_POWER_DOWN_REG 0xC8
/* bit position */
#define SP_TX_ANALOG_POWER_DOWN_MACRO_PD 0x20
#define SP_TX_ANALOG_POWER_DOWN_AUX_PD 0x10
/* #define SP_TX_ANALOG_POWER_DOWN_CH3_PD 0x08 */
/* #define SP_TX_ANALOG_POWER_DOWN_CH2_PD 0x04 */
#define SP_TX_ANALOG_POWER_DOWN_CH1_PD 0x02
#define SP_TX_ANALOG_POWER_DOWN_CH0_PD 0x01
#define SP_TX_ANALOG_TEST_REG 0xC9
/* bit position */
#define SP_TX_ANALOG_TEST_MACRO_RST 0x20
#define SP_TX_ANALOG_TEST_PLL_TEST 0x10
#define SP_TX_ANALOG_TEST_CH3_TEST 0x08
#define SP_TX_ANALOG_TEST_CH2_TEST 0x04
#define SP_TX_ANALOG_TEST_CH1_TEST 0x02
#define SP_TX_ANALOG_TEST_CH0_TEST 0x01
#define SP_TX_GNS_CTRL_REG 0xCD
/* bit position */
#define SP_EQ_LOOP_CNT 0x40
#define SP_TX_VIDEO_MAP_CTRL 0x02
#define SP_TX_RS_CTRL 0x01
#define SP_TX_DOWN_SPREADING_CTRL1 0xD0
#define SP_TX_DOWN_SPREADING_CTRL2 0xD1
#define SP_TX_DOWN_SPREADING_CTRL3 0xD2
/* bit position */
#define SP_TX_SSC_D_CTRL 0x40
#define SP_TX_FS_CTRL_TH_CTRL 0x20
#define SP_TX_M_CALCU_CTRL 0xD9
/* bit position */
#define M_GEN_CLK_SEL 0x01
#define SP_TX_EXTRA_ADDR_REG 0xCE
#define SP_TX_I2C_STRETCH_CTRL_REG 0xDB
#define SP_TX_AUX_STATUS 0xE0
#define SP_TX_DEFER_CTRL_REG 0xE2
/* bit position */
#define SP_TXL_DEFER_CTRL_EN 0x80
#define SP_TX_BUF_DATA_COUNT_REG 0xE4
#define SP_TX_AUX_CTRL_REG 0xE5
/* bit position */
#define SP_TX_MOT_BIT 0x04
#define SP_TX_AUX_ADDR_7_0_REG 0xE6
#define SP_TX_AUX_ADDR_15_8_REG 0xE7
#define SP_TX_AUX_ADDR_19_16_REG 0xE8
#define SP_TX_AUX_CTRL_REG2 0xE9
/* bit position */
#define SP_TX_ADDR_ONLY_BIT 0x02
#define SP_TX_BUF_DATA_0_REG 0xf0
#define SP_TX_BUF_DATA_1_REG 0xf1
#define SP_TX_BUF_DATA_2_REG 0xf2
#define SP_TX_BUF_DATA_3_REG 0xf3
#define SP_TX_BUF_DATA_4_REG 0xf4
#define SP_TX_BUF_DATA_5_REG 0xf5
#define SP_TX_BUF_DATA_6_REG 0xf6
#define SP_TX_BUF_DATA_7_REG 0xf7
#define SP_TX_BUF_DATA_8_REG 0xf8
#define SP_TX_BUF_DATA_9_REG 0xf9
#define SP_TX_BUF_DATA_10_REG 0xfa
#define SP_TX_BUF_DATA_11_REG 0xfb
#define SP_TX_BUF_DATA_12_REG 0xfc
#define SP_TX_BUF_DATA_13_REG 0xfd
#define SP_TX_BUF_DATA_14_REG 0xfe
#define SP_TX_BUF_DATA_15_REG 0xff
/* End for Address 0x70 or 0x78 */
/* ************************************************************* */
/* DEV_ADDR = 0x72 or 0x76, System control registers */
#define SP_TX_VND_IDL_REG 0x00
#define SP_TX_VND_IDH_REG 0x01
#define SP_TX_DEV_IDL_REG 0x02
#define SP_TX_DEV_IDH_REG 0x03
#define SP_TX_DEV_REV_REG 0x04
#define SP_POWERD_CTRL_REG 0x05
/* bit position */
#define SP_POWERD_REGISTER_REG 0x80
/* #define SP_POWERD_MISC_REG 0x40 */
#define SP_POWERD_IO_REG 0x20
#define SP_POWERD_AUDIO_REG 0x10
#define SP_POWERD_VIDEO_REG 0x08
#define SP_POWERD_LINK_REG 0x04
#define SP_POWERD_TOTAL_REG 0x02
#define SP_MODE_SEL_REG 0x01
#define SP_TX_RST_CTRL_REG 0x06
#define SP_TX_RST_MISC_REG 0x80
#define SP_TX_RST_VIDCAP_REG 0x40
#define SP_TX_RST_VIDFIF_REG 0x20
#define SP_TX_RST_AUDFIF_REG 0x10
#define SP_TX_RST_AUDCAP_REG 0x08
#define SP_TX_RST_HDCP_REG 0x04
#define SP_TX_RST_SW_RST 0x02
#define SP_TX_RST_HW_RST 0x01
#define SP_TX_RST_CTRL2_REG 0x07
#define SP_TX_RST_SSC 0x80
#define SP_TX_AC_MODE 0x40
/* #define SP_TX_DDC_RST 0x10 */
/* #define SP_TX_TMDS_BIST_RST 0x08 */
#define SP_TX_AUX_RST 0x04
#define SP_TX_SERDES_FIFO_RST 0x02
#define SP_TX_I2C_REG_RST 0x01
#define SP_TX_VID_CTRL1_REG 0x08
/* bit position */
#define SP_TX_VID_CTRL1_VID_EN 0x80
#define SP_TX_VID_CTRL1_VID_MUTE 0x40
#define SP_TX_VID_CTRL1_DE_GEN 0x20
#define SP_TX_VID_CTRL1_DEMUX 0x10
#define SP_TX_VID_CTRL1_IN_BIT 0x04
#define SP_TX_VID_CTRL1_DDRCTRL 0x02
#define SP_TX_VID_CTRL1_EDGE 0x01
#define SP_TX_VID_CTRL2_REG 0x09
/* bit position */
#define SP_TX_VID_CTRL1_YCBIT_SEL 0x04
#define SP_TX_VID_CTRL3_REG 0x0A
#define SP_TX_VID_CTRL4_REG 0x0B
/* bit position */
#define SP_TX_VID_CTRL4_E_SYNC_EN 0x80
#define SP_TX_VID_CTRL4_EX_E_SYNC 0x40
#define SP_TX_VID_CTRL4_BIST 0x08
#define SP_TX_VID_CTRL4_BIST_WIDTH 0x04
#define SP_TX_VID_CTRL5_REG 0x0C
#define SP_TX_VID_CTRL6_REG 0x0D
/* bit position */
#define SP_TX_VID_UPSAMPLE 0x02
#define SP_TX_VID_CTRL7_REG 0x0E
#define SP_TX_VID_CTRL8_REG 0x0F
#define SP_TX_VID_CTRL9_REG 0x10
#define SP_TX_VID_CTRL10_REG 0x11
/* bit position */
#define SP_TX_VID_CTRL10_INV_F 0x08
#define SP_TX_VID_CTRL10_I_SCAN 0x04
#define SP_TX_VID_CTRL10_VSYNC_POL 0x02
#define SP_TX_VID_CTRL10_HSYNC_POL 0x01
#define SP_TX_TOTAL_LINEL_REG 0x12
#define SP_TX_TOTAL_LINEH_REG 0x13
#define SP_TX_ACT_LINEL_REG 0x14
#define SP_TX_ACT_LINEH_REG 0x15
#define SP_TX_VF_PORCH_REG 0x16
#define SP_TX_VSYNC_CFG_REG 0x17
#define SP_TX_VB_PORCH_REG 0x18
#define SP_TX_TOTAL_PIXELL_REG 0x19
#define SP_TX_TOTAL_PIXELH_REG 0x1A
#define SP_TX_ACT_PIXELL_REG 0x1B
#define SP_TX_ACT_PIXELH_REG 0x1C
#define SP_TX_HF_PORCHL_REG 0x1D
#define SP_TX_HF_PORCHH_REG 0x1E
#define SP_TX_HSYNC_CFGL_REG 0x1F
#define SP_TX_HSYNC_CFGH_REG 0x20
#define SP_TX_HB_PORCHL_REG 0x21
#define SP_TX_HB_PORCHH_REG 0x22
#define SP_TX_VID_STATUS 0x23
#define SP_TX_TOTAL_LINE_STA_L 0x24
#define SP_TX_TOTAL_LINE_STA_H 0x25
#define SP_TX_ACT_LINE_STA_L 0x26
#define SP_TX_ACT_LINE_STA_H 0x27
#define SP_TX_V_F_PORCH_STA 0x28
#define SP_TX_V_SYNC_STA 0x29
#define SP_TX_V_B_PORCH_STA 0x2A
#define SP_TX_TOTAL_PIXEL_STA_L 0x2B
#define SP_TX_TOTAL_PIXEL_STA_H 0x2C
#define SP_TX_ACT_PIXEL_STA_L 0x2D
#define SP_TX_ACT_PIXEL_STA_H 0x2E
#define SP_TX_H_F_PORCH_STA_L 0x2F
#define SP_TX_H_F_PORCH_STA_H 0x30
#define SP_TX_H_SYNC_STA_L 0x31
#define SP_TX_H_SYNC_STA_H 0x32
#define SP_TX_H_B_PORCH_STA_L 0x33
#define SP_TX_H_B_PORCH_STA_H 0x34
#define SP_TX_Video_Interface_BIST 0x35
#define SPDIF_AUDIO_CTRL0 0x36
/* bit position */
#define SPDIF_AUDIO_CTRL0_SPDIF_IN 0x80
#define SPDIF_AUDIO_STATUS0 0x38
#define SPDIF_AUDIO_STATUS0_CLK_DET 0x80
#define SPDIF_AUDIO_STATUS0_AUD_DET 0x01
#define SPDIF_AUDIO_STATUS1 0x39
#define AUDIO_BIST_CTRL 0x3c
#define AUDIO_BIST_EN 0x01
/* #define AUDIO_BIST_CHANNEL_STATUS1 0xd0 */
/* #define AUDIO_BIST_CHANNEL_STATUS2 0xd1 */
/* #define AUDIO_BIST_CHANNEL_STATUS3 0xd2 */
/* #define AUDIO_BIST_CHANNEL_STATUS4 0xd3 */
/* #define AUDIO_BIST_CHANNEL_STATUS5 0xd4 */
#define SP_TX_VIDEO_BIT_CTRL_0_REG 0x40
#define SP_TX_VIDEO_BIT_CTRL_1_REG 0x41
#define SP_TX_VIDEO_BIT_CTRL_2_REG 0x42
#define SP_TX_VIDEO_BIT_CTRL_3_REG 0x43
#define SP_TX_VIDEO_BIT_CTRL_4_REG 0x44
#define SP_TX_VIDEO_BIT_CTRL_5_REG 0x45
#define SP_TX_VIDEO_BIT_CTRL_6_REG 0x46
#define SP_TX_VIDEO_BIT_CTRL_7_REG 0x47
#define SP_TX_VIDEO_BIT_CTRL_8_REG 0x48
#define SP_TX_VIDEO_BIT_CTRL_9_REG 0x49
#define SP_TX_VIDEO_BIT_CTRL_10_REG 0x4a
#define SP_TX_VIDEO_BIT_CTRL_11_REG 0x4b
#define SP_TX_VIDEO_BIT_CTRL_12_REG 0x4c
#define SP_TX_VIDEO_BIT_CTRL_13_REG 0x4d
#define SP_TX_VIDEO_BIT_CTRL_14_REG 0x4e
#define SP_TX_VIDEO_BIT_CTRL_15_REG 0x4f
#define SP_TX_VIDEO_BIT_CTRL_16_REG 0x50
#define SP_TX_VIDEO_BIT_CTRL_17_REG 0x51
#define SP_TX_VIDEO_BIT_CTRL_18_REG 0x52
#define SP_TX_VIDEO_BIT_CTRL_19_REG 0x53
#define SP_TX_VIDEO_BIT_CTRL_20_REG 0x54
#define SP_TX_VIDEO_BIT_CTRL_21_REG 0x55
#define SP_TX_VIDEO_BIT_CTRL_22_REG 0x56
#define SP_TX_VIDEO_BIT_CTRL_23_REG 0x57
#define SP_TX_VIDEO_BIT_CTRL_24_REG 0x58
#define SP_TX_VIDEO_BIT_CTRL_25_REG 0x59
#define SP_TX_VIDEO_BIT_CTRL_26_REG 0x5a
#define SP_TX_VIDEO_BIT_CTRL_27_REG 0x5b
#define SP_TX_VIDEO_BIT_CTRL_28_REG 0x5c
#define SP_TX_VIDEO_BIT_CTRL_29_REG 0x5d
#define SP_TX_VIDEO_BIT_CTRL_30_REG 0x5e
#define SP_TX_VIDEO_BIT_CTRL_31_REG 0x5f
#define SP_TX_VIDEO_BIT_CTRL_32_REG 0x60
#define SP_TX_VIDEO_BIT_CTRL_33_REG 0x61
#define SP_TX_VIDEO_BIT_CTRL_34_REG 0x62
#define SP_TX_VIDEO_BIT_CTRL_35_REG 0x63
#define SP_TX_VIDEO_BIT_CTRL_36_REG 0x64
#define SP_TX_VIDEO_BIT_CTRL_37_REG 0x65
#define SP_TX_VIDEO_BIT_CTRL_38_REG 0x66
#define SP_TX_VIDEO_BIT_CTRL_39_REG 0x67
#define SP_TX_VIDEO_BIT_CTRL_40_REG 0x68
#define SP_TX_VIDEO_BIT_CTRL_41_REG 0x69
#define SP_TX_VIDEO_BIT_CTRL_42_REG 0x6a
#define SP_TX_VIDEO_BIT_CTRL_43_REG 0x6b
#define SP_TX_VIDEO_BIT_CTRL_44_REG 0x6c
#define SP_TX_VIDEO_BIT_CTRL_45_REG 0x6d
#define SP_TX_VIDEO_BIT_CTRL_46_REG 0x6e
#define SP_TX_VIDEO_BIT_CTRL_47_REG 0x6f
/* AVI info frame */
#define SP_TX_AVI_TYPE 0x70
#define SP_TX_AVI_VER 0x71
#define SP_TX_AVI_LEN 0x72
#define SP_TX_AVI_DB0 0x73
#define SP_TX_AVI_DB1 0x74
#define SP_TX_AVI_DB2 0x75
#define SP_TX_AVI_DB3 0x76
#define SP_TX_AVI_DB4 0x77
#define SP_TX_AVI_DB5 0x78
#define SP_TX_AVI_DB6 0x79
#define SP_TX_AVI_DB7 0x7A
#define SP_TX_AVI_DB8 0x7B
#define SP_TX_AVI_DB9 0x7C
#define SP_TX_AVI_DB10 0x7D
#define SP_TX_AVI_DB11 0x7E
#define SP_TX_AVI_DB12 0x7F
#define SP_TX_AVI_DB13 0x80
#define SP_TX_AVI_DB14 0x81
#define SP_TX_AVI_DB15 0x82
/* Audio info frame */
#define SP_TX_AUD_TYPE 0x83
#define SP_TX_AUD_VER 0x84
#define SP_TX_AUD_LEN 0x85
#define SP_TX_AUD_DB0 0x86
#define SP_TX_AUD_DB1 0x87
#define SP_TX_AUD_DB2 0x88
#define SP_TX_AUD_DB3 0x89
#define SP_TX_AUD_DB4 0x8A
#define SP_TX_AUD_DB5 0x8B
#define SP_TX_AUD_DB6 0x8C
#define SP_TX_AUD_DB7 0x8D
#define SP_TX_AUD_DB8 0x8E
#define SP_TX_AUD_DB9 0x8F
#define SP_TX_AUD_DB10 0x90
/* SPD info frame */
#define SP_TX_SPD_TYPE 0x91
#define SP_TX_SPD_VER 0x92
#define SP_TX_SPD_LEN 0x93
#define SP_TX_SPD_DATA0 0x94
#define SP_TX_SPD_DATA1 0x95
#define SP_TX_SPD_DATA2 0x96
#define SP_TX_SPD_DATA3 0x97
#define SP_TX_SPD_DATA4 0x98
#define SP_TX_SPD_DATA5 0x99
#define SP_TX_SPD_DATA6 0x9A
#define SP_TX_SPD_DATA7 0x9B
#define SP_TX_SPD_DATA8 0x9C
#define SP_TX_SPD_DATA9 0x9D
#define SP_TX_SPD_DATA10 0x9E
#define SP_TX_SPD_DATA11 0x9F
#define SP_TX_SPD_DATA12 0xA0
#define SP_TX_SPD_DATA13 0xA1
#define SP_TX_SPD_DATA14 0xA2
#define SP_TX_SPD_DATA15 0xA3
#define SP_TX_SPD_DATA16 0xA4
#define SP_TX_SPD_DATA17 0xA5
#define SP_TX_SPD_DATA18 0xA6
#define SP_TX_SPD_DATA19 0xA7
#define SP_TX_SPD_DATA20 0xA8
#define SP_TX_SPD_DATA21 0xA9
#define SP_TX_SPD_DATA22 0xAA
#define SP_TX_SPD_DATA23 0xAB
#define SP_TX_SPD_DATA24 0xAC
#define SP_TX_SPD_DATA25 0xAD
#define SP_TX_SPD_DATA26 0xAE
#define SP_TX_SPD_DATA27 0xAF
/* Mpeg source info frame */
#define SP_TX_MPEG_TYPE 0xB0
#define SP_TX_MPEG_VER 0xB1
#define SP_TX_MPEG_LEN 0xB2
#define SP_TX_MPEG_DATA0 0xB3
#define SP_TX_MPEG_DATA1 0xB4
#define SP_TX_MPEG_DATA2 0xB5
#define SP_TX_MPEG_DATA3 0xB6
#define SP_TX_MPEG_DATA4 0xB7
#define SP_TX_MPEG_DATA5 0xB8
#define SP_TX_MPEG_DATA6 0xB9
#define SP_TX_MPEG_DATA7 0xBA
#define SP_TX_MPEG_DATA8 0xBB
#define SP_TX_MPEG_DATA9 0xBC
#define SP_TX_MPEG_DATA10 0xBD
#define SP_TX_MPEG_DATA11 0xBE
#define SP_TX_MPEG_DATA12 0xBF
#define SP_TX_MPEG_DATA13 0xC0
#define SP_TX_MPEG_DATA14 0xC1
#define SP_TX_MPEG_DATA15 0xC2
#define SP_TX_MPEG_DATA16 0xC3
#define SP_TX_MPEG_DATA17 0xC4
#define SP_TX_MPEG_DATA18 0xC5
#define SP_TX_MPEG_DATA19 0xC6
#define SP_TX_MPEG_DATA20 0xC7
#define SP_TX_MPEG_DATA21 0xC8
#define SP_TX_MPEG_DATA22 0xC9
#define SP_TX_MPEG_DATA23 0xCA
#define SP_TX_MPEG_DATA24 0xCB
#define SP_TX_MPEG_DATA25 0xCC
#define SP_TX_MPEG_DATA26 0xCD
#define SP_TX_MPEG_DATA27 0xCE
/* #define GNSS_CTRL_REG 0xCD */
/* bit position */
/* #define ENABLE_SSC_FILTER 0x80 */
/* #define SSC_D_VALUE 0xD0 */
/* #define SSC_CTRL_REG2 0xD1 */
#define ANALOG_DEBUG_REG1 0xDC
/* bit position */
#define ANALOG_SEL_BG 0x40
#define ANALOG_SWING_A_30PER 0x08
#define ANALOG_DEBUG_REG2 0xDD
/* bit position */
#define ANALOG_24M_SEL 0x08
/* #define ANALOG_FILTER_ENABLED 0x10 */
#define ANALOG_DEBUG_REG3 0xDE
#define PLL_FILTER_CTRL1 0xDF
/* bit position */
#define PD_RING_OSC 0x40
#define PLL_FILTER_CTRL2 0xE0
#define PLL_FILTER_CTRL3 0xE1
#define PLL_FILTER_CTRL4 0xE2
#define PLL_FILTER_CTRL5 0xE3
#define PLL_FILTER_CTRL6 0xE4
#define SP_TX_I2S_CTRL 0xE6
#define SP_TX_I2S_FMT 0xE7
#define SP_TX_I2S_CH_Status1 0xD0
#define SP_TX_I2S_CH_Status2 0xD1
#define SP_TX_I2S_CH_Status3 0xD2
#define SP_TX_I2S_CH_Status4 0xD3
#define SP_TX_I2S_CH_Status5 0xD4
/* interrupt */
#define SP_COMMON_INT_STATUS1 0xF1
/* bit position */
#define SP_COMMON_INT1_PLL_LOCK_CHG 0x40
#define SP_COMMON_INT1_VIDEO_FORMAT_CHG 0x08
#define SP_COMMON_INT1_AUDIO_CLK_CHG 0x04
#define SP_COMMON_INT1_VIDEO_CLOCK_CHG 0x02
#define SP_COMMON_INT_STATUS2 0xF2
/* bit position */
#define SP_COMMON_INT2_AUTHCHG 0x02
#define SP_COMMON_INT2_AUTHDONE 0x01
#define SP_COMMON_INT_STATUS3 0xF3
/* bit position */
#define SP_COMMON_INT3_AFIFO_UNDER 0x80
#define SP_COMMON_INT3_AFIFO_OVER 0x40
#define SP_COMMON_INT_STATUS4 0xF4
/* bit position */
#define SP_COMMON_INT4_PLUG 0x01
#define SP_COMMON_INT4_ESYNC_ERR 0x10
#define SP_COMMON_INT4_HPDLOST 0x02
#define SP_COMMON_INT4_HPD_CHANGE 0x04
#define SP_TX_INT_STATUS1 0xF7
/* bit position */
#define SP_TX_INT_STATUS1_HPD 0x40
#define SP_TX_INT_STATUS1_TRAINING_Finish 0x20
#define SP_TX_INT_STATUS1_POLLING_ERR 0x10
#define SP_TX_INT_SINK_CHG 0x08
/* interrupt mask */
#define SP_COMMON_INT_MASK1 0xF8
#define SP_COMMON_INT_MASK2 0xF9
#define SP_COMMON_INT_MASK3 0xFA
#define SP_COMMON_INT_MASK4 0xFB
#define SP_INT_MASK 0xFE
#define SP_TX_INT_CTRL_REG 0xFF
/* End for dev_addr 0x72 or 0x76 */
/***************************************************************/
/***************************************************************/
/* DPCD regs */
#define DPCD_DPCD_REV 0x00
#define DPCD_MAX_LINK_RATE 0x01
#define DPCD_MAX_LANE_COUNT 0x02
#define DPCD_MAX_DOWNSPREAD 0x03
#define DPCD_NORP 0x04
#define DPCD_DOWNSTREAMPORT_PRESENT 0x05
#define DPCD_RECEIVE_PORT0_CAP_0 0x08
#define DPCD_RECEIVE_PORT0_CAP_1 0x09
#define DPCD_RECEIVE_PORT0_CAP_2 0x0a
#define DPCD_RECEIVE_PORT0_CAP_3 0x0b
#define DPCD_LINK_BW_SET 0x00
#define DPCD_LANE_COUNT_SET 0x01
#define DPCD_TRAINING_PATTERN_SET 0x02
#define DPCD_TRAINNIG_LANE0_SET 0x03
#define DPCD_TRAINNIG_LANE1_SET 0x04
#define DPCD_TRAINNIG_LANE2_SET 0x05
#define DPCD_TRAINNIG_LANE3_SET 0x06
#define DPCD_DOWNSPREAD_CTRL 0x07
#define DPCD_SINK_COUNT 0x00
#define DPCD_DEVICE_SERVICE_IRQ_VECTOR 0x01
#define DPCD_LANE0_1_STATUS 0x02
#define DPCD_LANE2_3_STATUS 0x03
#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x04
#define DPCD_SINK_STATUS 0x05
#define DPCD_ADJUST_REQUEST_LANE0_1 0x06
#define DPCD_ADJUST_REQUEST_LANE2_3 0x07
#define DPCD_TRAINING_SCORE_LANE0 0x08
#define DPCD_TRAINING_SCORE_LANE1 0x09
#define DPCD_TRAINING_SCORE_LANE2 0x0a
#define DPCD_TRAINING_SCORE_LANE3 0x0b
#define DPCD_TEST_REQUEST 0x18
#define DPCD_TEST_LINK_RATE 0x19
#define DPCD_TEST_LANE_COUNT 0x20
#define DPCD_TEST_Response 0x60
#define TEST_ACK 0x01
/* bit position */
#define DPCD_TEST_EDID_Checksum_Write 0x04
#define DPCD_TEST_EDID_Checksum 0x61
#define DPCD_SPECIFIC_INTERRUPT 0x10
/* define for downstream HDMI Rx sense detection */
#define DPCD_USER_COMM1 0x22
#endif

View File

@@ -0,0 +1,242 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/i2c_tc101.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
static struct lcd_extern_config_s *ext_config;
static struct i2c_client *aml_tc101_i2c_client;
#define LCD_EXTERN_NAME "lcd_i2c_tc101"
static unsigned char i2c_init_table[][3] = {
/* {0xff, 0xff, 20},//delay mark(20ms) */
{0xf8, 0x30, 0xb2},
{0xf8, 0x33, 0xc2},
{0xf8, 0x31, 0xf0},
{0xf8, 0x40, 0x80},
{0xf8, 0x81, 0xec},
{0xff, 0xff, 0xff},/* end mark */
};
static int aml_i2c_write(struct i2c_client *i2client, unsigned char *buff,
unsigned int len)
{
int ret = 0;
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = len,
.buf = buff,
},
};
ret = i2c_transfer(i2client->adapter, msg, 1);
if (ret < 0) {
EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
}
return ret;
}
#if 0
static int aml_i2c_read(struct i2c_client *i2client, unsigned char *buff,
unsigned int len)
{
int ret = 0;
struct i2c_msg msgs[] = {
{
.addr = i2client->addr,
.flags = 0,
.len = 1,
.buf = buff,
},
{
.addr = i2client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buff,
},
};
ret = i2c_transfer(i2client->adapter, msgs, 2);
if (ret < 0) {
EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
__func__, i2client->addr);
}
return ret;
}
static int i2c_reg_read(unsigned char reg, unsigned char *buf)
{
int ret = 0;
return ret;
}
static int i2c_reg_write(unsigned char reg, unsigned char value)
{
int ret = 0;
return ret;
}
#endif
static int lcd_extern_power_on(void)
{
unsigned char tData[4];
int i = 0, ending_flag = 0;
int ret = 0;
while (ending_flag == 0) {
if ((i2c_init_table[i][0] == 0xff) &&
(i2c_init_table[i][1] == 0xff)) { /* special mark */
if (i2c_init_table[i][2] == 0xff) /* ending flag */
ending_flag = 1;
else /* delay flag */
mdelay(i2c_init_table[i][2]);
} else {
tData[0] = i2c_init_table[i][0];
tData[1] = i2c_init_table[i][1];
tData[2] = i2c_init_table[i][2];
aml_i2c_write(aml_tc101_i2c_client, tData, 3);
}
i++;
}
EXTPR("%s\n", __func__);
return ret;
}
static int lcd_extern_power_off(void)
{
int ret = 0;
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
if (ext_drv) {
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
} else {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
ret = -1;
}
return ret;
}
static int aml_tc101_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
EXTERR("%s: functionality check failed\n", __func__);
else
aml_tc101_i2c_client = client;
EXTPR("%s OK\n", __func__);
return 0;
}
static int aml_tc101_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id aml_tc101_i2c_id[] = {
{LCD_EXTERN_NAME, 0},
{ }
};
/* MODULE_DEVICE_TABLE(i2c, aml_tc101_id); */
static struct i2c_driver aml_tc101_i2c_driver = {
.probe = aml_tc101_i2c_probe,
.remove = aml_tc101_i2c_remove,
.id_table = aml_tc101_i2c_id,
.driver = {
.name = LCD_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
int aml_lcd_extern_i2c_tc101_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
int ret = 0;
ext_config = &ext_drv->config;
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(ext_drv->config.i2c_bus);
if (!adapter) {
EXTERR("%s failed to get i2c adapter\n", ext_drv->config.name);
return -1;
}
strncpy(i2c_info.type, ext_drv->config.name, I2C_NAME_SIZE);
i2c_info.addr = ext_drv->config.i2c_addr;
i2c_info.platform_data = &ext_drv->config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f) {
EXTERR("%s invalid i2c address: 0x%02x\n",
ext_drv->config.name, ext_drv->config.i2c_addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
EXTERR("%s failed to new i2c device\n", ext_drv->config.name);
} else {
if (lcd_debug_print_flag) {
EXTPR("%s new i2c device succeed\n",
ext_drv->config.name);
}
}
if (!aml_tc101_i2c_client) {
ret = i2c_add_driver(&aml_tc101_i2c_driver);
if (ret) {
EXTERR("%s add i2c_driver failed\n",
ext_drv->config.name);
return -1;
}
}
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.dts
*
* 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.
*
*/
lcd_extern{
compatible = "amlogic, lcd_extern";
dev_name = "lcd_extern";
status = "okay";
extern-gpios = <&gpio GPIODV_1 GPIO_ACTIVE_HIGH
&gpio GPIODV_16 GPIO_ACTIVE_HIGH
&gpio GPIODV_17 GPIO_ACTIVE_HIGH>;
extern_gpio_names = "GPIODV_1","GPIODV_16","GPIODV_17";
extern_0{
index = <0>;
extern_name = "i2c_T5800Q";
status = "disabled";
type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x1c>; /** 7bit i2c address */
i2c_bus = "i2c_bus_d";
};
extern_1{
index = <1>;
extern_name = "i2c_tc101";
status = "disabled";
type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x7e>; /** 7bit i2c address */
i2c_bus = "i2c_bus_a";
};
extern_2{
index = <2>;
extern_name = "i2c_anx6345";
status = "disabled";
type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x38>; /** 7bit i2c address */
i2c_bus = "i2c_bus_b";
lane_num = <1>; /** edp lane_num: 1/2/4 */
bits = <0>; /** lcd_bits(0=6bit, 1=8bit) */
link_rate = <1>; /** edp link rate: (0=1.62G, 1=27G, 2=5.4G) */
};
extern_3{
index = <3>;
extern_name = "spi_LD070WS2";
status = "disabled";
type = <1>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
gpio_spi_cs = <0>; /* index in extern-gpios */
gpio_spi_clk = <1>; /* index in extern-gpios */
gpio_spi_data = <2>; /* index in extern-gpios */
};
extern_4{
index = <4>;
extern_name = "mipi_N070ICN";
status = "disabled";
type = <2>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
};
extern_5{
index = <5>;
extern_name = "mipi_KD080D13";
status = "disabled";
type = <2>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
};
extern_6{
index = <6>;
extern_name = "i2c_DLPC3439";
status = "disabled";
type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
i2c_address = <0x1b>; /** 7bit i2c address */
i2c_bus = "i2c_bus_a";
};
};

View File

@@ -0,0 +1,74 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.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 _LCD_EXTERN_H_
#define _LCD_EXTERN_H_
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#define EXTPR(fmt, args...) pr_info("lcd extern: "fmt"", ## args)
#define EXTERR(fmt, args...) pr_info("lcd extern: error: "fmt"", ## args)
#define LCD_EXTERN_DRIVER "lcd_extern"
#ifdef CONFIG_USE_OF
extern struct device_node *aml_lcd_extern_get_dts_child(int index);
#endif
extern void lcd_extern_gpio_register(unsigned char index);
extern void lcd_extern_gpio_set(unsigned char index, int value);
extern unsigned int lcd_extern_gpio_get(unsigned char index);
#define LCD_EXTERN_DEFAULT_ENABLE
#ifdef LCD_EXTERN_DEFAULT_ENABLE
extern int aml_lcd_extern_default_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_T5800Q
extern int aml_lcd_extern_i2c_T5800Q_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_DLPC3439
extern int aml_lcd_extern_i2c_DLPC3439_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_TC101
extern int aml_lcd_extern_i2c_tc101_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_ANX6345
extern int aml_lcd_extern_i2c_anx6345_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_SPI_LD070WS2
extern int aml_lcd_extern_spi_LD070WS2_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_N070ICN
extern int aml_lcd_extern_mipi_N070ICN_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_KD080D13
extern int aml_lcd_extern_mipi_KD080D13_probe(
struct aml_lcd_extern_driver_s *ext_drv);
#endif
#endif

View File

@@ -0,0 +1,129 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/mipi_KD080D13.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#define LCD_EXTERN_NAME "lcd_mipi_KD080D13"
/* ******************** mipi command ********************
* format: data_type, num, data....
* special: data_type=0xff, num<0xff means delay ms, num=0xff means ending.
*/
static unsigned char mipi_init_on_table[] = {
0x39, 3, 0xf0, 0x5a, 0x5a,
0x39, 3, 0xf1, 0x5a, 0x5a,
0x39, 3, 0xfc, 0xa5, 0xa5,
0x39, 3, 0xd0, 0x00, 0x10,
0x15, 2, 0xb1, 0x10,
0x39, 5, 0xb2, 0x14, 0x22, 0x2f, 0x04,
0x39, 6, 0xf2, 0x02, 0x08, 0x08, 0x40, 0x10,
0x15, 2, 0xb0, 0x03,
0x39, 3, 0xfd, 0x23, 0x09,
0x39, 11, 0xf3, 0x01, 0x93, 0x20, 0x22, 0x80, 0x05, 0x25, 0x3c, 0x26,
0x00,
0x39, 46, 0xf4, 0x00, 0x02, 0x03, 0x26, 0x03, 0x02, 0x09, 0x00, 0x07,
0x16, 0x16, 0x03, 0x00, 0x08, 0x08, 0x03, 0x0E, 0x0F, 0x12,
0x1C, 0x1D, 0x1E, 0x0C, 0x09, 0x01, 0x04, 0x02, 0x61, 0x74,
0x75, 0x72, 0x83, 0x80, 0x80, 0xB0, 0x00, 0x01, 0x01, 0x28,
0x04, 0x03, 0x28, 0x01, 0xD1, 0x32,
0x39, 27, 0xf5, 0x84, 0x2F, 0x2F, 0x5F, 0xAB, 0x98, 0x52, 0x0F, 0x33,
0x43, 0x04, 0x59, 0x54, 0x52, 0x05, 0x40, 0x60, 0x4E, 0x60,
0x40, 0x27, 0x26, 0x52, 0x25, 0x6D, 0x18,
0x39, 9, 0xee, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00,
0x39, 9, 0xef, 0x34, 0x12, 0x98, 0xBA, 0x20, 0x00, 0x24, 0x80,
0x39, 33, 0xf7, 0x0E, 0x0E, 0x0A, 0x0A, 0x0F, 0x0F, 0x0B, 0x0B, 0x05,
0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0C, 0x0C, 0x08,
0x08, 0x0D, 0x0D, 0x09, 0x09, 0x04, 0x06, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01,
0x39, 4, 0xbc, 0x01, 0x4e, 0x0a,
0x39, 6, 0xe1, 0x03, 0x10, 0x1c, 0xa0, 0x10,
0x39, 7, 0xf6, 0x60, 0x21, 0xA6, 0x00, 0x00, 0x00,
0x39, 7, 0xfe, 0x00, 0x0D, 0x03, 0x21, 0x80, 0x48,
0x15, 2, 0xb0, 0x22,
0x39, 18, 0xfa, 0x02, 0x34, 0x09, 0x13, 0x0B, 0x0F, 0x16, 0x16, 0x17,
0x1E, 0x1D, 0x1C, 0x1E, 0x1D, 0x1D, 0x1F, 0x24,
0x15, 2, 0xb0, 0x22,
0x39, 18, 0xfb, 0x00, 0x34, 0x07, 0x11, 0x09, 0x0D, 0x14, 0x14, 0x15,
0x1C, 0x1F, 0x1C, 0x1D, 0x1D, 0x1D, 0x20, 0x26,
0x15, 2, 0xb0, 0x11,
0x39, 18, 0xfa, 0x20, 0x34, 0x24, 0x27, 0x19, 0x1B, 0x1F, 0x1E, 0x1B,
0x1F, 0x21, 0x1F, 0x1E, 0x20, 0x1E, 0x1E, 0x21,
0x15, 2, 0xb0, 0x11,
0x39, 18, 0xfb, 0x1E, 0x34, 0x22, 0x25, 0x17, 0x19, 0x1D, 0x1A, 0x19,
0x20, 0x1F, 0x1E, 0x20, 0x1E, 0x1E, 0x1F, 0x22,
0x39, 18, 0xfa, 0x1C, 0x34, 0x1C, 0x1F, 0x13, 0x17, 0x1A, 0x18, 0x18,
0x1E, 0x20, 0x21, 0x21, 0x21, 0x23, 0x22, 0x2A,
0x39, 18, 0xfb, 0x1A, 0x34, 0x1A, 0x1D, 0x11, 0x15, 0x18, 0x16, 0x16,
0x1C, 0x20, 0x20, 0x20, 0x1F, 0x23, 0x23, 0x2B,
0x05, 1, 0x11,
0xff, 20,
0x39, 4, 0xc3, 0x40, 0x00, 0x28,
0xff, 200,
0x15, 2, 0x35, 0x00,
0x05, 1, 0x29,
0xff, 30, /* delay 30ms */
0xff, 0xff, /* ending flag */
};
static unsigned char mipi_init_off_table[] = {
0x05, 1, 0x28, /* display off */
0xff, 30, /* delay 30ms */
0x05, 1, 0x10, /* sleep in */
0xff, 30, /* delay 30ms */
0x39, 4, 0xc3, 0x40, 0x00, 0x20,
0xff, 10,
0xff, 0xff, /* ending flag */
};
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
if (ext_drv) {
ext_drv->config.table_init_on = &mipi_init_on_table[0];
ext_drv->config.table_init_off = &mipi_init_off_table[0];
} else {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
ret = -1;
}
return ret;
}
int aml_lcd_extern_mipi_KD080D13_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,246 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/mipi_N070ICN.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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#define LCD_EXTERN_NAME "lcd_mipi_N070ICN"
/* ******************** mipi command ********************
* format: data_type, num, data....
* special: data_type=0xff, num<0xff means delay ms, num=0xff means ending.
*/
static unsigned char mipi_init_on_table[] = {
/* ========== Internal setting ========== */
0x39, 5, 0xFF, 0xAA, 0x55, 0xA5, 0x80,
0x39, 3, 0x6F, 0x11, 0x00, /* MIPI related Timing Setting */
0x39, 3, 0xF7, 0x20, 0x00,
0x15, 2, 0x6F, 0x06, /* Improve ESD option */
0x15, 2, 0xF7, 0xA0,
0x15, 2, 0x6F, 0x19,
0x15, 2, 0xF7, 0x12,
0x15, 2, 0x6F, 0x08, /* Vcom floating */
0x15, 2, 0xFA, 0x40,
0x15, 2, 0x6F, 0x11,
0x15, 2, 0xF3, 0x01,
/* ========== page0 relative ========== */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00,
0x15, 2, 0xC8, 0x80,
0x39, 3, 0xB1, 0x6C, 0x01, /* Set WXGA resolution */
0x15, 2, 0xB6, 0x08, /* Set source output hold time */
0x15, 2, 0x6F, 0x02, /* EQ control function */
0x15, 2, 0xB8, 0x08,
0x39, 3, 0xBB, 0x54, 0x54, /* Set bias current for GOP and SOP */
0x39, 3, 0xBC, 0x05, 0x05, /* Inversion setting */
0x15, 2, 0xC7, 0x01, /* zigzag setting */
/* DSP Timing Settings update for BIST */
0x39, 6, 0xBD, 0x02, 0xB0, 0x0C, 0x0A, 0x00,
/* ========== page1 relative ========== */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01,
0x39, 3, 0xB0, 0x05, 0x05, /* Setting AVDD, AVEE clamp */
0x39, 3, 0xB1, 0x05, 0x05,
0x39, 3, 0xBC, 0x3A, 0x01, /* VGMP, VGMN, VGSP, VGSN setting */
0x39, 3, 0xBD, 0x3E, 0x01,
0x15, 2, 0xCA, 0x00, /* gate signal control */
0x15, 2, 0xC0, 0x04, /* power IC control */
0x15, 2, 0xB2, 0x00,
0x15, 2, 0xBE, 0x80, /*vcom -1.88V */
0x39, 3, 0xB3, 0x19, 0x19, /* Setting VGH=15V, VGL=-11V */
0x39, 3, 0xB4, 0x12, 0x12,
0x39, 3, 0xB9, 0x24, 0x24, /* power control for VGH, VGL */
0x39, 3, 0xBA, 0x14, 0x14,
/* ========== page2 relative ========== */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02,
0x15, 2, 0xEE, 0x01, /* Gamma setting */
/* Gradient Control for Gamma Voltage */
0x39, 5, 0xEF, 0x09, 0x06, 0x15, 0x18,
/* ========== GOA relative ========== */
0x39, 7, 0xB0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17,
0x15, 2, 0x6F, 0x06,
0x39, 7, 0xB0, 0x00, 0x25, 0x00, 0x30, 0x00, 0x45,
0x15, 2, 0x6F, 0x0C,
0x39, 5, 0xB0, 0x00, 0x56, 0x00, 0x7A,
0x39, 7, 0xB1, 0x00, 0xA3, 0x00, 0xE7, 0x01, 0x20,
0x15, 2, 0x6F, 0x06,
0x39, 7, 0xB1, 0x01, 0x7A, 0x01, 0xC2, 0x01, 0xC5,
0x15, 2, 0x6F, 0x0C,
0x39, 5, 0xB1, 0x02, 0x06, 0x02, 0x5F,
0x39, 7, 0xB2, 0x02, 0x92, 0x02, 0xD0, 0x02, 0xFC,
0x15, 2, 0x6F, 0x06,
0x39, 7, 0xB2, 0x03, 0x35, 0x03, 0x5D, 0x03, 0x8B,
0x15, 2, 0x6F, 0x0C,
0x39, 5, 0xB2, 0x03, 0xA2, 0x03, 0xBF,
0x39, 5, 0xB3, 0x03, 0xD2, 0x03, 0xFF,
/* PAGE6 : GOUT Mapping, VGLO select */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x06,
0x39, 3, 0xB0, 0x00, 0x17,
0x39, 3, 0xB1, 0x16, 0x15,
0x39, 3, 0xB2, 0x14, 0x13,
0x39, 3, 0xB3, 0x12, 0x11,
0x39, 3, 0xB4, 0x10, 0x2D,
0x39, 3, 0xB5, 0x01, 0x08,
0x39, 3, 0xB6, 0x09, 0x31,
0x39, 3, 0xB7, 0x31, 0x31,
0x39, 3, 0xB8, 0x31, 0x31,
0x39, 3, 0xB9, 0x31, 0x31,
0x39, 3, 0xBA, 0x31, 0x31,
0x39, 3, 0xBB, 0x31, 0x31,
0x39, 3, 0xBC, 0x31, 0x31,
0x39, 3, 0xBD, 0x31, 0x09,
0x39, 3, 0xBE, 0x08, 0x01,
0x39, 3, 0xBF, 0x2D, 0x10,
0x39, 3, 0xC0, 0x11, 0x12,
0x39, 3, 0xC1, 0x13, 0x14,
0x39, 3, 0xC2, 0x15, 0x16,
0x39, 3, 0xC3, 0x17, 0x00,
0x39, 3, 0xE5, 0x31, 0x31,
0x39, 3, 0xC4, 0x00, 0x17,
0x39, 3, 0xC5, 0x16, 0x15,
0x39, 3, 0xC6, 0x14, 0x13,
0x39, 3, 0xC7, 0x12, 0x11,
0x39, 3, 0xC8, 0x10, 0x2D,
0x39, 3, 0xC9, 0x01, 0x08,
0x39, 3, 0xCA, 0x09, 0x31,
0x39, 3, 0xCB, 0x31, 0x31,
0x39, 3, 0xCC, 0x31, 0x31,
0x39, 3, 0xCD, 0x31, 0x31,
0x39, 3, 0xCE, 0x31, 0x31,
0x39, 3, 0xCF, 0x31, 0x31,
0x39, 3, 0xD0, 0x31, 0x31,
0x39, 3, 0xD1, 0x31, 0x09,
0x39, 3, 0xD2, 0x08, 0x01,
0x39, 3, 0xD3, 0x2D, 0x10,
0x39, 3, 0xD4, 0x11, 0x12,
0x39, 3, 0xD5, 0x13, 0x14,
0x39, 3, 0xD6, 0x15, 0x16,
0x39, 3, 0xD7, 0x17, 0x00,
0x39, 3, 0xE6, 0x31, 0x31,
0x39, 6, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, /* VGL level select; */
0x39, 6, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 2, 0xE7, 0x00,
/* ===page 3====//gate timing control */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03,
0x39, 3, 0xB0, 0x20, 0x00,
0x39, 3, 0xB1, 0x20, 0x00,
0x39, 6, 0xB2, 0x05, 0x00, 0x42, 0x00, 0x00,
0x39, 6, 0xB6, 0x05, 0x00, 0x42, 0x00, 0x00,
0x39, 6, 0xBA, 0x53, 0x00, 0x42, 0x00, 0x00,
0x39, 6, 0xBB, 0x53, 0x00, 0x42, 0x00, 0x00,
0x15, 2, 0xC4, 0x40,
/* ===page 5==== */
0x39, 6, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x05,
0x39, 3, 0xB0, 0x17, 0x06,
0x15, 2, 0xB8, 0x00,
0x39, 6, 0xBD, 0x03, 0x01, 0x01, 0x00, 0x01,
0x39, 3, 0xB1, 0x17, 0x06,
0x39, 3, 0xB9, 0x00, 0x01,
0x39, 3, 0xB2, 0x17, 0x06,
0x39, 3, 0xBA, 0x00, 0x01,
0x39, 3, 0xB3, 0x17, 0x06,
0x39, 3, 0xBB, 0x0A, 0x00,
0x39, 3, 0xB4, 0x17, 0x06,
0x39, 3, 0xB5, 0x17, 0x06,
0x39, 3, 0xB6, 0x14, 0x03,
0x39, 3, 0xB7, 0x00, 0x00,
0x39, 3, 0xBC, 0x02, 0x01,
0x15, 2, 0xC0, 0x05,
0x15, 2, 0xC4, 0xA5,
0x39, 3, 0xC8, 0x03, 0x30,
0x39, 3, 0xC9, 0x03, 0x51,
0x39, 6, 0xD1, 0x00, 0x05, 0x03, 0x00, 0x00,
0x39, 6, 0xD2, 0x00, 0x05, 0x09, 0x00, 0x00,
0x15, 2, 0xE5, 0x02,
0x15, 2, 0xE6, 0x02,
0x15, 2, 0xE7, 0x02,
0x15, 2, 0xE9, 0x02,
0x15, 2, 0xED, 0x33,
0x05, 1, 0x11, /* sleep out */
0xff, 30, /* delay 30ms */
0x05, 1, 0x29, /* display on */
0xff, 30, /* delay 30ms */
0xff, 0xff, /* ending flag */
};
static unsigned char mipi_init_off_table[] = {
0x05, 1, 0x28, /* display off */
0xff, 10, /* delay 10ms */
0x05, 1, 0x10, /* sleep in */
0xff, 10, /* delay 10ms */
0xff, 0xff, /* ending flag */
};
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
if (ext_drv) {
ext_drv->config.table_init_on = &mipi_init_on_table[0];
ext_drv->config.table_init_off = &mipi_init_off_table[0];
} else {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
ret = -1;
}
return ret;
}
int aml_lcd_extern_mipi_N070ICN_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,231 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.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.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/sysctl.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
static struct lcd_extern_config_s *ext_config;
#define LCD_EXTERN_NAME "lcd_spi_LD070WS2"
#define SPI_DELAY 30 /* unit: us */
#define LCD_EXTERN_CMD_SIZE 4
static unsigned char init_on_table[] = {
0x00, 0x00, 0x21, 0x00, /* reset */
0x00, 0x00, 0xa5, 0x00, /* standby */
0x00, 0x01, 0x30, 0x00, /* enable FRC/Dither */
0x00, 0x02, 0x40, 0x00, /* enable normally black */
0x00, 0x0e, 0x5f, 0x00, /* enable test mode1 */
0x00, 0x0f, 0xa4, 0x00, /* enable test mode2 */
0x00, 0x0d, 0x00, 0x00, /* enable SDRRS, enlarge OE width */
0x00, 0x02, 0x43, 0x00, /* adjust charge sharing time */
0x00, 0x0a, 0x28, 0x00, /* trigger bias reduction */
0x00, 0x10, 0x41, 50, /* adopt 2 line/1 dot */ /* delay 50ms */
0x00, 0x00, 0xad, 0x00, /* display on */
0xff, 0x00, 0x00, 0x00, /* ending flag */
};
static unsigned char init_off_table[] = {
0x00, 0x00, 0xa5, 0x00, /* standby */
0xff, 0x00, 0x00, 0x00, /* ending flag */
};
static void set_lcd_csb(unsigned int v)
{
lcd_extern_gpio_set(ext_config->spi_cs, v);
udelay(SPI_DELAY);
}
static void set_lcd_scl(unsigned int v)
{
lcd_extern_gpio_set(ext_config->spi_clk, v);
udelay(SPI_DELAY);
}
static void set_lcd_sda(unsigned int v)
{
lcd_extern_gpio_set(ext_config->spi_data, v);
udelay(SPI_DELAY);
}
static void spi_gpio_init(void)
{
set_lcd_csb(1);
set_lcd_scl(1);
set_lcd_sda(1);
}
static void spi_gpio_off(void)
{
set_lcd_sda(0);
set_lcd_scl(0);
set_lcd_csb(0);
}
static void spi_write_8(unsigned char addr, unsigned char data)
{
int i;
unsigned int sdata;
sdata = (unsigned int)(addr & 0x3f);
sdata <<= 10;
sdata |= (data & 0xff);
sdata &= ~(1<<9); /* write flag */
set_lcd_csb(1);
set_lcd_scl(1);
set_lcd_sda(1);
set_lcd_csb(0);
for (i = 0; i < 16; i++) {
set_lcd_scl(0);
if (sdata & 0x8000)
set_lcd_sda(1);
else
set_lcd_sda(0);
sdata <<= 1;
set_lcd_scl(1);
}
set_lcd_csb(1);
set_lcd_scl(1);
set_lcd_sda(1);
udelay(SPI_DELAY);
}
static int lcd_extern_spi_write(unsigned char *buf, int len)
{
if (len != 2) {
EXTERR("%s: len %d error\n", __func__, len);
return -1;
}
spi_write_8(buf[0], buf[1]);
return 0;
}
static int lcd_extern_power_cmd(unsigned char *init_table)
{
int i = 0, len;
int ret = 0;
len = ext_config->cmd_size;
if (len < 1) {
EXTERR("%s: cmd_size %d is invalid\n", __func__, len);
return -1;
}
while (i <= LCD_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == LCD_EXTERN_INIT_END) {
break;
} else if (init_table[i] == LCD_EXTERN_INIT_NONE) {
/* do nothing, only for delay */
} else if (init_table[i] == LCD_EXTERN_INIT_GPIO) {
if (init_table[i+1] < LCD_GPIO_MAX) {
lcd_extern_gpio_set(init_table[i+1],
init_table[i+2]);
}
} else if (init_table[i] == LCD_EXTERN_INIT_CMD) {
ret = lcd_extern_spi_write(&init_table[i+1], (len-2));
} else {
EXTERR("%s(%d: %s): power_type %d is invalid\n",
__func__, ext_config->index,
ext_config->name, ext_config->type);
}
if (init_table[i+len-1] > 0)
mdelay(init_table[i+len-1]);
i += len;
}
return ret;
}
static int lcd_extern_power_ctrl(int flag)
{
int ret = 0;
spi_gpio_init();
if (flag)
ret = lcd_extern_power_cmd(ext_config->table_init_on);
else
ret = lcd_extern_power_cmd(ext_config->table_init_off);
mdelay(10);
spi_gpio_off();
EXTPR("%s(%d: %s): %d\n",
__func__, ext_config->index, ext_config->name, flag);
return ret;
}
static int lcd_extern_power_on(void)
{
int ret;
ret = lcd_extern_power_ctrl(1);
return ret;
}
static int lcd_extern_power_off(void)
{
int ret;
ret = lcd_extern_power_ctrl(0);
return ret;
}
static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
{
if (ext_drv == NULL) {
EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
return -1;
}
if (ext_drv->config.table_init_loaded == 0) {
ext_drv->config.table_init_on = init_on_table;
ext_drv->config.table_init_off = init_off_table;
}
ext_drv->power_on = lcd_extern_power_on;
ext_drv->power_off = lcd_extern_power_off;
return 0;
}
int aml_lcd_extern_spi_LD070WS2_probe(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = 0;
ext_config = &ext_drv->config;
ret = lcd_extern_driver_update(ext_drv);
if (lcd_debug_print_flag)
EXTPR("%s: %d\n", __func__, ret);
return ret;
}

View File

@@ -0,0 +1,52 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_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.
*
*/
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
static BLOCKING_NOTIFIER_HEAD(lcd_notifier_list);
/**
* aml_lcd_notifier_register - register a client notifier
* @nb: notifier block to callback on events
*/
int aml_lcd_notifier_register(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&lcd_notifier_list, nb);
}
EXPORT_SYMBOL(aml_lcd_notifier_register);
/**
* aml_lcd_notifier_unregister - unregister a client notifier
* @nb: notifier block to callback on events
*/
int aml_lcd_notifier_unregister(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&lcd_notifier_list, nb);
}
EXPORT_SYMBOL(aml_lcd_notifier_unregister);
/**
* aml_lcd_notifier_call_chain - notify clients of lcd events
*
*/
int aml_lcd_notifier_call_chain(unsigned long event, void *v)
{
return blocking_notifier_call_chain(&lcd_notifier_list, event, v);
}
EXPORT_SYMBOL_GPL(aml_lcd_notifier_call_chain);

View File

@@ -0,0 +1,631 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_reg.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.
*
*/
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#include "lcd_common.h"
#include "lcd_reg.h"
/* ********************************************* */
#define LCD_REG_GLOBAL_API 0
#define LCD_REG_IOREMAP 1
#define LCD_REG_IF LCD_REG_IOREMAP
/* ********************************************* */
#if (LCD_REG_IF == LCD_REG_IOREMAP)
struct reg_map_s {
unsigned int base_addr;
unsigned int size;
void __iomem *p;
char flag;
char dummy;
};
static struct reg_map_s *lcd_map;
static int lcd_map_num;
#define LCD_MAP_HIUBUS 0
#define LCD_MAP_VCBUS 1
#define LCD_MAP_PERIPHS 2
#define LCD_MAP_CBUS 3
#define LCD_MAP_DSI_HOST 4
#define LCD_MAP_DSI_PHY 5
static struct reg_map_s lcd_reg_maps_gxb[] = {
{ /* HIU */
.base_addr = 0xc883c000,
.size = 0x400,
.flag = 0,
.dummy = 0,
},
{ /* VCBUS */
.base_addr = 0xd0100000,
.size = 0x10000,
.flag = 0,
.dummy = 0,
},
{ /* PERIPHS */
.base_addr = 0xc8834400,
.size = 0x100,
.flag = 0,
.dummy = 0,
},
{ /* CBUS */
.base_addr = 0xc1100000,
.size = 0x8000,
.flag = 0,
.dummy = 0,
},
};
static struct reg_map_s lcd_reg_maps_txlx[] = {
{ /* HIU */
.base_addr = 0xff63c000,
.size = 0x400,
.flag = 0,
.dummy = 0,
},
{ /* VCBUS */
.base_addr = 0xff900000,
.size = 0xa000,
.flag = 0,
.dummy = 0,
},
{ /* PERIPHS */
.base_addr = 0xff634000,
.size = 0x100,
.flag = 0,
.dummy = 0,
},
};
static struct reg_map_s lcd_reg_maps_axg[] = {
{ /* HIU */
.base_addr = 0xff63c000,
.size = 0x400,
.flag = 0,
.dummy = 0,
},
{ /* VCBUS */
.base_addr = 0xff900000,
.size = 0xa000,
.flag = 0,
.dummy = 0,
},
{ /* PERIPHS */
.base_addr = 0xff634000,
.size = 0x100,
.flag = 0,
.dummy = 0,
},
{ /* CBUS, dummy */
.base_addr = 0xffd00000,
.size = 0x10,
.flag = 0,
.dummy = 1,
},
{ /* mipi_dsi_host */
.base_addr = 0xffd00000, /* 0xffd06000 */
.size = 0x6400,
.flag = 0,
.dummy = 0,
},
{ /* mipi_dsi_phy */
.base_addr = 0xff640000,
.size = 0x100,
.flag = 0,
.dummy = 0,
},
};
int lcd_ioremap(void)
{
int i;
int ret = 0;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
lcd_map = NULL;
lcd_map_num = 0;
switch (lcd_drv->chip_type) {
case LCD_CHIP_TXLX:
lcd_map = lcd_reg_maps_txlx;
lcd_map_num = ARRAY_SIZE(lcd_reg_maps_txlx);
break;
case LCD_CHIP_AXG:
lcd_map = lcd_reg_maps_axg;
lcd_map_num = ARRAY_SIZE(lcd_reg_maps_axg);
break;
default:
lcd_map = lcd_reg_maps_gxb;
lcd_map_num = ARRAY_SIZE(lcd_reg_maps_gxb);
break;
}
for (i = 0; i < lcd_map_num; i++) {
if (lcd_map[i].dummy)
continue;
lcd_map[i].p = ioremap(lcd_map[i].base_addr,
lcd_map[i].size);
if (lcd_map[i].p == NULL) {
lcd_map[i].flag = 0;
LCDPR("reg map failed: 0x%x\n",
lcd_map[i].base_addr);
ret = -1;
} else {
lcd_map[i].flag = 1;
if (lcd_debug_print_flag) {
LCDPR("reg mapped: 0x%x -> %p\n",
lcd_map[i].base_addr, lcd_map[i].p);
}
}
}
return ret;
}
static int check_lcd_ioremap(int n)
{
if (lcd_map == NULL)
return -1;
if (n >= lcd_map_num)
return -1;
if (lcd_map[n].dummy) {
LCDERR("reg 0x%x is invalid(dummy)\n", lcd_map[n].base_addr);
return -1;
}
if (lcd_map[n].flag == 0) {
LCDERR("reg 0x%x mapped error\n", lcd_map[n].base_addr);
return -1;
}
return 0;
}
#else
int lcd_ioremap(void)
{
LCDPR("reg interface is global api\n");
return 0;
}
#endif
/* register mapping check */
#if (LCD_REG_IF == LCD_REG_IOREMAP)
static inline void __iomem *check_lcd_vcbus_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
reg_bus = LCD_MAP_VCBUS;
if (check_lcd_ioremap(reg_bus))
return NULL;
reg_offset = LCD_REG_OFFSET_VCBUS(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid vcbus reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
static inline void __iomem *check_lcd_hiu_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB)
reg_bus = LCD_MAP_HIUBUS;
else
reg_bus = LCD_MAP_CBUS;
if (check_lcd_ioremap(reg_bus))
return NULL;
if (reg_bus == LCD_MAP_HIUBUS)
reg_offset = LCD_REG_OFFSET_HIU(_reg);
else
reg_offset = LCD_REG_OFFSET_CBUS(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid hiu reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
static inline void __iomem *check_lcd_cbus_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
reg_bus = LCD_MAP_CBUS;
if (check_lcd_ioremap(reg_bus))
return NULL;
reg_offset = LCD_REG_OFFSET_CBUS(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid cbus reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
static inline void __iomem *check_lcd_periphs_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB)
reg_bus = LCD_MAP_PERIPHS;
else
reg_bus = LCD_MAP_CBUS;
if (check_lcd_ioremap(reg_bus))
return NULL;
if (reg_bus == LCD_MAP_PERIPHS)
reg_offset = LCD_REG_OFFSET_PERIPHS(_reg);
else
reg_offset = LCD_REG_OFFSET_PERIPHS(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid periphs reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
static inline void __iomem *check_lcd_dsi_host_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
reg_bus = LCD_MAP_DSI_HOST;
if (check_lcd_ioremap(reg_bus))
return NULL;
reg_offset = LCD_REG_OFFSET_DSI_HOST(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid dsi_host reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
static inline void __iomem *check_lcd_dsi_phy_reg(unsigned int _reg)
{
void __iomem *p;
int reg_bus;
unsigned int reg_offset;
reg_bus = LCD_MAP_DSI_PHY;
if (check_lcd_ioremap(reg_bus))
return NULL;
reg_offset = LCD_REG_OFFSET_DSI_PHY(_reg);
if (reg_offset >= lcd_map[reg_bus].size) {
LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg);
return NULL;
}
p = lcd_map[reg_bus].p + reg_offset;
return p;
}
#endif
/* register access api */
#if (LCD_REG_IF == LCD_REG_IOREMAP)
unsigned int lcd_vcbus_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_vcbus_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void lcd_vcbus_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_vcbus_reg(_reg);
if (p)
writel(_value, p);
};
#else
unsigned int lcd_vcbus_read(unsigned int reg)
{
return aml_read_vcbus(reg);
};
void lcd_vcbus_write(unsigned int reg, unsigned int value)
{
aml_write_vcbus(reg, value);
};
#endif
void lcd_vcbus_setb(unsigned int reg, unsigned int value,
unsigned int _start, unsigned int _len)
{
lcd_vcbus_write(reg, ((lcd_vcbus_read(reg) &
(~(((1L << _len)-1) << _start))) |
((value & ((1L << _len)-1)) << _start)));
}
unsigned int lcd_vcbus_getb(unsigned int reg,
unsigned int _start, unsigned int _len)
{
return (lcd_vcbus_read(reg) >> _start) & ((1L << _len)-1);
}
void lcd_vcbus_set_mask(unsigned int reg, unsigned int _mask)
{
lcd_vcbus_write(reg, (lcd_vcbus_read(reg) | (_mask)));
}
void lcd_vcbus_clr_mask(unsigned int reg, unsigned int _mask)
{
lcd_vcbus_write(reg, (lcd_vcbus_read(reg) & (~(_mask))));
}
#if (LCD_REG_IF == LCD_REG_IOREMAP)
unsigned int lcd_hiu_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_hiu_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void lcd_hiu_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_hiu_reg(_reg);
if (p)
writel(_value, p);
};
#else
unsigned int lcd_hiu_read(unsigned int _reg)
{
return aml_read_cbus(_reg);
};
void lcd_hiu_write(unsigned int _reg, unsigned int _value)
{
aml_write_cbus(_reg, _value);
};
#endif
void lcd_hiu_setb(unsigned int _reg, unsigned int _value,
unsigned int _start, unsigned int _len)
{
lcd_hiu_write(_reg, ((lcd_hiu_read(_reg) &
~(((1L << (_len))-1) << (_start))) |
(((_value)&((1L<<(_len))-1)) << (_start))));
}
unsigned int lcd_hiu_getb(unsigned int _reg,
unsigned int _start, unsigned int _len)
{
return (lcd_hiu_read(_reg) >> (_start)) & ((1L << (_len)) - 1);
}
void lcd_hiu_set_mask(unsigned int _reg, unsigned int _mask)
{
lcd_hiu_write(_reg, (lcd_hiu_read(_reg) | (_mask)));
}
void lcd_hiu_clr_mask(unsigned int _reg, unsigned int _mask)
{
lcd_hiu_write(_reg, (lcd_hiu_read(_reg) & (~(_mask))));
}
#if (LCD_REG_IF == LCD_REG_IOREMAP)
unsigned int lcd_cbus_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_cbus_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void lcd_cbus_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_cbus_reg(_reg);
if (p)
writel(_value, p);
};
#else
unsigned int lcd_cbus_read(unsigned int _reg)
{
return aml_read_cbus(_reg);
};
void lcd_cbus_write(unsigned int _reg, unsigned int _value)
{
aml_write_cbus(_reg, _value);
};
#endif
void lcd_cbus_setb(unsigned int _reg, unsigned int _value,
unsigned int _start, unsigned int _len)
{
lcd_cbus_write(_reg, ((lcd_cbus_read(_reg) &
~(((1L << (_len))-1) << (_start))) |
(((_value)&((1L<<(_len))-1)) << (_start))));
}
#if (LCD_REG_IF == LCD_REG_IOREMAP)
unsigned int lcd_periphs_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_periphs_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void lcd_periphs_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_periphs_reg(_reg);
if (p)
writel(_value, p);
};
#else
unsigned int lcd_periphs_read(unsigned int _reg)
{
return aml_read_cbus(_reg);
};
void lcd_periphs_write(unsigned int _reg, unsigned int _value)
{
aml_write_cbus(_reg, _value);
};
#endif
void lcd_pinmux_set_mask(unsigned int n, unsigned int _mask)
{
unsigned int _reg = PERIPHS_PIN_MUX_0;
_reg += n;
lcd_periphs_write(_reg, (lcd_periphs_read(_reg) | (_mask)));
}
void lcd_pinmux_clr_mask(unsigned int n, unsigned int _mask)
{
unsigned int _reg = PERIPHS_PIN_MUX_0;
_reg += n;
lcd_periphs_write(_reg, (lcd_periphs_read(_reg) & (~(_mask))));
}
#if (LCD_REG_IF == LCD_REG_IOREMAP)
unsigned int dsi_host_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_dsi_host_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void dsi_host_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_dsi_host_reg(_reg);
if (p)
writel(_value, p);
};
void dsi_host_setb(unsigned int reg, unsigned int value,
unsigned int _start, unsigned int _len)
{
dsi_host_write(reg, ((dsi_host_read(reg) &
(~(((1L << _len)-1) << _start))) |
((value & ((1L << _len)-1)) << _start)));
}
unsigned int dsi_host_getb(unsigned int reg,
unsigned int _start, unsigned int _len)
{
return (dsi_host_read(reg) >> _start) & ((1L << _len)-1);
}
void dsi_host_set_mask(unsigned int reg, unsigned int _mask)
{
dsi_host_write(reg, (dsi_host_read(reg) | (_mask)));
}
void dsi_host_clr_mask(unsigned int reg, unsigned int _mask)
{
dsi_host_write(reg, (dsi_host_read(reg) & (~(_mask))));
}
unsigned int dsi_phy_read(unsigned int _reg)
{
void __iomem *p;
p = check_lcd_dsi_phy_reg(_reg);
if (p)
return readl(p);
else
return -1;
};
void dsi_phy_write(unsigned int _reg, unsigned int _value)
{
void __iomem *p;
p = check_lcd_dsi_phy_reg(_reg);
if (p)
writel(_value, p);
};
void dsi_phy_setb(unsigned int reg, unsigned int value,
unsigned int _start, unsigned int _len)
{
dsi_phy_write(reg, ((dsi_phy_read(reg) &
(~(((1L << _len)-1) << _start))) |
((value & ((1L << _len)-1)) << _start)));
}
unsigned int dsi_phy_getb(unsigned int reg,
unsigned int _start, unsigned int _len)
{
return (dsi_phy_read(reg) >> _start) & ((1L << _len)-1);
}
void dsi_phy_set_mask(unsigned int reg, unsigned int _mask)
{
dsi_phy_write(reg, (dsi_phy_read(reg) | (_mask)));
}
void dsi_phy_clr_mask(unsigned int reg, unsigned int _mask)
{
dsi_phy_write(reg, (dsi_phy_read(reg) & (~(_mask))));
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
config AMLOGIC_LCD_GAMMA_DEBUG
bool "LCD Gamma debug support"
default n
help
Amlogic LCD gamma debug

View File

@@ -0,0 +1 @@
obj-y += lcd_tablet.o lcd_drv.o mipi_dsi_util.o

View File

@@ -0,0 +1,182 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_tablet/aml_lcd.dts
*
* 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.
*
*/
lcd{
compatible = "amlogic, lcd";
dev_name = "lcd";
mode = "tablet";
status = "okay";
resets = <&clock GCLK_IDX_VCLK2_ENCL &clock GCLK_IDX_VCLK2_VENCL>;
reset-names = "encl","vencl";
pinctrl-names = "ttl_6bit_hvsync_de_on","ttl_6bit_hvsync_on",
"ttl_6bit_de_on","ttl_8bit_hvsync_de_on",
"ttl_8bit_hvsync_on","ttl_8bit_de_on",
"ttl_6bit_hvsync_de_off","ttl_8bit_hvsync_de_off";
pinctrl-0 = <&lcd_ttl_rgb_6bit_pins_on &lcd_ttl_de_hvsync_on_pins>;
pinctrl-1 = <&lcd_ttl_rgb_6bit_pins_on &lcd_ttl_hvsync_on_pins>;
pinctrl-2 = <&lcd_ttl_rgb_6bit_pins_on &lcd_ttl_de_on_pins>;
pinctrl-3 = <&lcd_ttl_rgb_8bit_pins_on &lcd_ttl_de_hvsync_on_pins>;
pinctrl-4 = <&lcd_ttl_rgb_8bit_pins_on &lcd_ttl_hvsync_on_pins>;
pinctrl-5 = <&lcd_ttl_rgb_8bit_pins_on &lcd_ttl_de_on_pins>;
pinctrl-6 = <&lcd_ttl_rgb_6bit_pins_off &lcd_ttl_de_hvsync_off_pins>;
pinctrl-7 = <&lcd_ttl_rgb_8bit_pins_off &lcd_ttl_de_hvsync_off_pins>;
/* power type:(0=cpu_gpio, 1=pmu_gpio,
* 2=signal, 3=extern, 0xff=ending)
*/
/* power index:(point gpios_index, or extern_index, 0xff=invalid) */
/* power value:(0=output low, 1=output high, 2=input) */
/* power delay:(unit in ms) */
lcd_cpu-gpios = <&gpio GPIOX_3 GPIO_ACTIVE_HIGH>;
lcd_cpu_gpio_names = "GPIOX_3";
lcd_0{
model_name = "LCD720P";
interface = "ttl"; /* lcd_interface(ttl, lvds, mipi, edp) */
basic_setting = <1280 720 1650 750 8 16 9>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <40 220 1 5 20 1>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1 74250000>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate,
* pixel_clk(unit in Hz)
*/
ttl_attr = <0 1 1 0 0>;
/* clk_pol, de_valid, hvsync_valid,
* rb_swap, bit_swap
*/
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
lcd_1{
model_name = "HJ080IA";
interface = "lvds"; /* lcd_interface(ttl, lvds, mipi, edp) */
basic_setting = <1024 768 1344 806 8 162 122>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <10 60 0 2 18 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1 65000000>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate,
* pixel_clk(unit in Hz)
*/
lvds_attr = <1 0 0 0>;
/* lvds_repack, dual_port, pn_swap, port_swap */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
/* operation_mode:(bit[0] for init, bit[1] for display.
*0=video mode, 1=command mode)
*/
/* lp_clk_continuous:(0=disable, 1=enable) */
/* transfer_switch:(0=auto, 1=standard, 2=slow) */
/* clk_factor:(special adjust between pixel_clk
* & lanebyte_clk, default 0)
*/
/* mipi-dsi command:(data_type, num, data....).
* data_type=0xff, num=0xff means ending
* num<0xff means delay num(unit: ms)
*/
lcd_2{
model_name = "B080XAN01";
interface = "mipi"; /* lcd_interface(ttl, lvds, mipi, edp) */
basic_setting = <768 1024 948 1140 8 119 159>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <64 56 0 50 30 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1 64843200>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate,
* pixel_clk(unit in Hz)
*/
mipi_attr = <4 0x1 1 0 1 1 550>;
/* lane_count, operation_mode, lp_clk_continuous,
* transfer_switch, factor_denominator,
* factor_numerator, dsi_bit_rate_max (MHz)
*/
dsi_cmd_init_on = <0x05 1 0x11 /* sleep out */
0xff 20 /* delay 20ms */
0x05 1 0x29 /* display on */
0xff 20 /* delay 20ms */
0xff 0xff>; /* ending flag */
dsi_cmd_init_off = <0x05 1 0x28 /* display off */
0xff 10 /* delay 10ms */
0x05 1 0x10 /* sleep in */
0xff 10 /* delay 10ms */
0xff 0xff>; /* ending flag */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
/* link_rate:(0=1.62G, 1=2.7G, 0xff=auto setting) */
/* lane_count:(support 1,2,4, 0xff=auto setting) */
/* link_vswing:(support level 0,1,2,3, 0xff=adaptive) */
/* sync_clk_mode:(0=asyncronous clock,
* 1=synchronous clock. default 1)
*/
/* edid_timing_used:(0=no use, 1=use) */
lcd_3{
model_name = "LP097QX1";
interface = "edp"; /* lcd_interface(ttl, lvds, mipi, edp) */
basic_setting = <2048 1536 2219 1560 8 197 147>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <5 115 0 1 21 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1 207700000>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate,
* pixel_clk(unit in Hz)
*/
edp_attr = <4 1 2 0 1 0>;
/* max_lane_count, link_rate, lane_count, link_vswing,
* sync_clk_mode, edid_timing_used
*/
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.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 __AML_LCD_TABLET_H__
#define __AML_LCD_TABLET_H__
extern void lcd_tablet_config_update(struct lcd_config_s *pconf);
extern void lcd_tablet_config_post_update(struct lcd_config_s *pconf);
extern void lcd_tablet_driver_init_pre(void);
extern int lcd_tablet_driver_init(void);
extern void lcd_tablet_driver_disable(void);
extern void lcd_tablet_driver_tiny_enable(void);
extern void lcd_tablet_driver_tiny_disable(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,539 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.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 MIPI_DSI_UTIL_H
#define MIPI_DSI_UTIL_H
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
/* ********************************************************
* MIPI DSI Data Type/ MIPI DCS Command Type Definitions
* Pheripheral to Host
*/
enum mipi_dsi_data_type_host_e {
DT_VSS = 0x01,
DT_VSE = 0x11,
DT_HSS = 0x21,
DT_HSE = 0x31,
DT_EOTP = 0x08,
DT_CMOFF = 0x02,
DT_CMON = 0x12,
DT_SHUT_DOWN = 0x22,
DT_TURN_ON = 0x32,
DT_GEN_SHORT_WR_0 = 0x03,
DT_GEN_SHORT_WR_1 = 0x13,
DT_GEN_SHORT_WR_2 = 0x23,
DT_GEN_RD_0 = 0x04,
DT_GEN_RD_1 = 0x14,
DT_GEN_RD_2 = 0x24,
DT_DCS_SHORT_WR_0 = 0x05,
DT_DCS_SHORT_WR_1 = 0x15,
DT_DCS_RD_0 = 0x06,
DT_SET_MAX_RET_PKT_SIZE = 0x37,
DT_NULL_PKT = 0x09,
DT_BLANK_PKT = 0x19,
DT_GEN_LONG_WR = 0x29,
DT_DCS_LONG_WR = 0x39,
DT_20BIT_LOOSE_YCBCR = 0x0c,
DT_24BIT_YCBCR = 0x1c,
DT_16BIT_YCBCR = 0x2c,
DT_30BIT_RGB_101010 = 0x0d,
DT_36BIT_RGB_121212 = 0x1d,
DT_12BIT_YCBCR = 0x3d,
DT_16BIT_RGB_565 = 0x0e,
DT_18BIT_RGB_666 = 0x1e,
DT_18BIT_LOOSE_RGB_666 = 0x2e,
DT_24BIT_RGB_888 = 0x3e
};
/* DCS Command List */
#define DCS_ENTER_IDLE_MODE 0x39
#define DCS_ENTER_INVERT_MODE 0x21
#define DCS_ENTER_NORMAL_MODE 0x13
#define DCS_ENTER_PARTIAL_MODE 0x12
#define DCS_ENTER_SLEEP_MODE 0x10
#define DCS_EXIT_IDLE_MODE 0x38
#define DCS_EXIT_INVERT_MODE 0x20
#define DCS_EXIT_SLEEP_MODE 0x11
#define DCS_GET_3D_CONTROL 0x3f
#define DCS_GET_ADDRESS_MODE 0x0b
#define DCS_GET_BLUE_CHANNEL 0x08
#define DCS_GET_DIAGNOSTIC_RESULT 0x0f
#define DCS_GET_DISPLAY_MODE 0x0d
#define DCS_GET_GREEN_CHANNEL 0x07
#define DCS_GET_PIXEL_FORMAT 0x0c
#define DCS_GET_POWER_MODE 0x0a
#define DCS_GET_RED_CHANNEL 0x06
#define DCS_GET_SCANLINE 0x45
#define DCS_GET_SIGNAL_MODE 0x0e
#define DCS_NOP 0x00
#define DCS_READ_DDB_CONTINUE 0xa8
#define DCS_READ_DDB_START 0xa1
#define DCS_READ_MEMORY_CONTINUE 0x3e
#define DCS_READ_MEMORY_START 0x2e
#define DCS_SET_3D_CONTROL 0x3d
#define DCS_SET_ADDRESS_MODE 0x36
#define DCS_SET_COLUMN_ADDRESS 0x2a
#define DCS_SET_DISPLAY_OFF 0x28
#define DCS_SET_DISPLAY_ON 0x29
#define DCS_SET_GAMMA_CURVE 0x26
#define DCS_SET_PAGE_ADDRESS 0x2b
#define DCS_SET_PARTIAL_COLUMNS 0x31
#define DCS_SET_PARTIAL_ROWS 0x30
#define DCS_SET_PIXEL_FORMAT 0x3a
#define DCS_SET_SCROLL_AREA 0x33
#define DCS_SET_SCROLL_START 0x37
#define DCS_SET_TEAR_OFF 0x34
#define DCS_SET_TEAR_ON 0x35
#define DCS_SET_TEAR_SCANLINE 0x44
#define DCS_SET_VSYNC_TIMING 0x40
#define DCS_SOFT_RESET 0x01
#define DCS_WRITE_LUT 0x2d
#define DCS_WRITE_MEMORY_CONTINUE 0x3c
#define DCS_WRITE_MEMORY_START 0x2c
/* Pheripheral to Host
* normal: 0x87(LPDT), data_type, 0, 0, ecc. (write or tearing-effect)
* error: 0x87(LPDT), 0x02, error_code[15:0], ecc.
* short read: 0x87, data_type, data0, data1, ecc
* long read: 0x87, data_type, word_cnt[15:0], ecc, data0, ... data(N-1),
* checksum(or 0)[15:0].
*/
enum mipi_dsi_data_type_peripheral_e {
DT_RESP_TE = 0xba,
DT_RESP_ACK = 0x84,
DT_RESP_ACK_ERR = 0x02,
DT_RESP_EOT = 0x08,
DT_RESP_GEN_READ_1 = 0x11,
DT_RESP_GEN_READ_2 = 0x12,
DT_RESP_GEN_READ_LONG = 0x1a,
DT_RESP_DCS_READ_LONG = 0x1c,
DT_RESP_DCS_READ_1 = 0x21,
DT_RESP_DCS_READ_2 = 0x22,
};
struct dsi_cmd_request_s {
unsigned char data_type;
unsigned char vc_id;
unsigned char *payload;
unsigned short pld_count;
unsigned int req_ack;
};
/* MIPI DCS Pixel-to-Byte Format */
#define DCS_PF_RSVD 0x0
#define DCS_PF_3BIT 0x1
#define DCS_PF_8BIT 0x2
#define DCS_PF_12BIT 0x3
#define DCS_PF_16BIT 0x5
#define DCS_PF_18BIT 0x6
#define DCS_PF_24BIT 0x7
/* MIPI DSI/VENC Color Format Definitions */
#define MIPI_DSI_VENC_COLOR_30B 0x0
#define MIPI_DSI_VENC_COLOR_24B 0x1
#define MIPI_DSI_VENC_COLOR_18B 0x2
#define MIPI_DSI_VENC_COLOR_16B 0x3
#define COLOR_16BIT_CFG_1 0x0
#define COLOR_16BIT_CFG_2 0x1
#define COLOR_16BIT_CFG_3 0x2
#define COLOR_18BIT_CFG_1 0x3
#define COLOR_18BIT_CFG_2 0x4
#define COLOR_24BIT 0x5
#define COLOR_20BIT_LOOSE 0x6
#define COLOR_24_BIT_YCBCR 0x7
#define COLOR_16BIT_YCBCR 0x8
#define COLOR_30BIT 0x9
#define COLOR_36BIT 0xa
#define COLOR_12BIT 0xb
#define COLOR_RGB_111 0xc
#define COLOR_RGB_332 0xd
#define COLOR_RGB_444 0xe
/* MIPI DSI Relative REGISTERs Definitions */
/* For MIPI_DSI_TOP_CNTL */
#define BIT_DPI_COLOR_MODE 20
#define BIT_IN_COLOR_MODE 16
#define BIT_CHROMA_SUBSAMPLE 14
#define BIT_COMP2_SEL 12
#define BIT_COMP1_SEL 10
#define BIT_COMP0_SEL 8
#define BIT_DE_POL 6
#define BIT_HSYNC_POL 5
#define BIT_VSYNC_POL 4
#define BIT_DPICOLORM 3
#define BIT_DPISHUTDN 2
#define BIT_EDPITE_INTR_PULSE 1
#define BIT_ERR_INTR_PULSE 0
/* For MIPI_DSI_DWC_CLKMGR_CFG_OS */
#define BIT_TO_CLK_DIV 8
#define BIT_TX_ESC_CLK_DIV 0
/* For MIPI_DSI_DWC_PCKHDL_CFG_OS */
#define BIT_CRC_RX_EN 4
#define BIT_ECC_RX_EN 3
#define BIT_BTA_EN 2
#define BIT_EOTP_RX_EN 1
#define BIT_EOTP_TX_EN 0
/* For MIPI_DSI_DWC_VID_MODE_CFG_OS */
#define BIT_LP_CMD_EN 15
#define BIT_FRAME_BTA_ACK_EN 14
#define BIT_LP_HFP_EN 13
#define BIT_LP_HBP_EN 12
#define BIT_LP_VCAT_EN 11
#define BIT_LP_VFP_EN 10
#define BIT_LP_VBP_EN 9
#define BIT_LP_VSA_EN 8
#define BIT_VID_MODE_TYPE 0
/* For MIPI_DSI_DWC_PHY_STATUS_OS */
#define BIT_PHY_ULPSACTIVENOT3LANE 12
#define BIT_PHY_STOPSTATE3LANE 11
#define BIT_PHY_ULPSACTIVENOT2LANE 10
#define BIT_PHY_STOPSTATE2LANE 9
#define BIT_PHY_ULPSACTIVENOT1LANE 8
#define BIT_PHY_STOPSTATE1LANE 7
#define BIT_PHY_RXULPSESC0LANE 6
#define BIT_PHY_ULPSACTIVENOT0LANE 5
#define BIT_PHY_STOPSTATE0LANE 4
#define BIT_PHY_ULPSACTIVENOTCLK 3
#define BIT_PHY_STOPSTATECLKLANE 2
#define BIT_PHY_DIRECTION 1
#define BIT_PHY_LOCK 0
/* For MIPI_DSI_DWC_PHY_IF_CFG_OS */
#define BIT_PHY_STOP_WAIT_TIME 8
#define BIT_N_LANES 0
/* For MIPI_DSI_DWC_DPI_COLOR_CODING_OS */
#define BIT_LOOSELY18_EN 8
#define BIT_DPI_COLOR_CODING 0
/* For MIPI_DSI_DWC_GEN_HDR_OS */
#define BIT_GEN_WC_MSBYTE 16
#define BIT_GEN_WC_LSBYTE 8
#define BIT_GEN_VC 6
#define BIT_GEN_DT 0
/* For MIPI_DSI_DWC_LPCLK_CTRL_OS */
#define BIT_AUTOCLKLANE_CTRL 1
#define BIT_TXREQUESTCLKHS 0
/* For MIPI_DSI_DWC_DPI_CFG_POL_OS */
#define BIT_COLORM_ACTIVE_LOW 4
#define BIT_SHUTD_ACTIVE_LOW 3
#define BIT_HSYNC_ACTIVE_LOW 2
#define BIT_VSYNC_ACTIVE_LOW 1
#define BIT_DATAEN_ACTIVE_LOW 0
/* For MIPI_DSI_DWC_CMD_MODE_CFG_OS */
#define BIT_MAX_RD_PKT_SIZE 24
#define BIT_DCS_LW_TX 19
#define BIT_DCS_SR_0P_TX 18
#define BIT_DCS_SW_1P_TX 17
#define BIT_DCS_SW_0P_TX 16
#define BIT_GEN_LW_TX 14
#define BIT_GEN_SR_2P_TX 13
#define BIT_GEN_SR_1P_TX 12
#define BIT_GEN_SR_0P_TX 11
#define BIT_GEN_SW_2P_TX 10
#define BIT_GEN_SW_1P_TX 9
#define BIT_GEN_SW_0P_TX 8
#define BIT_ACK_RQST_EN 1
#define BIT_TEAR_FX_EN 0
/* For MIPI_DSI_DWC_CMD_PKT_STATUS_OS */
/* For DBI no use full */
#define BIT_DBI_RD_CMD_BUSY 14
#define BIT_DBI_PLD_R_FULL 13
#define BIT_DBI_PLD_R_EMPTY 12
#define BIT_DBI_PLD_W_FULL 11
#define BIT_DBI_PLD_W_EMPTY 10
#define BIT_DBI_CMD_FULL 9
#define BIT_DBI_CMD_EMPTY 8
/* For Generic interface */
#define BIT_GEN_RD_CMD_BUSY 6
#define BIT_GEN_PLD_R_FULL 5
#define BIT_GEN_PLD_R_EMPTY 4
#define BIT_GEN_PLD_W_FULL 3
#define BIT_GEN_PLD_W_EMPTY 2
#define BIT_GEN_CMD_FULL 1
#define BIT_GEN_CMD_EMPTY 0
/* For MIPI_DSI_TOP_MEAS_CNTL */
/* measure vsync control */
#define BIT_CNTL_MEAS_VSYNC 10
/* tear measure enable */
#define BIT_EDPITE_MEAS_EN 9
/* not clear the counter */
#define BIT_EDPITE_ACCUM_MEAS_EN 8
#define BIT_EDPITE_VSYNC_SPAN 0
/* For MIPI_DSI_TOP_STAT */
/* signal from halt */
#define BIT_STAT_EDPIHALT 31
/* line number when edpite pulse */
#define BIT_STAT_TE_LINE 16
/* pixel number when edpite pulse */
#define BIT_STAT_TE_PIXEL 0
/* For MIPI_DSI_TOP_INTR_CNTL_STAT */
/* State/Clear for pic_eof */
#define BIT_STAT_CLR_DWC_PIC_EOF 21
/* State/Clear for de_fall */
#define BIT_STAT_CLR_DWC_DE_FALL 20
/* State/Clear for de_rise */
#define BIT_STAT_CLR_DWC_DE_RISE 19
/* State/Clear for vs_fall */
#define BIT_STAT_CLR_DWC_VS_FALL 18
/* State/Clear for vs_rise */
#define BIT_STAT_CLR_DWC_VS_RISE 17
/* State/Clear for edpite */
#define BIT_STAT_CLR_DWC_EDPITE 16
/* end of picture */
#define BIT_PIC_EOF 5
/* data enable fall */
#define BIT_DE_FALL 4
/* data enable rise */
#define BIT_DE_RISE 3
/* vsync fall */
#define BIT_VS_FALL 2
/* vsync rise */
#define BIT_VS_RISE 1
/* edpite int enable */
#define BIT_EDPITE_INT_EN 0
/* For MIPI_DSI_TOP_MEAS_CNTL */
/* vsync measure enable */
#define BIT_VSYNC_MEAS_EN 19
/* vsync accumulate measure */
#define BIT_VSYNC_ACCUM_MEAS_EN 18
/* vsync span */
#define BIT_VSYNC_SPAN 10
/* tearing measure enable */
#define BIT_TE_MEAS_EN 9
/* tearing accumulate measure */
#define BIT_TE_ACCUM_MEAS_EN 8
/* tearing span */
#define BIT_TE_SPAN 0
/* For MIPI_DSI_DWC_INT_ST0_OS */
/* LP1 contention error from lane0 */
#define BIT_DPHY_ERR_4 20
/* LP0 contention error from lane0 */
#define BIT_DPHY_ERR_3 19
/* ErrControl error from lane0 */
#define BIT_DPHY_ERR_2 18
/* ErrSyncEsc error from lane0 */
#define BIT_DPHY_ERR_1 17
/* ErrEsc escape error lane0 */
#define BIT_DPHY_ERR_0 16
#define BIT_ACK_ERR_15 15
#define BIT_ACK_ERR_14 14
#define BIT_ACK_ERR_13 13
#define BIT_ACK_ERR_12 12
#define BIT_ACK_ERR_11 11
#define BIT_ACK_ERR_10 10
#define BIT_ACK_ERR_9 9
#define BIT_ACK_ERR_8 8
#define BIT_ACK_ERR_7 7
#define BIT_ACK_ERR_6 6
#define BIT_ACK_ERR_5 5
#define BIT_ACK_ERR_4 4
#define BIT_ACK_ERR_3 3
#define BIT_ACK_ERR_2 2
#define BIT_ACK_ERR_1 1
#define BIT_ACK_ERR_0 0
/* Command transfer type in command mode */
#define DCS_TRANS_HS 0
#define DCS_TRANS_LP 1
#define MIPI_DSI_DCS_NO_ACK 0
#define MIPI_DSI_DCS_REQ_ACK 1
/* DSI Tear Defines */
#define MIPI_DCS_SET_TEAR_ON_MODE_0 0
#define MIPI_DCS_SET_TEAR_ON_MODE_1 1
#define MIPI_DCS_ENABLE_TEAR 1
#define MIPI_DCS_DISABLE_TEAR 0
/* Pixel FIFO Depth */
#define PIXEL_FIFO_DEPTH 1440
#define BYTE_PER_PIXEL_COLOR_16BIT_CFG_1 2
#define BYTE_PER_PIXEL_COLOR_16BIT_CFG_2 2
#define BYTE_PER_PIXEL_COLOR_16BIT_CFG_3 2
#define BYTE_PER_PIXEL_COLOR_18BIT_CFG_1 3
#define BYTE_PER_PIXEL_COLOR_18BIT_CFG_2 3
#define BYTE_PER_PIXEL_COLOR_24BIT 3
#define BYTE_PER_PIXEL_COLOR_20BIT_LOOSE 3
#define BYTE_PER_PIXEL_COLOR_24_BIT_YCBCR 3
#define BYTE_PER_PIXEL_COLOR_16BIT_YCBCR 2
#define BYTE_PER_PIXEL_COLOR_30BIT 4
#define BYTE_PER_PIXEL_COLOR_36BIT 5
/* in fact it should be 1.5(12bit) */
#define BYTE_PER_PIXEL_COLOR_12BIT 3
/* Tearing Interrupt Bit */
#define INT_TEARING 6
enum tv_enc_lcd_type_e {
TV_ENC_LCD480x234 = 0,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD480x234_dsi36b = 1,
TV_ENC_LCD240x160 = 2,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD240x160_dsi36b = 3,
TV_ENC_LCD720x480 = 4,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD720x480_dsi36b = 5,
TV_ENC_LCD720x576 = 6,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD720x576_dsi36b = 7,
TV_ENC_LCD1280x720 = 8,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD1280x720_dsi36b = 9,
TV_ENC_LCD1920x1080 = 10,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD1920x1080_dsi36b = 11,
TV_ENC_LCD1920x2205 = 12,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD1920x2205_dsi36b = 13,
TV_ENC_LCD2560x1600 = 14,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD2560x1600_dsi36b = 15,
TV_ENC_LCD3840x2440 = 16,
/* For MIPI_DSI 36-bit color: sample rate=2, 1 pixel per 2 cycle */
TV_ENC_LCD3840x2440_dsi36b = 17,
TV_ENC_LCD3840x2160p_vic03 = 18,
TV_ENC_LCD4096x2160p_vic04 = 19,
TV_ENC_LCD640x480 = 20,
TV_ENC_LCD1920x1200p = 21,
TV_ENC_LCD240x160_dsi = 22,
TV_ENC_LCD240x160_slow = 23,
TV_ENC_LCD3840x2160p_vic01 = 24,
TV_ENC_LCD2048x1536 = 25,
TV_ENC_LCD768x1024p = 26,
TV_ENC_LCD_TYPE_MAX
}; /* tv encoder output format */
/* DCS COMMAND LIST */
#define DCS_CMD_CODE_ENTER_IDLE_MODE 0x0
#define DCS_CMD_CODE_ENTER_INVERT_MODE 0x1
#define DCS_CMD_CODE_ENTER_NORMAL_MODE 0x2
#define DCS_CMD_CODE_ENTER_PARTIAL_MODE 0x3
#define DCS_CMD_CODE_ENTER_SLEEP_MODE 0x4
#define DCS_CMD_CODE_EXIT_IDLE_MODE 0x5
#define DCS_CMD_CODE_EXIT_INVERT_MODE 0x6
#define DCS_CMD_CODE_EXIT_SLEEP_MODE 0x7
#define DCS_CMD_CODE_NOP 0x8
#define DCS_CMD_CODE_SET_DISPLAY_OFF 0x9
#define DCS_CMD_CODE_SET_DISPLAY_ON 0xa
#define DCS_CMD_CODE_SET_TEAR_OFF 0xb
#define DCS_CMD_CODE_SOFT_RESET 0xc
/* DPHY standard timing */
/* unit: MHz */
#define MIPI_PHY_CLK_MAX 1000
/* **** DPHY timing parameter Value (unit: 0.01ns) **** */
/* >100ns (4M) */
#define DPHY_TIME_LP_TESC(ui) (250 * 100)
/* >50ns */
#define DPHY_TIME_LP_LPX(ui) (100 * 100)
/* (lpx, 2*lpx) */
#define DPHY_TIME_LP_TA_SURE(ui) DPHY_TIME_LP_LPX(ui)
/* 4*lpx */
#define DPHY_TIME_LP_TA_GO(ui) (4 * DPHY_TIME_LP_LPX(ui))
/* 5*lpx */
#define DPHY_TIME_LP_TA_GETX(ui) (5 * DPHY_TIME_LP_LPX(ui))
/* >100ns */
#define DPHY_TIME_HS_EXIT(ui) (120 * 100)
/* max(8*ui, 60+4*ui), (teot)<105+12*ui */
#define DPHY_TIME_HS_TRAIL(ui) ((ui > (60 * 100 / 4)) ? \
(8 * ui) : ((60 * 100) + 4 * ui))
/* (40+4*ui, 85+6*ui) */
#define DPHY_TIME_HS_PREPARE(ui) (50 * 100 + 4 * t_ui)
/* hs_prepare+hs_zero >145+10*ui */
#define DPHY_TIME_HS_ZERO(ui) (160 * 100 + 10 * ui - \
DPHY_TIME_HS_PREPARE(ui))
/* >60ns, (teot)<105+12*ui */
#define DPHY_TIME_CLK_TRAIL(ui) (70 * 100)
/* >60+52*ui */
#define DPHY_TIME_CLK_POST(ui) (70 * 100 + 52 * ui)
/* (38, 95) */
#define DPHY_TIME_CLK_PREPARE(ui) (50 * 100)
/* clk_prepare+clk_zero > 300 */
#define DPHY_TIME_CLK_ZERO(ui) (320 * 100 - DPHY_TIME_CLK_PREPARE(ui))
/* >8*ui */
#define DPHY_TIME_CLK_PRE(ui) (10 * ui)
/* >100us */
#define DPHY_TIME_INIT(ui) (110 * 1000 * 100)
/* >1ms */
#define DPHY_TIME_WAKEUP(ui) (1020 * 1000 * 100)
struct dsi_phy_s {
unsigned int lp_tesc;
unsigned int lp_lpx;
unsigned int lp_ta_sure;
unsigned int lp_ta_go;
unsigned int lp_ta_get;
unsigned int hs_exit;
unsigned int hs_trail;
unsigned int hs_zero;
unsigned int hs_prepare;
unsigned int clk_trail;
unsigned int clk_post;
unsigned int clk_zero;
unsigned int clk_prepare;
unsigned int clk_pre;
unsigned int init;
unsigned int wakeup;
};
struct dsi_vid_s {
unsigned int hline;
unsigned int hsa;
unsigned int hbp;
unsigned int vsa;
unsigned int vbp;
unsigned int vfp;
unsigned int vact;
/* for non-burst chunk overhead */
unsigned int pixel_per_chunk;
unsigned int num_of_chunk;
unsigned int vid_null_size;
};
#define DSI_CMD_SIZE_MAX 2000
/* #define DSI_CMD_READ_VALID // DPHY don't support for M8 */
extern void mipi_dsi_print_info(struct lcd_config_s *pconf);
extern int lcd_mipi_dsi_init_table_detect(struct device_node *m_node,
struct dsi_config_s *dconf, int on_off);
extern void lcd_mipi_dsi_config_set(struct lcd_config_s *pconf);
extern void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf);
extern void mipi_dsi_link_off(struct lcd_config_s *pconf);
extern void lcd_mipi_control_set(struct lcd_config_s *pconf, int status);
#endif

View File

@@ -0,0 +1 @@
obj-$(CONFIG_AMLOGIC_LCD_TV) += lcd_tv.o lcd_drv.o

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.dts
*
* 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.
*
*/
lcd{
compatible = "amlogic, lcd";
dev_name = "lcd";
mode = "tv";
status = "okay";
resets = <&clock GCLK_IDX_VCLK2_ENCL &clock GCLK_IDX_VCLK2_VENCL>;
reset-names = "encl","vencl";
interrupts = <0 78 1 0 3 1>;
interrupt-names = "vbyone","vbyone_vsync";
pinctrl-names = "vbyone";
pinctrl-0 = <&lcd_vbyone_pins>;
/* power type:(0=cpu, 1=pmu, 2=signal, 3=extern, 0xff=ending) */
/* power index:(point gpios_index, or extern_index, 0xff=invalid) */
/* power value:(0=output low, 1=output high, 2=input) */
/* power delay:(unit in ms) */
lcd_cpu-gpios = <&gpio GPIOX_3 GPIO_ACTIVE_HIGH>;
lcd_cpu_gpio_names = "GPIOX_3";
lvds_0{
model_name = "public";
interface = "lvds"; /* lcd_interface(lvds, vbyone) */
basic_setting = <1920 1080 2200 1125 8 16 9>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <44 148 0 5 30 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate
*/
lvds_attr = <1 1 0 0>;
/** lvds_repack, dual_port, pn_swap, port_swap */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
vbyone_0{
model_name = "BOE_HV550QU2";
interface = "vbyone"; /* lcd_interface(lvds, vbyone) */
basic_setting = <3840 2160 4400 2250 10 16 9>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <33 477 0 6 65 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <0 0 1>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate
*/
vbyone_attr = <8 2 4 4>;
/** lane_count, region_num, byte_mode, color_fmt */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
vbyone_1{
model_name = "LG_RDL550WY";
interface = "vbyone"; /* lcd_interface(lvds, vbyone) */
basic_setting = <3840 2160 4400 2250 10 16 9>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <33 477 0 6 65 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <2 0 1>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate
*/
vbyone_attr = <8 2 4 4>;
/** lane_count, region_num, byte_mode, color_fmt */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
vbyone_2{
model_name = "INL_V580DJ2";
interface = "vbyone"; /* lcd_interface(lvds, vbyone) */
basic_setting = <3840 2160 4400 2250 10 16 9>;
/* h_active, v_active, h_period, v_period, lcd_bits,
* screen_widht, screen_height
*/
lcd_timing = <33 477 0 6 65 0>;
/* hs_width, hs_bp, hs_pol, vs_width, vs_bp, vs_pol */
clk_attr = <2 0 1>;
/* fr_adj_type(0=clock, 1=htotal, 2=vtotal),
* clk_ss_level, clk_auto_generate
*/
vbyone_attr = <8 1 4 4>;
/** lane_count, region_num, byte_mode, color_fmt */
power_on_step = <0 0 1 50
2 0 0 0
0xff 0 0 0>; /* type, index, value, delay */
power_off_step = <2 0 0 50
0 0 0 100
0xff 0 0 0>; /* type, index, value, delay */
backlight_index = <0>;
};
};

View File

@@ -0,0 +1,34 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.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 __AML_LCD_TV_H__
#define __AML_LCD_TV_H__
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
extern void lcd_tv_config_update(struct lcd_config_s *pconf);
extern void lcd_tv_driver_init_pre(void);
extern int lcd_tv_driver_init(void);
extern void lcd_tv_driver_disable(void);
extern int lcd_tv_driver_change(void);
extern void lcd_tv_driver_tiny_enable(void);
extern void lcd_tv_driver_tiny_disable(void);
extern void lcd_vbyone_wait_stable(void);
extern void lcd_vbyone_interrupt_up(void);
extern void lcd_vbyone_interrupt_down(void);
#endif

View File

@@ -0,0 +1,301 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_unifykey.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.
*
*/
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/reset.h>
#include <linux/amlogic/media/vout/lcd/lcd_unifykey.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#define LCDUKEY(fmt, args...) pr_info("lcd ukey: "fmt"", ## args)
#define LCDUKEYERR(fmt, args...) pr_info("lcd ukey err: error: "fmt"", ## args)
#ifdef CONFIG_KEY_MANAGE
static unsigned int cal_crc32(unsigned int crc, const unsigned char *buf,
int buf_len) {
unsigned int s_crc32[16] = {
0, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
};
unsigned int crcu32 = crc;
unsigned char b;
if (buf_len <= 0)
return 0;
if (!buf)
return 0;
crcu32 = ~crcu32;
while (buf_len--) {
b = *buf++;
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
}
return ~crcu32;
}
int lcd_unifykey_len_check(int key_len, int len)
{
if (key_len < len) {
LCDUKEYERR("invalid unifykey length %d, need %d\n",
key_len, len);
return -1;
}
return 0;
}
int lcd_unifykey_header_check(unsigned char *buf,
struct aml_lcd_unifykey_header_s *header)
{
header->crc32 = (buf[0] | (buf[1] << 8) |
(buf[2] << 16) | (buf[3] << 24));
header->data_len = (buf[4] | (buf[5] << 8));
header->version = (buf[6] | (buf[7] << 8));
header->reserved = (buf[8] | (buf[9] << 8));
return 0;
}
int lcd_unifykey_check(char *key_name)
{
unsigned int key_exist, keypermit, key_len;
unsigned char buf[550];
struct aml_lcd_unifykey_header_s key_header;
int retry_cnt = 0;
unsigned int key_crc32;
int ret;
key_exist = 0;
key_len = 0;
ret = key_unify_query(key_name, &key_exist, &keypermit);
if (ret < 0) {
if (lcd_debug_print_flag)
LCDUKEYERR("%s query exist error\n", key_name);
return -1;
}
if (key_exist == 0) {
if (lcd_debug_print_flag)
LCDUKEYERR("%s is not exist\n", key_name);
return -1;
}
ret = key_unify_size(key_name, &key_len);
if (ret < 0) {
LCDUKEYERR("%s query size error\n", key_name);
return -1;
}
if (key_len == 0) {
if (lcd_debug_print_flag)
LCDUKEY("%s size is zero\n", key_name);
return -1;
}
if (lcd_debug_print_flag)
LCDUKEY("%s size: %d\n", key_name, key_len);
lcd_unifykey_read:
ret = key_unify_read(key_name, buf, key_len, &key_len);
if (ret < 0) {
LCDUKEYERR("%s unify read error\n", key_name);
return -1;
}
/* check header */
if (key_len <= LCD_UKEY_HEAD_SIZE) {
LCDUKEYERR("%s unify key_len %d error\n", key_name, key_len);
return -1;
}
lcd_unifykey_header_check(buf, &key_header);
if (key_len != key_header.data_len) { /* length check */
if (lcd_debug_print_flag) {
LCDUKEYERR("data_len %d is not match key_len %d\n",
key_header.data_len, key_len);
}
if (retry_cnt < LCD_UKEY_RETRY_CNT_MAX) {
retry_cnt++;
goto lcd_unifykey_read;
} else {
LCDUKEYERR("%s: load unifykey failed\n", key_name);
return -1;
}
}
key_crc32 = cal_crc32(0, &buf[4], (key_len - 4)); /* except crc32 */
if (lcd_debug_print_flag) {
LCDUKEY("crc32: 0x%08x, header_crc32: 0x%08x\n",
key_crc32, key_header.crc32);
}
if (key_crc32 != key_header.crc32) { /* crc32 check */
LCDUKEYERR("crc32 0x%08x is not match header_crc32 0x%08x\n",
key_header.crc32, key_crc32);
if (retry_cnt < LCD_UKEY_RETRY_CNT_MAX) {
retry_cnt++;
goto lcd_unifykey_read;
} else {
LCDUKEYERR("%s: load unifykey failed\n", key_name);
return -1;
}
}
return 0;
}
int lcd_unifykey_get(char *key_name, unsigned char *buf, int *len)
{
int key_len;
int ret;
key_len = 0;
ret = lcd_unifykey_check(key_name);
if (ret < 0)
return -1;
ret = key_unify_size(key_name, &key_len);
if (key_len > *len) {
LCDUKEYERR("%s size(%d) is bigger than buf_size(%d)\n",
key_name, key_len, *len);
return -1;
}
*len = key_len;
ret = key_unify_read(key_name, buf, key_len, &key_len);
if (ret < 0) {
LCDUKEYERR("%s unify read error\n", key_name);
return -1;
}
return 0;
}
void lcd_unifykey_print(void)
{
unsigned char buf[600];
char *key_name;
unsigned int key_len;
int i, j;
int ret;
key_name = "lcd";
key_len = LCD_UKEY_LCD_SIZE;
ret = lcd_unifykey_get(key_name, buf, &key_len);
if (ret < 0)
return;
LCDUKEY("%s: %s: %d\n", __func__, key_name, key_len);
i = 0;
while (1) {
pr_info("0x%08x: ", (i * 16));
for (j = 0; j < 16; j++) {
if ((i*16+j) < key_len) {
pr_info("0x%02x ", buf[i*16+j]);
} else {
pr_info("\n");
goto exit_print_lcd;
}
}
pr_info("\n");
i++;
}
exit_print_lcd:
key_name = "lcd_extern";
key_len = LCD_UKEY_LCD_EXT_SIZE;
ret = lcd_unifykey_get(key_name, buf, &key_len);
if (ret < 0)
return;
LCDUKEY("%s: %s: %d\n", __func__, key_name, key_len);
i = 0;
while (1) {
pr_info("0x%08x: ", (i * 16));
for (j = 0; j < 16; j++) {
if ((i*16+j) < key_len) {
pr_info("0x%02x ", buf[i*16+j]);
} else {
pr_info("\n");
goto exit_print_lcd_ext;
}
}
pr_info("\n");
i++;
}
exit_print_lcd_ext:
key_name = "backlight";
key_len = LCD_UKEY_BL_SIZE;
ret = lcd_unifykey_get(key_name, buf, &key_len);
if (ret < 0)
return;
LCDUKEY("%s: %s: %d\n", __func__, key_name, key_len);
i = 0;
while (1) {
pr_info("0x%08x: ", (i * 16));
for (j = 0; j < 16; j++) {
if ((i*16+j) < key_len) {
pr_info("0x%02x ", buf[i*16+j]);
} else {
pr_info("\n");
goto exit_print_backlight;
}
}
pr_info("\n");
i++;
}
exit_print_backlight:
return;
}
#else
/* dummy driver */
int lcd_unifykey_len_check(int key_len, int len)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int lcd_unifykey_header_check(unsigned char *buf,
struct aml_lcd_unifykey_header_s *header)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int lcd_unifykey_check(char *key_name)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int lcd_unifykey_get(char *key_name, unsigned char *buf, int *len)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
void lcd_unifykey_print(void)
{
LCDUKEYERR("Don't support unifykey\n");
}
#endif

View File

@@ -0,0 +1,998 @@
/*
* drivers/amlogic/media/vout/lcd/lcd_vout.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.
*
*/
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/clk.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#endif
#include <linux/reset.h>
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/vout/vinfo.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
#include <linux/amlogic/media/vout/lcd/lcd_unifykey.h>
#ifdef CONFIG_AMLOGIC_LCD_EXTERN
#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
#endif
#include "lcd_reg.h"
#include "lcd_common.h"
#define LCD_CDEV_NAME "lcd"
unsigned char lcd_debug_print_flag;
unsigned char lcd_resume_flag;
static struct aml_lcd_drv_s *lcd_driver;
struct mutex lcd_power_mutex;
struct mutex lcd_vout_mutex;
int lcd_vout_serve_bypass;
static char lcd_propname[20] = "lvds_0";
struct lcd_cdev_s {
dev_t devno;
struct cdev cdev;
struct device *dev;
};
static struct lcd_cdev_s *lcd_cdev;
/* lcd config define */
static struct ttl_config_s lcd_ttl_config = {
.clk_pol = 0,
.sync_valid = ((1 << 1) | (1 << 0)),
.swap_ctrl = ((0 << 1) | (0 << 0)),
};
static struct lvds_config_s lcd_lvds_config = {
.lvds_vswing = 1,
.lvds_repack = 1,
.dual_port = 0,
.pn_swap = 0,
.port_swap = 0,
.lane_reverse = 0,
.port_sel = 0,
.phy_vswing = LVDS_PHY_VSWING_DFT,
.phy_preem = LVDS_PHY_PREEM_DFT,
};
static struct vbyone_config_s lcd_vbyone_config = {
.lane_count = 8,
.region_num = 2,
.byte_mode = 4,
.color_fmt = 4,
.phy_div = 1,
.bit_rate = 0,
.phy_vswing = VX1_PHY_VSWING_DFT,
.phy_preem = VX1_PHY_PREEM_DFT,
.intr_en = 1,
.vsync_intr_en = 1,
};
static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff};
static unsigned char dsi_init_off_table[DSI_INIT_OFF_MAX] = {0xff, 0xff};
static struct dsi_config_s lcd_mipi_config = {
.lane_num = 4,
.bit_rate_max = 550, /* MHz */
.factor_numerator = 0,
.factor_denominator = 100,
.operation_mode_init = 1, /* 0=video mode, 1=command mode */
.operation_mode_display = 0, /* 0=video mode, 1=command mode */
.video_mode_type = 2, /* 0=sync_pulse, 1=sync_event, 2=burst */
.clk_lp_continuous = 1, /* 0=stop, 1=continue */
.phy_stop_wait = 0, /* 0=auto, 1=standard, 2=slow */
.dsi_init_on = &dsi_init_on_table[0],
.dsi_init_off = &dsi_init_off_table[0],
.extern_init = 0xff,
/* ext_index if needed, must match ext_config index;
* 0xff for invalid
*/
};
static struct lcd_power_ctrl_s lcd_power_config = {
.cpu_gpio = {
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
{.flag = 0,},
},
.power_on_step = {
{
.type = LCD_POWER_TYPE_MAX,
},
},
.power_off_step = {
{
.type = LCD_POWER_TYPE_MAX,
},
},
};
static struct lcd_config_s lcd_config_dft = {
.lcd_propname = lcd_propname,
.lcd_basic = {
.lcd_type = LCD_TYPE_MAX,
},
.lcd_timing = {
.lcd_clk = 0,
.clk_auto = 1,
.ss_level = 0,
.fr_adjust_type = 0,
},
.hdr_info = {
.hdr_support = 0,
.features = 0,
.primaries_r_x = 0,
.primaries_r_y = 0,
.primaries_g_x = 0,
.primaries_g_y = 0,
.primaries_b_x = 0,
.primaries_b_y = 0,
.white_point_x = 0,
.white_point_y = 0,
.luma_max = 0,
.luma_min = 0,
.luma_avg = 0,
},
.lcd_control = {
.ttl_config = &lcd_ttl_config,
.lvds_config = &lcd_lvds_config,
.vbyone_config = &lcd_vbyone_config,
.mipi_config = &lcd_mipi_config,
},
.lcd_power = &lcd_power_config,
};
static struct vinfo_s lcd_vinfo = {
.name = "panel",
.mode = VMODE_LCD,
.viu_color_fmt = COLOR_FMT_RGB444,
};
struct aml_lcd_drv_s *aml_lcd_get_driver(void)
{
return lcd_driver;
}
/* ********************************************************* */
static void lcd_chip_detect(void)
{
unsigned int cpu_type;
cpu_type = get_cpu_type();
switch (cpu_type) {
case MESON_CPU_MAJOR_ID_GXTVBB:
lcd_driver->chip_type = LCD_CHIP_GXTVBB;
break;
case MESON_CPU_MAJOR_ID_GXL:
lcd_driver->chip_type = LCD_CHIP_GXL;
break;
case MESON_CPU_MAJOR_ID_GXM:
lcd_driver->chip_type = LCD_CHIP_GXM;
break;
case MESON_CPU_MAJOR_ID_TXL:
lcd_driver->chip_type = LCD_CHIP_TXL;
break;
case MESON_CPU_MAJOR_ID_TXLX:
lcd_driver->chip_type = LCD_CHIP_TXLX;
break;
case MESON_CPU_MAJOR_ID_AXG:
lcd_driver->chip_type = LCD_CHIP_AXG;
break;
default:
lcd_driver->chip_type = LCD_CHIP_MAX;
}
if (lcd_debug_print_flag)
LCDPR("check chip: %d\n", lcd_driver->chip_type);
}
static void lcd_power_tiny_ctrl(int status)
{
struct lcd_power_ctrl_s *lcd_power = lcd_driver->lcd_config->lcd_power;
struct lcd_power_step_s *power_step;
#ifdef CONFIG_AMLOGIC_LCD_EXTERN
struct aml_lcd_extern_driver_s *ext_drv;
#endif
int i, index;
LCDPR("%s: %d\n", __func__, status);
i = 0;
while (i < LCD_PWR_STEP_MAX) {
if (status)
power_step = &lcd_power->power_on_step[i];
else
power_step = &lcd_power->power_off_step[i];
if (power_step->type >= LCD_POWER_TYPE_MAX)
break;
if (lcd_debug_print_flag) {
LCDPR("power_tiny_ctrl: %d, step %d\n", status, i);
LCDPR("type=%d, index=%d, value=%d, delay=%d\n",
power_step->type, power_step->index,
power_step->value, power_step->delay);
}
switch (power_step->type) {
case LCD_POWER_TYPE_CPU:
index = power_step->index;
lcd_cpu_gpio_set(index, power_step->value);
break;
case LCD_POWER_TYPE_PMU:
LCDPR("to do\n");
break;
case LCD_POWER_TYPE_SIGNAL:
if (status)
lcd_driver->driver_tiny_enable();
else
lcd_driver->driver_tiny_disable();
break;
#ifdef CONFIG_AMLOGIC_LCD_EXTERN
case LCD_POWER_TYPE_EXTERN:
index = power_step->index;
ext_drv = aml_lcd_extern_get_driver(index);
if (ext_drv) {
if (status) {
if (ext_drv->power_on)
ext_drv->power_on();
else
LCDERR("no ext power on\n");
} else {
if (ext_drv->power_off)
ext_drv->power_off();
else
LCDERR("no ext power off\n");
}
}
break;
#endif
default:
break;
}
if (power_step->delay)
mdelay(power_step->delay);
i++;
}
if (lcd_debug_print_flag)
LCDPR("%s: %d finished\n", __func__, status);
}
static void lcd_power_ctrl(int status)
{
struct lcd_power_ctrl_s *lcd_power = lcd_driver->lcd_config->lcd_power;
struct lcd_power_step_s *power_step;
#ifdef CONFIG_AMLOGIC_LCD_EXTERN
struct aml_lcd_extern_driver_s *ext_drv;
#endif
int i, index;
int ret = 0;
LCDPR("%s: %d\n", __func__, status);
i = 0;
while (i < LCD_PWR_STEP_MAX) {
if (status)
power_step = &lcd_power->power_on_step[i];
else
power_step = &lcd_power->power_off_step[i];
if (power_step->type >= LCD_POWER_TYPE_MAX)
break;
if (lcd_debug_print_flag) {
LCDPR("power_ctrl: %d, step %d\n", status, i);
LCDPR("type=%d, index=%d, value=%d, delay=%d\n",
power_step->type, power_step->index,
power_step->value, power_step->delay);
}
switch (power_step->type) {
case LCD_POWER_TYPE_CPU:
index = power_step->index;
lcd_cpu_gpio_set(index, power_step->value);
break;
case LCD_POWER_TYPE_PMU:
LCDPR("to do\n");
break;
case LCD_POWER_TYPE_SIGNAL:
if (status)
ret = lcd_driver->driver_init();
else
lcd_driver->driver_disable();
break;
#ifdef CONFIG_AMLOGIC_LCD_EXTERN
case LCD_POWER_TYPE_EXTERN:
index = power_step->index;
ext_drv = aml_lcd_extern_get_driver(index);
if (ext_drv) {
if (status) {
if (ext_drv->power_on)
ext_drv->power_on();
else
LCDERR("no ext power on\n");
} else {
if (ext_drv->power_off)
ext_drv->power_off();
else
LCDERR("no ext power off\n");
}
}
break;
#endif
default:
break;
}
if (power_step->delay)
mdelay(power_step->delay);
i++;
}
if (lcd_debug_print_flag)
LCDPR("%s: %d finished\n", __func__, status);
}
static void lcd_module_enable(void)
{
mutex_lock(&lcd_vout_mutex);
lcd_driver->driver_init_pre();
lcd_driver->power_ctrl(1);
lcd_driver->lcd_status = 1;
mutex_unlock(&lcd_vout_mutex);
}
static void lcd_module_disable(void)
{
mutex_lock(&lcd_vout_mutex);
lcd_driver->lcd_status = 0;
lcd_driver->power_ctrl(0);
mutex_unlock(&lcd_vout_mutex);
}
static void lcd_module_reset(void)
{
mutex_lock(&lcd_vout_mutex);
lcd_driver->lcd_status = 0;
lcd_driver->power_ctrl(0);
msleep(500);
lcd_driver->driver_init_pre();
lcd_driver->power_ctrl(1);
lcd_driver->lcd_status = 1;
mutex_unlock(&lcd_vout_mutex);
}
static void lcd_module_tiny_reset(void)
{
mutex_lock(&lcd_vout_mutex);
lcd_driver->lcd_status = 0;
lcd_power_tiny_ctrl(0);
mdelay(500);
lcd_power_tiny_ctrl(1);
lcd_driver->lcd_status = 1;
mutex_unlock(&lcd_vout_mutex);
}
/* lcd notify */
static int lcd_power_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
if (lcd_debug_print_flag)
LCDPR("%s: 0x%lx\n", __func__, event);
if (event & LCD_EVENT_LCD_ON)
lcd_module_enable();
else if (event & LCD_EVENT_LCD_OFF)
lcd_module_disable();
else
return NOTIFY_DONE;
return NOTIFY_OK;
}
static struct notifier_block lcd_power_nb = {
.notifier_call = lcd_power_notifier,
.priority = LCD_PRIORITY_POWER_LCD,
};
static int lcd_interface_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
if (lcd_debug_print_flag)
LCDPR("%s: 0x%lx\n", __func__, event);
if (event & LCD_EVENT_IF_ON)
lcd_driver->power_tiny_ctrl(1);
else if (event & LCD_EVENT_IF_OFF)
lcd_driver->power_tiny_ctrl(0);
else
return NOTIFY_DONE;
return NOTIFY_OK;
}
static struct notifier_block lcd_interface_nb = {
.notifier_call = lcd_interface_notifier,
.priority = LCD_PRIORITY_POWER_LCD,
};
static int lcd_bl_select_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
unsigned int *index;
/* LCDPR("%s: 0x%lx\n", __func__, event); */
if ((event & LCD_EVENT_BACKLIGHT_SEL) == 0)
return NOTIFY_DONE;
index = (unsigned int *)data;
*index = lcd_driver->lcd_config->backlight_index;
return NOTIFY_OK;
}
static struct notifier_block lcd_bl_select_nb = {
.notifier_call = lcd_bl_select_notifier,
};
/* **************************************** */
/* ************************************************************* */
/* lcd ioctl */
/* ************************************************************* */
static int lcd_io_open(struct inode *inode, struct file *file)
{
struct lcd_cdev_s *lcd_cdev;
LCDPR("%s\n", __func__);
lcd_cdev = container_of(inode->i_cdev, struct lcd_cdev_s, cdev);
file->private_data = lcd_cdev;
return 0;
}
static int lcd_io_release(struct inode *inode, struct file *file)
{
LCDPR("%s\n", __func__);
file->private_data = NULL;
return 0;
}
static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
void __user *argp;
int mcd_nr;
struct lcd_hdr_info_s *hdr_info = &lcd_driver->lcd_config->hdr_info;
mcd_nr = _IOC_NR(cmd);
LCDPR("%s: cmd_dir = 0x%x, cmd_nr = 0x%x\n",
__func__, _IOC_DIR(cmd), mcd_nr);
argp = (void __user *)arg;
switch (mcd_nr) {
case LCD_IOC_NR_GET_HDR_INFO:
if (copy_to_user(argp, hdr_info, sizeof(struct lcd_hdr_info_s)))
ret = -EFAULT;
break;
case LCD_IOC_NR_SET_HDR_INFO:
if (copy_from_user(hdr_info, argp,
sizeof(struct lcd_hdr_info_s))) {
ret = -EFAULT;
} else {
lcd_hdr_vinfo_update();
if (lcd_debug_print_flag) {
LCDPR("set hdr_info:\n"
"hdr_support %d\n"
"features %d\n"
"primaries_r_x %d\n"
"primaries_r_y %d\n"
"primaries_g_x %d\n"
"primaries_g_y %d\n"
"primaries_b_x %d\n"
"primaries_b_y %d\n"
"white_point_x %d\n"
"white_point_y %d\n"
"luma_max %d\n"
"luma_min %d\n\n",
hdr_info->hdr_support,
hdr_info->features,
hdr_info->primaries_r_x,
hdr_info->primaries_r_y,
hdr_info->primaries_g_x,
hdr_info->primaries_g_y,
hdr_info->primaries_b_x,
hdr_info->primaries_b_y,
hdr_info->white_point_x,
hdr_info->white_point_y,
hdr_info->luma_max,
hdr_info->luma_min);
}
}
break;
default:
LCDERR("not support ioctl cmd_nr: 0x%x\n", mcd_nr);
ret = -EINVAL;
break;
}
return ret;
}
#ifdef CONFIG_COMPAT
static long lcd_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned long ret;
arg = (unsigned long)compat_ptr(arg);
ret = lcd_ioctl(file, cmd, arg);
return ret;
}
#endif
static const struct file_operations lcd_fops = {
.owner = THIS_MODULE,
.open = lcd_io_open,
.release = lcd_io_release,
.unlocked_ioctl = lcd_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = lcd_compat_ioctl,
#endif
};
static int lcd_fops_create(void)
{
int ret = 0;
lcd_cdev = kmalloc(sizeof(struct lcd_cdev_s), GFP_KERNEL);
if (!lcd_cdev) {
LCDERR("%s: failed to allocate lcd_cdev\n", __func__);
return -1;
}
ret = alloc_chrdev_region(&lcd_cdev->devno, 0, 1, LCD_CDEV_NAME);
if (ret < 0) {
LCDERR("%s: failed to alloc devno\n", __func__);
kfree(lcd_cdev);
lcd_cdev = NULL;
return -1;
}
cdev_init(&lcd_cdev->cdev, &lcd_fops);
lcd_cdev->cdev.owner = THIS_MODULE;
ret = cdev_add(&lcd_cdev->cdev, lcd_cdev->devno, 1);
if (ret) {
LCDERR("%s: failed to add cdev\n", __func__);
unregister_chrdev_region(lcd_cdev->devno, 1);
kfree(lcd_cdev);
lcd_cdev = NULL;
return -1;
}
lcd_cdev->dev = device_create(lcd_driver->lcd_debug_class, NULL,
lcd_cdev->devno, NULL, LCD_CDEV_NAME);
if (IS_ERR(lcd_cdev->dev)) {
LCDERR("%s: failed to add device\n", __func__);
ret = PTR_ERR(lcd_cdev->dev);
cdev_del(&lcd_cdev->cdev);
unregister_chrdev_region(lcd_cdev->devno, 1);
kfree(lcd_cdev);
lcd_cdev = NULL;
return -1;
}
LCDPR("%s OK\n", __func__);
return 0;
}
static void lcd_fops_remove(void)
{
cdev_del(&lcd_cdev->cdev);
unregister_chrdev_region(lcd_cdev->devno, 1);
kfree(lcd_cdev);
lcd_cdev = NULL;
}
/* ************************************************************* */
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;
#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)
{
int ret;
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_tv_probe(dev);
break;
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
case LCD_MODE_TABLET:
lcd_tablet_probe(dev);
break;
#endif
default:
LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode);
break;
}
lcd_class_creat();
lcd_fops_create();
ret = aml_lcd_notifier_register(&lcd_interface_nb);
if (ret)
LCDERR("register aml_bl_select_notifier failed\n");
ret = aml_lcd_notifier_register(&lcd_bl_select_nb);
if (ret)
LCDERR("register aml_bl_select_notifier failed\n");
ret = aml_lcd_notifier_register(&lcd_power_nb);
if (ret)
LCDPR("register lcd_power_notifier failed\n");
/* add notifier for video sync_duration info refresh */
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
&lcd_driver->lcd_info->mode);
return 0;
}
static int lcd_mode_remove(struct device *dev)
{
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_tv_remove(dev);
break;
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
case LCD_MODE_TABLET:
lcd_tablet_remove(dev);
break;
#endif
default:
LCDPR("invalid lcd mode\n");
break;
}
return 0;
}
static void lcd_config_probe_delayed(struct work_struct *work)
{
int key_init_flag = 0;
int i = 0;
int ret;
if (lcd_driver->lcd_key_valid) {
key_init_flag = key_unify_get_init_flag();
while (key_init_flag == 0) {
if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT)
break;
msleep(20);
key_init_flag = key_unify_get_init_flag();
}
LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i);
}
ret = lcd_mode_probe(lcd_driver->dev);
if (ret) {
kfree(lcd_driver);
lcd_driver = NULL;
LCDERR("probe exit\n");
}
}
static void lcd_config_default(void)
{
struct lcd_config_s *pconf;
pconf = lcd_driver->lcd_config;
pconf->lcd_basic.h_active = lcd_vcbus_read(ENCL_VIDEO_HAVON_END)
- lcd_vcbus_read(ENCL_VIDEO_HAVON_BEGIN) + 1;
pconf->lcd_basic.v_active = lcd_vcbus_read(ENCL_VIDEO_VAVON_ELINE)
- lcd_vcbus_read(ENCL_VIDEO_VAVON_BLINE) + 1;
if (lcd_vcbus_read(ENCL_VIDEO_EN)) {
lcd_driver->lcd_status = 1;
lcd_resume_flag = 1;
} else {
lcd_driver->lcd_status = 0;
lcd_resume_flag = 0;
}
LCDPR("status: %d\n", lcd_driver->lcd_status);
}
static int lcd_config_probe(void)
{
const char *str;
unsigned int val;
int ret = 0;
if (lcd_driver->dev->of_node == NULL) {
LCDERR("dev of_node is null\n");
lcd_driver->lcd_mode = LCD_MODE_MAX;
return -1;
}
/* lcd driver assign */
ret = of_property_read_string(lcd_driver->dev->of_node, "mode", &str);
if (ret) {
str = "none";
LCDERR("failed to get mode\n");
return -1;
}
lcd_driver->lcd_mode = lcd_mode_str_to_mode(str);
ret = of_property_read_u32(lcd_driver->dev->of_node,
"fr_auto_policy", &val);
if (ret) {
if (lcd_debug_print_flag)
LCDPR("failed to get fr_auto_policy\n");
lcd_driver->fr_auto_policy = 0;
} else {
lcd_driver->fr_auto_policy = (unsigned char)val;
}
ret = of_property_read_u32(lcd_driver->dev->of_node, "key_valid", &val);
if (ret) {
if (lcd_debug_print_flag)
LCDPR("failed to get key_valid\n");
lcd_driver->lcd_key_valid = 0;
} else {
lcd_driver->lcd_key_valid = (unsigned char)val;
}
LCDPR("detect mode: %s, fr_auto_policy: %d, key_valid: %d\n",
str, lcd_driver->fr_auto_policy, lcd_driver->lcd_key_valid);
lcd_clktree_probe();
lcd_driver->lcd_info = &lcd_vinfo;
lcd_driver->lcd_config = &lcd_config_dft;
lcd_driver->lcd_config->pinmux_flag = 0;
lcd_driver->lcd_test_flag = 0;
lcd_driver->power_ctrl = lcd_power_ctrl;
lcd_driver->module_reset = lcd_module_reset;
lcd_driver->power_tiny_ctrl = lcd_power_tiny_ctrl;
lcd_driver->module_tiny_reset = lcd_module_tiny_reset;
lcd_config_default();
lcd_init_vout();
if (lcd_driver->lcd_key_valid) {
if (lcd_driver->workqueue) {
queue_delayed_work(lcd_driver->workqueue,
&lcd_driver->lcd_probe_delayed_work,
msecs_to_jiffies(2000));
} else {
LCDPR("Warning: no lcd_probe_delayed workqueue\n");
ret = lcd_mode_probe(lcd_driver->dev);
if (ret) {
kfree(lcd_driver);
lcd_driver = NULL;
LCDERR("probe exit\n");
}
}
} else {
ret = lcd_mode_probe(lcd_driver->dev);
if (ret) {
kfree(lcd_driver);
lcd_driver = NULL;
LCDERR("probe exit\n");
}
}
return 0;
}
static void lcd_resume_work(struct work_struct *p_work)
{
mutex_lock(&lcd_power_mutex);
lcd_resume_flag = 1;
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL);
LCDPR("%s finished\n", __func__);
mutex_unlock(&lcd_power_mutex);
}
static int lcd_probe(struct platform_device *pdev)
{
int ret = 0;
#ifdef LCD_DEBUG_INFO
lcd_debug_print_flag = 1;
#else
lcd_debug_print_flag = 0;
#endif
lcd_driver = kmalloc(sizeof(struct aml_lcd_drv_s), GFP_KERNEL);
if (!lcd_driver) {
LCDERR("%s: lcd driver no enough memory\n", __func__);
return -ENOMEM;
}
lcd_driver->dev = &pdev->dev;
mutex_init(&lcd_vout_mutex);
mutex_init(&lcd_power_mutex);
lcd_vout_serve_bypass = 0;
/* init workqueue */
INIT_DELAYED_WORK(&lcd_driver->lcd_probe_delayed_work,
lcd_config_probe_delayed);
lcd_driver->workqueue = create_singlethread_workqueue("lcd_work_queue");
if (lcd_driver->workqueue == NULL)
LCDERR("can't create lcd workqueue\n");
INIT_WORK(&(lcd_driver->lcd_resume_work), lcd_resume_work);
lcd_chip_detect();
lcd_ioremap();
lcd_clk_config_probe();
ret = lcd_config_probe();
LCDPR("%s %s\n", __func__, (ret ? "failed" : "ok"));
return 0;
}
static int lcd_remove(struct platform_device *pdev)
{
int ret;
ret = cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work);
if (lcd_driver->workqueue)
destroy_workqueue(lcd_driver->workqueue);
if (lcd_driver) {
aml_lcd_notifier_unregister(&lcd_power_nb);
aml_lcd_notifier_unregister(&lcd_bl_select_nb);
aml_lcd_notifier_unregister(&lcd_interface_nb);
lcd_fops_remove();
lcd_class_remove();
if (!IS_ERR(lcd_driver->vencl_top))
devm_clk_put(lcd_driver->dev, lcd_driver->vencl_top);
if (!IS_ERR(lcd_driver->vencl_int))
devm_clk_put(lcd_driver->dev, lcd_driver->vencl_int);
lcd_mode_remove(lcd_driver->dev);
kfree(lcd_driver);
lcd_driver = NULL;
}
LCDPR("%s\n", __func__);
return 0;
}
static int lcd_resume(struct platform_device *pdev)
{
queue_work(lcd_driver->workqueue, &(lcd_driver->lcd_resume_work));
return 0;
}
static int lcd_suspend(struct platform_device *pdev, pm_message_t state)
{
mutex_lock(&lcd_power_mutex);
if (lcd_driver->lcd_status) {
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
lcd_resume_flag = 0;
LCDPR("%s finished\n", __func__);
}
mutex_unlock(&lcd_power_mutex);
return 0;
}
static void lcd_shutdown(struct platform_device *pdev)
{
if (lcd_debug_print_flag)
LCDPR("%s\n", __func__);
if (lcd_driver->lcd_status)
aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL);
}
#ifdef CONFIG_OF
static const struct of_device_id lcd_dt_match[] = {
{
.compatible = "amlogic, lcd",
},
{},
};
#endif
static struct platform_driver lcd_platform_driver = {
.probe = lcd_probe,
.remove = lcd_remove,
.suspend = lcd_suspend,
.resume = lcd_resume,
.shutdown = lcd_shutdown,
.driver = {
.name = "mesonlcd",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = lcd_dt_match,
#endif
},
};
static int __init lcd_init(void)
{
if (platform_driver_register(&lcd_platform_driver)) {
LCDERR("failed to register lcd driver module\n");
return -ENODEV;
}
return 0;
}
static void __exit lcd_exit(void)
{
platform_driver_unregister(&lcd_platform_driver);
}
subsys_initcall(lcd_init);
module_exit(lcd_exit);
static int __init lcd_panel_type_para_setup(char *str)
{
if (str != NULL)
sprintf(lcd_propname, "%s", str);
LCDPR("panel_type: %s\n", lcd_propname);
return 0;
}
__setup("panel_type=", lcd_panel_type_para_setup);
MODULE_DESCRIPTION("Meson LCD Panel Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Amlogic, Inc.");

View File

@@ -354,6 +354,7 @@ static const unsigned int tcon_stv1_pins[] = { PIN(GPIODV_24, EE_OFF) };
static const unsigned int tcon_sth1_pins[] = { PIN(GPIODV_25, EE_OFF) };
static const unsigned int tcon_cph_pins[] = { PIN(GPIODV_26, EE_OFF) };
static const unsigned int tcon_vcom_pins[] = { PIN(GPIODV_27, EE_OFF) };
static const unsigned int tcon_oeh_pins[] = { PIN(GPIODV_27, EE_OFF) };
/*i2c_a*/
static const unsigned int i2c_sda_a_pins[] = { PIN(GPIODV_24, EE_OFF) };
@@ -612,19 +613,23 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = {
GROUP(tsout_clk, 1, 27), /*dv15*/
GROUP(tsout_d0, 1, 26), /*dv16*/
GROUP(tsout_d1_7, 1, 25), /*dv17-23*/
GROUP(lcd_r0_1, 3, 10), /*dv0-1*/
GROUP(lcd_r2_7, 3, 9), /*dv2-7*/
GROUP(lcd_g0_1, 3, 8), /*dv8-9*/
GROUP(lcd_g2_7, 3, 7), /*dv10-15*/
GROUP(lcd_b0_1, 3, 6), /*dv16-17*/
GROUP(lcd_b2_7, 3, 5), /*dv18-23*/
GROUP(lcd_r0_1, 3, 10), /*dv0-1*/
GROUP(lcd_r2_7, 3, 9), /*dv2-7*/
GROUP(lcd_g0_1, 3, 8), /*dv8-9*/
GROUP(lcd_g2_7, 3, 7), /*dv10-15*/
GROUP(lcd_b0_1, 3, 6), /*dv16-17*/
GROUP(lcd_b2_7, 3, 5), /*dv18-23*/
GROUP(lcd_vs, 3, 4), /*dv24*/
GROUP(lcd_hs, 3, 3), /*dv25*/
GROUP(tcon_stv1, 1, 22), /*dv24*/
GROUP(tcon_sth1, 1, 21), /*dv25*/
GROUP(tcon_cph, 1, 20), /*dv26*/
GROUP(tcon_vcom, 1, 19), /*dv27*/
GROUP(tcon_oeh, 1, 18), /*dv27*/
GROUP(uart_tx_b, 2, 16),
GROUP(uart_rx_b, 2, 15),
GROUP(uart_cts_b, 2, 14),
GROUP(uart_rts_b, 2, 13),
GROUP(lcd_vs, 3, 4), /*dv24*/
GROUP(lcd_hs, 3, 3), /*dv25*/
GROUP(tcon_stv1, 1, 22),
GROUP(i2c_sda_a, 1, 15), /*dv24*/
GROUP(i2c_scl_a, 1, 14), /*dv25*/
GROUP(dmic_in_dv24, 2, 7), /*dv24*/
@@ -969,11 +974,12 @@ static const char * const tsout_a_groups[] = {
"tsout_d0", "tsout_d1_7",
};
static const char * const lcd_groups[] = {
static const char * const lcd_ttl_groups[] = {
"lcd_r0_1", "lcd_r2_7",
"lcd_g0_1", "lcd_g2_7",
"lcd_b0_1", "lcd_b2_7",
"lcd_vs", "lcd_hs",
"tcon_stv1", "tcon_sth1",
"tcon_cph", "tcon_oeh",
};
static const char *const nor_groups[] = {
@@ -1022,7 +1028,7 @@ static struct meson_pmx_func meson_gxl_periphs_functions[] = {
FUNCTION(tsin_a),
FUNCTION(tsin_b),
FUNCTION(tsout_a),
FUNCTION(lcd),
FUNCTION(lcd_ttl),
FUNCTION(nor),
FUNCTION(dvp),
FUNCTION(dmic),

View File

@@ -0,0 +1,175 @@
/*
* include/linux/amlogic/media/vout/lcd/aml_bl.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 __INC_AML_BL_H
#define __INC_AML_BL_H
#include <linux/workqueue.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/pinctrl/consumer.h>
#define BLPR(fmt, args...) pr_info("bl: "fmt"", ## args)
#define BLERR(fmt, args...) pr_err("bl error: "fmt"", ## args)
#define AML_BL_NAME "aml-bl"
#define BL_LEVEL_MAX 255
#define BL_LEVEL_MIN 10
#define BL_LEVEL_OFF 1
#define BL_LEVEL_MID 128
#define BL_LEVEL_MID_MAPPED BL_LEVEL_MID
#define BL_LEVEL_DEFAULT BL_LEVEL_MID
#define XTAL_FREQ_HZ (24*1000*1000) /* unit: Hz */
#define XTAL_HALF_FREQ_HZ (24*1000*500) /* 24M/2 in HZ */
#define BL_FREQ_DEFAULT 1000 /* unit: HZ */
#define BL_FREQ_VS_DEFAULT 2 /* multiple 2 of vfreq */
enum bl_chip_type_e {
BL_CHIP_GXTVBB,
BL_CHIP_GXL,
BL_CHIP_GXM,
BL_CHIP_TXL,
BL_CHIP_TXLX,
BL_CHIP_AXG,
BL_CHIP_MAX,
};
/* for lcd backlight power */
enum bl_ctrl_method_e {
BL_CTRL_GPIO = 0,
BL_CTRL_PWM,
BL_CTRL_PWM_COMBO,
BL_CTRL_LOCAL_DIMING,
BL_CTRL_EXTERN,
BL_CTRL_MAX,
};
enum bl_pwm_method_e {
BL_PWM_NEGATIVE = 0,
BL_PWM_POSITIVE,
BL_PWM_METHOD_MAX,
};
enum bl_pwm_port_e {
BL_PWM_A = 0,
BL_PWM_B,
BL_PWM_C,
BL_PWM_D,
BL_PWM_E,
BL_PWM_F,
BL_PWM_VS,
BL_PWM_MAX,
};
enum bl_off_policy_e {
BL_OFF_POLICY_NONE = 0,
BL_OFF_POLICY_ALWAYS,
BL_OFF_POLICY_ONCE,
BL_OFF_POLICY_MAX,
};
#define BL_GPIO_OUTPUT_LOW 0
#define BL_GPIO_OUTPUT_HIGH 1
#define BL_GPIO_INPUT 2
#define BL_GPIO_MAX 0xff
#define BL_GPIO_NUM_MAX 5
struct bl_gpio_s {
char name[15];
struct gpio_desc *gpio;
int flag;
};
struct bl_pwm_config_s {
unsigned int index;
struct pwm_device *bl_pwm_ch;
struct aml_pwm_chip *bl_pwm_chip;
enum bl_pwm_method_e pwm_method;
enum bl_pwm_port_e pwm_port;
unsigned int level_max;
unsigned int level_min;
unsigned int pwm_freq; /* pwm_vs: 1~4(vfreq), pwm: freq(unit: Hz) */
unsigned int pwm_duty; /* unit: % */
unsigned int pwm_duty_max; /* unit: % */
unsigned int pwm_duty_min; /* unit: % */
unsigned int pwm_cnt; /* internal used for pwm control */
unsigned int pwm_pre_div; /* internal used for pwm control */
unsigned int pwm_max; /* internal used for pwm control */
unsigned int pwm_min; /* internal used for pwm control */
unsigned int pwm_level; /* internal used for pwm control */
};
struct bl_config_s {
char name[30];
unsigned int level_default;
unsigned int level_min;
unsigned int level_max;
unsigned int level_mid;
unsigned int level_mid_mapping;
enum bl_ctrl_method_e method;
unsigned int en_gpio;
unsigned int en_gpio_on;
unsigned int en_gpio_off;
unsigned int power_on_delay;
unsigned int power_off_delay;
unsigned int dim_max;
unsigned int dim_min;
struct bl_pwm_config_s *bl_pwm;
struct bl_pwm_config_s *bl_pwm_combo0;
struct bl_pwm_config_s *bl_pwm_combo1;
unsigned int pwm_on_delay;
unsigned int pwm_off_delay;
struct bl_gpio_s bl_gpio[BL_GPIO_NUM_MAX];
struct pinctrl *pin;
unsigned int pinmux_flag;
};
#define BL_INDEX_DEFAULT 0
/* backlight_properties: state */
/* Flags used to signal drivers of state changes */
/* Upper 4 bits in bl props are reserved for driver internal use */
#define BL_STATE_LCD_ON (1 << 3)
#define BL_STATE_BL_POWER_ON (1 << 1)
#define BL_STATE_BL_ON (1 << 0)
struct aml_bl_drv_s {
unsigned int index;
unsigned int level;
unsigned int state;
enum bl_chip_type_e chip_type;
struct device *dev;
struct bl_config_s *bconf;
struct backlight_device *bldev;
struct workqueue_struct *workqueue;
struct delayed_work bl_delayed_work;
};
extern enum bl_chip_type_e aml_bl_check_chip(void);
extern struct aml_bl_drv_s *aml_bl_get_driver(void);
extern void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm);
extern enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str);
#define BL_GPIO_OUTPUT_LOW 0
#define BL_GPIO_OUTPUT_HIGH 1
#define BL_GPIO_INPUT 2
#endif

View File

@@ -0,0 +1,76 @@
/*
* include/linux/amlogic/media/vout/lcd/aml_bl_extern.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 __AMLOGIC_BL_EXTERN_H_
#define __AMLOGIC_BL_EXTERN_H_
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/pinctrl/consumer.h>
enum bl_extern_type_e {
BL_EXTERN_I2C = 0,
BL_EXTERN_SPI,
BL_EXTERN_OTHER,
BL_EXTERN_MAX,
};
struct bl_extern_config_s {
const char *name;
enum bl_extern_type_e type;
struct gpio_desc *gpio;
unsigned char gpio_on;
unsigned char gpio_off;
int i2c_addr;
int i2c_bus;
struct gpio_desc *spi_cs;
struct gpio_desc *spi_clk;
struct gpio_desc *spi_data;
unsigned int dim_min;
unsigned int dim_max;
/* unsigned int level_min; */
/* unsigned int level_max; */
};
/*******global API******/
struct aml_bl_extern_driver_t {
const char *name;
enum bl_extern_type_e type;
int (*power_on)(void);
int (*power_off)(void);
int (*set_level)(unsigned int level);
};
#define BL_EXTERN_DRIVER "bl_extern"
#define bl_extern_gpio_free(gpio) gpiod_free(gpio, BL_EXTERN_DRIVER)
#define bl_extern_gpio_input(gpio) gpiod_direction_input(gpio)
#define bl_extern_gpio_output(gpio, val) gpiod_direction_output(gpio, val)
#define bl_extern_gpio_get_value(gpio) gpiod_get_value(gpio)
#define bl_extern_gpio_set_value(gpio, val) gpiod_set_value(gpio, val)
extern struct aml_bl_extern_driver_t *aml_bl_extern_get_driver(void);
extern int bl_extern_driver_check(void);
extern int get_bl_extern_dt_data(struct device dev,
struct bl_extern_config_s *pdata);
extern void get_bl_ext_level(struct bl_extern_config_s *bl_ext_cfg);
#endif

View File

@@ -0,0 +1,88 @@
/*
* include/linux/amlogic/media/vout/lcd/aml_ldim.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 _INC_AML_LDIM_H_
#define _INC_AML_LDIM_H_
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/amlogic/media/vout/aml_bl.h>
#include <linux/spi/spi.h>
enum ldim_dev_type_e {
LDIM_DEV_TYPE_NORMAL = 0,
LDIM_DEV_TYPE_SPI,
LDIM_DEV_TYPE_I2C,
LDIM_DEV_TYPE_MAX,
};
#define LDIM_SPI_INIT_ON_SIZE 300
#define LDIM_SPI_INIT_OFF_SIZE 20
struct ldim_dev_config_s {
char name[20];
char pinmux_name[20];
unsigned char type;
int cs_hold_delay;
int cs_clk_delay;
int en_gpio;
int en_gpio_on;
int en_gpio_off;
int lamp_err_gpio;
unsigned char fault_check;
unsigned char write_check;
unsigned int dim_min;
unsigned int dim_max;
unsigned char cmd_size;
unsigned char *init_on;
unsigned char *init_off;
struct bl_pwm_config_s pwm_config;
};
/*******global API******/
struct aml_ldim_driver_s {
int valid_flag;
int dev_index;
int static_pic_flag;
struct ldim_dev_config_s *ldev_conf;
unsigned short *ldim_matrix_buf;
int (*init)(void);
int (*power_on)(void);
int (*power_off)(void);
int (*set_level)(unsigned int level);
int (*pinmux_ctrl)(char *pin_str, int status);
int (*pwm_vs_update)(void);
int (*device_power_on)(void);
int (*device_power_off)(void);
int (*device_bri_update)(unsigned short *buf, unsigned char len);
int (*device_bri_check)(void);
void (*config_print)(void);
void (*test_ctrl)(int flag);
struct pinctrl *pin;
struct device *dev;
struct spi_device *spi;
struct spi_board_info *spi_dev;
};
extern struct aml_ldim_driver_s *aml_ldim_get_driver(void);
extern int aml_ldim_probe(struct platform_device *pdev);
extern int aml_ldim_remove(void);
#endif

View File

@@ -0,0 +1,87 @@
/*
* include/linux/amlogic/media/vout/lcd/lcd_extern.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 _INC_AML_LCD_EXTERN_H_
#define _INC_AML_LCD_EXTERN_H_
enum lcd_extern_type_e {
LCD_EXTERN_I2C = 0,
LCD_EXTERN_SPI,
LCD_EXTERN_MIPI,
LCD_EXTERN_MAX,
};
enum lcd_extern_i2c_bus_e {
LCD_EXTERN_I2C_BUS_AO = 0,
LCD_EXTERN_I2C_BUS_A,
LCD_EXTERN_I2C_BUS_B,
LCD_EXTERN_I2C_BUS_C,
LCD_EXTERN_I2C_BUS_D,
LCD_EXTERN_I2C_BUS_MAX,
};
#define LCD_EXTERN_I2C_BUS_INVALID 0xff
#define LCD_EXTERN_SPI_CLK_FREQ_DFT 10000 /* default 10k */
#define LCD_EXTERN_INIT_TABLE_MAX 500
#define LCD_EXTERN_INIT_CMD 0x00
#define LCD_EXTERN_INIT_CMD2 0x01 /* only for special i2c device */
#define LCD_EXTERN_INIT_GPIO 0x10
#define LCD_EXTERN_INIT_NONE 0xf0
#define LCD_EXTERN_INIT_END 0xff
#define LCD_EXTERN_DYNAMIC_LEN 0xff
#define LCD_EXTERN_GPIO_NUM_MAX 6
#define LCD_EXTERN_INDEX_INVALID 0xff
#define LCD_EXTERN_NAME_LEN_MAX 30
struct lcd_extern_config_s {
unsigned char index;
char name[LCD_EXTERN_NAME_LEN_MAX];
enum lcd_extern_type_e type;
unsigned char status;
unsigned char i2c_addr;
unsigned char i2c_addr2;
unsigned char i2c_bus;
unsigned char spi_gpio_cs;
unsigned char spi_gpio_clk;
unsigned char spi_gpio_data;
unsigned int spi_clk_freq;
unsigned char spi_clk_pol;
unsigned char cmd_size;
unsigned char table_init_loaded; /* internal use */
unsigned char *table_init_on;
unsigned char *table_init_off;
};
/* global API */
#define LCD_EXT_DRIVER_MAX 10
struct aml_lcd_extern_driver_s {
struct lcd_extern_config_s config;
int (*reg_read)(unsigned char reg, unsigned char *buf);
int (*reg_write)(unsigned char reg, unsigned char value);
int (*power_on)(void);
int (*power_off)(void);
};
extern struct aml_lcd_extern_driver_s *aml_lcd_extern_get_driver(int index);
#endif

View File

@@ -0,0 +1,52 @@
/*
* include/linux/amlogic/media/vout/lcd/lcd_mipi.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 _INC_LCD_MIPI_H
#define _INC_LCD_MIPI_H
/* **********************************
* mipi-dsi read/write api
*/
/* mipi command(payload) */
/* format: data_type, num, data.... */
/* special: data_type=0xff,
* num<0xff means delay ms, num=0xff means ending.
*/
/* *************************************************************
* Function: dsi_write_cmd
* Supported Data Type: DT_GEN_SHORT_WR_0, DT_GEN_SHORT_WR_1, DT_GEN_SHORT_WR_2,
DT_DCS_SHORT_WR_0, DT_DCS_SHORT_WR_1,
DT_GEN_LONG_WR, DT_DCS_LONG_WR,
DT_SET_MAX_RET_PKT_SIZE
DT_GEN_RD_0, DT_GEN_RD_1, DT_GEN_RD_2,
DT_DCS_RD_0
* Return: command number
*/
extern int dsi_write_cmd(unsigned char *payload);
/* *************************************************************
* Function: dsi_read_single
* Supported Data Type: DT_GEN_RD_0, DT_GEN_RD_1, DT_GEN_RD_2,
DT_DCS_RD_0
* Return: data count
0 for not support
*/
extern int dsi_read_single(unsigned char *payload, unsigned char *rd_data,
unsigned int rd_byte_len);
#endif

View File

@@ -0,0 +1,63 @@
/*
* include/linux/amlogic/media/vout/lcd/lcd_notify.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 _INC_LCD_NOTIFY_H_
#define _INC_LCD_NOTIFY_H_
#include <linux/notifier.h>
#define LCD_PRIORITY_INIT_CONFIG 4
#define LCD_PRIORITY_INIT_VOUT 3
#define LCD_PRIORITY_BLACK_SCREEN 3
#define LCD_PRIORITY_POWER_BL_OFF 2
#define LCD_PRIORITY_POWER_LCD 1
#define LCD_PRIORITY_POWER_BL_ON 0
#define LCD_EVENT_BL_ON (1 << 0)
#define LCD_EVENT_LCD_ON (1 << 1)
#define LCD_EVENT_IF_ON (1 << 2)
#define LCD_EVENT_POWER_ON (LCD_EVENT_BL_ON | LCD_EVENT_LCD_ON)
#define LCD_EVENT_IF_POWER_ON (LCD_EVENT_BL_ON | LCD_EVENT_IF_ON)
#define LCD_EVENT_BLACK_SCREEN (1 << 3)
#define LCD_EVENT_BL_OFF (1 << 4)
#define LCD_EVENT_LCD_OFF (1 << 5)
#define LCD_EVENT_IF_OFF (1 << 6)
#define LCD_EVENT_POWER_OFF (LCD_EVENT_BL_OFF | LCD_EVENT_LCD_OFF |\
LCD_EVENT_BLACK_SCREEN)
#define LCD_EVENT_IF_POWER_OFF (LCD_EVENT_BL_OFF | LCD_EVENT_IF_OFF |\
LCD_EVENT_BLACK_SCREEN)
/* lcd backlight index select */
#define LCD_EVENT_BACKLIGHT_SEL (1 << 8)
/* lcd backlight pwm_vs vfreq change occurred */
#define LCD_EVENT_BACKLIGHT_UPDATE (1 << 9)
#define LCD_EVENT_GAMMA_UPDATE (1 << 10)
/* lcd frame rate change occurred */
#define LCD_EVENT_FRAME_RATE_ADJUST (1 << 12)
/* lcd config change occurred */
#define LCD_EVENT_CONFIG_UPDATE (1 << 13)
/* lcd bist pattern test occurred */
#define LCD_EVENT_TEST_PATTERN (1 << 14)
extern int aml_lcd_notifier_register(struct notifier_block *nb);
extern int aml_lcd_notifier_unregister(struct notifier_block *nb);
extern int aml_lcd_notifier_call_chain(unsigned long event, void *v);
#endif /* _INC_LCD_NOTIFY_H_ */

View File

@@ -0,0 +1,185 @@
/*
* include/linux/amlogic/media/vout/lcd/lcd_unifykey.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 _INC_AML_LCD_UNIFYKEY_H__
#define _INC_AML_LCD_UNIFYKEY_H__
#define LCD_UNIFYKEY_WAIT_TIMEOUT 300
/* declare external unifykey function */
extern int key_unify_read(char *keyname, unsigned char *keydata,
unsigned int datalen, unsigned int *reallen);
extern int key_unify_size(char *keyname, unsigned int *reallen);
extern int key_unify_query(char *keyname, unsigned int *keystate,
unsigned int *keypermit);
extern int key_unify_get_init_flag(void);
#define LCD_UKEY_RETRY_CNT_MAX 5
/*
* lcd unifykey data struct: little-endian, for example:
* 4byte: d[0]=0x01, d[1]=0x02, d[2] = 0x03, d[3]= 0x04,
* data = 0x04030201
*/
/* define lcd unifykey length */
#define LCD_UKEY_HEAD_SIZE 10
#define LCD_UKEY_HEAD_CRC32 4
#define LCD_UKEY_HEAD_DATA_LEN 2
#define LCD_UKEY_HEAD_VERSION 2
#define LCD_UKEY_HEAD_RESERVED 2
struct aml_lcd_unifykey_header_s {
unsigned int crc32;
unsigned short data_len;
unsigned short version;
unsigned short reserved;
};
/* lcd */
#define LCD_UKEY_LCD_SIZE 265
/* header (10Byte) */
/* LCD_UKEY_HEAD_SIZE */
/* basic (36Byte) */
#define LCD_UKEY_MODEL_NAME 30
#define LCD_UKEY_INTERFACE 1
#define LCD_UKEY_LCD_BITS 1
#define LCD_UKEY_SCREEN_WIDTH 2
#define LCD_UKEY_SCREEN_HEIGHT 2
/* timing (18Byte) */
#define LCD_UKEY_H_ACTIVE 2
#define LCD_UKEY_V_ACTIVE 2
#define LCD_UKEY_H_PERIOD 2
#define LCD_UKEY_V_PERIOD 2
#define LCD_UKEY_HS_WIDTH 2
#define LCD_UKEY_HS_BP 2
#define LCD_UKEY_HS_POL 1
#define LCD_UKEY_VS_WIDTH 2
#define LCD_UKEY_VS_BP 2
#define LCD_UKEY_VS_POL 1
/* customer (31Byte) */
#define LCD_UKEY_FR_ADJ_TYPE 1
#define LCD_UKEY_SS_LEVEL 1
#define LCD_UKEY_CLK_AUTO_GEN 1
#define LCD_UKEY_PCLK 4
#define LCD_UKEY_H_PERIOD_MIN 2
#define LCD_UKEY_H_PERIOD_MAX 2
#define LCD_UKEY_V_PERIOD_MIN 2
#define LCD_UKEY_V_PERIOD_MAX 2
#define LCD_UKEY_PCLK_MIN 4
#define LCD_UKEY_PCLK_MAX 4
#define LCD_UKEY_CUST_VAL_8 4
#define LCD_UKEY_CUST_VAL_9 4
/* interface (20Byte) */
#define LCD_UKEY_IF_ATTR_0 2
#define LCD_UKEY_IF_ATTR_1 2
#define LCD_UKEY_IF_ATTR_2 2
#define LCD_UKEY_IF_ATTR_3 2
#define LCD_UKEY_IF_ATTR_4 2
#define LCD_UKEY_IF_ATTR_5 2
#define LCD_UKEY_IF_ATTR_6 2
#define LCD_UKEY_IF_ATTR_7 2
#define LCD_UKEY_IF_ATTR_8 2
#define LCD_UKEY_IF_ATTR_9 2
/* power (5Byte * n) */
#define LCD_UKEY_PWR_TYPE 1
#define LCD_UKEY_PWR_INDEX 1
#define LCD_UKEY_PWR_VAL 1
#define LCD_UKEY_PWR_DELAY 2
/* lcd extern */
#define LCD_UKEY_LCD_EXT_SIZE 550
/* header (10Byte) */
/* LCD_UKEY_HEAD_SIZE */
/* basic (33Byte) */
#define LCD_UKEY_EXT_NAME 30
#define LCD_UKEY_EXT_INDEX 1
#define LCD_UKEY_EXT_TYPE 1
#define LCD_UKEY_EXT_STATUS 1
/* type (10Byte) */
#define LCD_UKEY_EXT_TYPE_VAL_0 1
#define LCD_UKEY_EXT_TYPE_VAL_1 1
#define LCD_UKEY_EXT_TYPE_VAL_2 1
#define LCD_UKEY_EXT_TYPE_VAL_3 1
#define LCD_UKEY_EXT_TYPE_VAL_4 1
#define LCD_UKEY_EXT_TYPE_VAL_5 1
#define LCD_UKEY_EXT_TYPE_VAL_6 1
#define LCD_UKEY_EXT_TYPE_VAL_7 1
#define LCD_UKEY_EXT_TYPE_VAL_8 1
#define LCD_UKEY_EXT_TYPE_VAL_9 1
/* init (cmd_size) */
#define LCD_UKEY_EXT_INIT_TYPE 1
/*#define LCD_UKEY_EXT_INIT_VAL 1 //not defined */
#define LCD_UKEY_EXT_INIT_DELAY 1
/* backlight */
#define LCD_UKEY_BL_SIZE 92
/* header (10Byte) */
/* LCD_UKEY_HEAD_SIZE */
/* basic (30Byte) */
#define LCD_UKEY_BL_NAME 30
/* level (12Byte) */
#define LCD_UKEY_BL_LEVEL_UBOOT 2
#define LCD_UKEY_BL_LEVEL_KERNEL 2
#define LCD_UKEY_BL_LEVEL_MAX 2
#define LCD_UKEY_BL_LEVEL_MIN 2
#define LCD_UKEY_BL_LEVEL_MID 2
#define LCD_UKEY_BL_LEVEL_MID_MAP 2
/* method (8Byte) */
#define LCD_UKEY_BL_METHOD 1
#define LCD_UKEY_BL_EN_GPIO 1
#define LCD_UKEY_BL_EN_GPIO_ON 1
#define LCD_UKEY_BL_EN_GPIO_OFF 1
#define LCD_UKEY_BL_ON_DELAY 2
#define LCD_UKEY_BL_OFF_DELAY 2
/* pwm (32Byte) */
#define LCD_UKEY_BL_PWM_ON_DELAY 2
#define LCD_UKEY_BL_PWM_OFF_DELAY 2
#define LCD_UKEY_BL_PWM_METHOD 1
#define LCD_UKEY_BL_PWM_PORT 1
#define LCD_UKEY_BL_PWM_FREQ 4
#define LCD_UKEY_BL_PWM_DUTY_MAX 1
#define LCD_UKEY_BL_PWM_DUTY_MIN 1
#define LCD_UKEY_BL_PWM_GPIO 1
#define LCD_UKEY_BL_PWM_GPIO_OFF 1
#define LCD_UKEY_BL_PWM2_METHOD 1
#define LCD_UKEY_BL_PWM2_PORT 1
#define LCD_UKEY_BL_PWM2_FREQ 4
#define LCD_UKEY_BL_PWM2_DUTY_MAX 1
#define LCD_UKEY_BL_PWM2_DUTY_MIN 1
#define LCD_UKEY_BL_PWM2_GPIO 1
#define LCD_UKEY_BL_PWM2_GPIO_OFF 1
#define LCD_UKEY_BL_PWM_LEVEL_MAX 2
#define LCD_UKEY_BL_PWM_LEVEL_MIN 2
#define LCD_UKEY_BL_PWM2_LEVEL_MAX 2
#define LCD_UKEY_BL_PWM2_LEVEL_MIN 2
/* API */
extern int lcd_unifykey_len_check(int key_len, int len);
extern int lcd_unifykey_check(char *key_name);
extern int lcd_unifykey_header_check(unsigned char *buf,
struct aml_lcd_unifykey_header_s *header);
extern int lcd_unifykey_get(char *key_name,
unsigned char *buf, int *len);
extern void lcd_unifykey_print(void);
#endif

View File

@@ -0,0 +1,403 @@
/*
* include/linux/amlogic/media/vout/lcd/lcd_vout.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 _INC_LCD_VOUT_H
#define _INC_LCD_VOUT_H
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/amlogic/media/vout/vout_notify.h>
/* debug print define */
/* #define LCD_DEBUG_INFO */
extern unsigned char lcd_debug_print_flag;
#define LCDPR(fmt, args...) pr_info("lcd: "fmt"", ## args)
#define LCDERR(fmt, args...) pr_err("lcd: error: "fmt"", ## args)
/* clk parameter bit define */
/* pll_ctrl, div_ctrl, clk_ctrl */
/* ******** pll_ctrl ******** */
#define PLL_CTRL_OD3 20 /* [21:20] */
#define PLL_CTRL_OD2 18 /* [19:18] */
#define PLL_CTRL_OD1 16 /* [17:16] */
#define PLL_CTRL_N 9 /* [13:9] */
#define PLL_CTRL_M 0 /* [8:0] */
/* ******** div_ctrl ******** */
#define DIV_CTRL_EDP_DIV1 24 /* [26:24] */
#define DIV_CTRL_EDP_DIV0 20 /* [23:20] */
#define DIV_CTRL_DIV_POST 12 /* [14:12] */
#define DIV_CTRL_DIV_PRE 8 /* [10:8] */
#define DIV_CTRL_DIV_SEL 8 /* [15:8] */
#define DIV_CTRL_XD 0 /* [7:0] */
/* ******** clk_ctrl ******** */
#define CLK_CTRL_LEVEL 12 /* [14:12] */
#define CLK_CTRL_FRAC 0 /* [11:0] */
/* VENC to TCON sync delay */
#define TTL_DELAY 13
/* ******** AXG ******** */
/* bit[15:11] */
#define BIT_PHY_LANE_AXG 11
#define PHY_LANE_WIDTH_AXG 5
/* MIPI-DSI */
#define DSI_LANE_0 (1 << 4)
#define DSI_LANE_1 (1 << 3)
#define DSI_LANE_CLK (1 << 2)
#define DSI_LANE_2 (1 << 1)
#define DSI_LANE_3 (1 << 0)
#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0)
#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1)
#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\
DSI_LANE_1 | DSI_LANE_2)
#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\
DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3)
/* global control define */
enum lcd_mode_e {
LCD_MODE_TV = 0,
LCD_MODE_TABLET,
LCD_MODE_MAX,
};
enum lcd_chip_e {
LCD_CHIP_GXTVBB = 0,
LCD_CHIP_GXL, /* 1 */
LCD_CHIP_GXM, /* 2 */
LCD_CHIP_TXL, /* 3 */
LCD_CHIP_TXLX, /* 4 */
LCD_CHIP_AXG, /* 5 */
LCD_CHIP_MAX,
};
enum lcd_type_e {
LCD_TTL = 0,
LCD_LVDS,
LCD_VBYONE,
LCD_MIPI,
LCD_TYPE_MAX,
};
#define MOD_LEN_MAX 30
struct lcd_basic_s {
char model_name[MOD_LEN_MAX];
enum lcd_type_e lcd_type;
unsigned short lcd_bits;
unsigned short h_active; /* Horizontal display area */
unsigned short v_active; /* Vertical display area */
unsigned short h_period; /* Horizontal total period time */
unsigned short v_period; /* Vertical total period time */
unsigned short h_period_min;
unsigned short h_period_max;
unsigned short v_period_min;
unsigned short v_period_max;
unsigned int lcd_clk_min;
unsigned int lcd_clk_max;
unsigned int screen_width; /* screen physical width(unit: mm) */
unsigned int screen_height; /* screen physical height(unit: mm) */
};
#define LCD_CLK_FRAC_UPDATE (1 << 0)
#define LCD_CLK_PLL_CHANGE (1 << 1)
struct lcd_timing_s {
unsigned char clk_auto; /* clk parameters auto generation */
unsigned int lcd_clk; /* pixel clock(unit: Hz) */
unsigned int lcd_clk_dft; /* internal used */
unsigned int h_period_dft; /* internal used */
unsigned int v_period_dft; /* internal used */
unsigned char clk_change; /* internal used */
unsigned int pll_ctrl; /* pll settings */
unsigned int div_ctrl; /* divider settings */
unsigned int clk_ctrl; /* clock settings */
unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */
unsigned char ss_level;
unsigned int sync_duration_num;
unsigned int sync_duration_den;
unsigned short video_on_pixel;
unsigned short video_on_line;
unsigned short hsync_width;
unsigned short hsync_bp;
unsigned short hsync_pol;
unsigned short vsync_width;
unsigned short vsync_bp;
unsigned short vsync_pol;
/* unsigned int vsync_h_phase; // [31]sign, [15:0]value */
unsigned int h_offset;
unsigned int v_offset;
unsigned short de_hs_addr;
unsigned short de_he_addr;
unsigned short de_vs_addr;
unsigned short de_ve_addr;
unsigned short hs_hs_addr;
unsigned short hs_he_addr;
unsigned short hs_vs_addr;
unsigned short hs_ve_addr;
unsigned short vs_hs_addr;
unsigned short vs_he_addr;
unsigned short vs_vs_addr;
unsigned short vs_ve_addr;
};
/* HDR info define */
struct lcd_hdr_info_s {
unsigned int hdr_support;
unsigned int features;
unsigned int primaries_r_x;
unsigned int primaries_r_y;
unsigned int primaries_g_x;
unsigned int primaries_g_y;
unsigned int primaries_b_x;
unsigned int primaries_b_y;
unsigned int white_point_x;
unsigned int white_point_y;
unsigned int luma_max;
unsigned int luma_min;
unsigned int luma_avg;
};
struct ttl_config_s {
unsigned int clk_pol;
unsigned int sync_valid; /* [1]DE, [0]hvsync */
unsigned int swap_ctrl; /* [1]rb swap, [0]bit swap */
};
#define LVDS_PHY_VSWING_DFT 3
#define LVDS_PHY_PREEM_DFT 0
#define LVDS_PHY_CLK_VSWING_DFT 0
#define LVDS_PHY_CLK_PREEM_DFT 0
struct lvds_config_s {
unsigned int lvds_vswing;
unsigned int lvds_repack;
unsigned int dual_port;
unsigned int pn_swap;
unsigned int port_swap;
unsigned int lane_reverse;
unsigned int port_sel;
unsigned int phy_vswing;
unsigned int phy_preem;
unsigned int phy_clk_vswing;
unsigned int phy_clk_preem;
};
#define VX1_PHY_VSWING_DFT 3
#define VX1_PHY_PREEM_DFT 0
struct vbyone_config_s {
unsigned int lane_count;
unsigned int region_num;
unsigned int byte_mode;
unsigned int color_fmt;
unsigned int phy_div;
unsigned int bit_rate;
unsigned int phy_vswing; /*[4]:ext_pullup, [3:0]vswing*/
unsigned int phy_preem;
unsigned int intr_en;
unsigned int vsync_intr_en;
};
/* mipi-dsi config */
/* Operation mode parameters */
#define OPERATION_VIDEO_MODE 0
#define OPERATION_COMMAND_MODE 1
#define SYNC_PULSE 0x0
#define SYNC_EVENT 0x1
#define BURST_MODE 0x2
/* command config */
#define DSI_CMD_INDEX 1 /* byte[1] */
#define DSI_INIT_ON_MAX 100
#define DSI_INIT_OFF_MAX 30
struct dsi_config_s {
unsigned char lane_num;
unsigned int bit_rate_max; /* MHz */
unsigned int bit_rate_min; /* MHz*/
unsigned int bit_rate; /* Hz */
unsigned int factor_numerator;
unsigned int factor_denominator; /* 100 */
unsigned char operation_mode_init; /* 0=video mode, 1=command mode */
unsigned char operation_mode_display; /* 0=video mode, 1=command mode */
unsigned char video_mode_type; /* 0=sync_pulse, 1=sync_event, 2=burst */
unsigned char clk_lp_continuous; /* 0=stop, 1=continue */
unsigned char phy_stop_wait; /* 0=auto, 1=standard, 2=slow */
unsigned int venc_data_width;
unsigned int dpi_data_format;
unsigned int venc_fmt;
unsigned char *dsi_init_on;
unsigned char *dsi_init_off;
unsigned char extern_init;
};
struct lcd_control_config_s {
struct ttl_config_s *ttl_config;
struct lvds_config_s *lvds_config;
struct vbyone_config_s *vbyone_config;
struct dsi_config_s *mipi_config;
};
/* power control define */
enum lcd_power_type_e {
LCD_POWER_TYPE_CPU = 0,
LCD_POWER_TYPE_PMU,
LCD_POWER_TYPE_SIGNAL,
LCD_POWER_TYPE_EXTERN,
LCD_POWER_TYPE_MAX,
};
enum lcd_pmu_gpio_e {
LCD_PMU_GPIO0 = 0,
LCD_PMU_GPIO1,
LCD_PMU_GPIO2,
LCD_PMU_GPIO3,
LCD_PMU_GPIO4,
LCD_PMU_GPIO_MAX,
};
#define LCD_GPIO_MAX 0xff
#define LCD_GPIO_OUTPUT_LOW 0
#define LCD_GPIO_OUTPUT_HIGH 1
#define LCD_GPIO_INPUT 2
/* Power Control */
#define LCD_CPU_GPIO_NUM_MAX 10
struct lcd_cpu_gpio_s {
char name[15];
struct gpio_desc *gpio;
int flag;
};
#define LCD_PMU_GPIO_NUM_MAX 3
struct lcd_pmu_gpio_s {
char name[15];
int gpio;
};
#define LCD_PWR_STEP_MAX 15
struct lcd_power_step_s {
unsigned char type;
unsigned int index; /* point to lcd_cpu/pmu_gpio_s or lcd_extern */
unsigned int value;
unsigned int delay;
};
struct lcd_power_ctrl_s {
struct lcd_cpu_gpio_s cpu_gpio[LCD_CPU_GPIO_NUM_MAX];
struct lcd_pmu_gpio_s pmu_gpio[LCD_PMU_GPIO_NUM_MAX];
struct lcd_power_step_s power_on_step[LCD_PWR_STEP_MAX];
struct lcd_power_step_s power_off_step[LCD_PWR_STEP_MAX];
int power_on_step_max; /* internal use for debug */
int power_off_step_max; /* internal use for debug */
};
struct lcd_clk_gate_ctrl_s {
struct reset_control *encl;
struct reset_control *vencl;
};
struct lcd_config_s {
char *lcd_propname;
unsigned int backlight_index;
struct lcd_basic_s lcd_basic;
struct lcd_timing_s lcd_timing;
struct lcd_hdr_info_s hdr_info;
struct lcd_control_config_s lcd_control;
struct lcd_power_ctrl_s *lcd_power;
struct pinctrl *pin;
unsigned char pinmux_flag;
struct lcd_clk_gate_ctrl_s rstc;
};
struct lcd_duration_s {
unsigned int duration_num;
unsigned int duration_den;
};
struct aml_lcd_drv_s {
char *version;
enum lcd_chip_e chip_type;
unsigned char lcd_mode;
unsigned char lcd_status;
unsigned char lcd_key_valid;
unsigned char lcd_config_load;
unsigned char lcd_test_flag;
unsigned char lcd_mute;
struct clk *vencl_top;
struct clk *vencl_int;
struct clk *dsi_host;
struct clk *dsi_phy;
struct clk *dsi_meas;
struct device *dev;
struct lcd_config_s *lcd_config;
struct vinfo_s *lcd_info;
struct class *lcd_debug_class;
int fr_auto_policy;
struct lcd_duration_s std_duration;
void (*vout_server_init)(void);
void (*driver_init_pre)(void);
int (*driver_init)(void);
void (*driver_disable)(void);
int (*driver_change)(void);
void (*module_reset)(void);
void (*power_tiny_ctrl)(int status);
void (*driver_tiny_enable)(void);
void (*driver_tiny_disable)(void);
void (*module_tiny_reset)(void);
void (*lcd_test_pattern_restore)(void);
void (*power_ctrl)(int status);
struct workqueue_struct *workqueue;
struct delayed_work lcd_probe_delayed_work;
struct delayed_work lcd_vx1_delayed_work;
struct work_struct lcd_resume_work;
};
extern struct aml_lcd_drv_s *aml_lcd_get_driver(void);
/* IOCTL define */
#define LCD_IOC_TYPE 'C'
#define LCD_IOC_NR_GET_HDR_INFO 0x0
#define LCD_IOC_NR_SET_HDR_INFO 0x1
#define LCD_IOC_CMD_GET_HDR_INFO \
_IOR(LCD_IOC_TYPE, LCD_IOC_NR_GET_HDR_INFO, struct lcd_hdr_info_s)
#define LCD_IOC_CMD_SET_HDR_INFO \
_IOW(LCD_IOC_TYPE, LCD_IOC_NR_SET_HDR_INFO, struct lcd_hdr_info_s)
#endif

View File

@@ -19,6 +19,7 @@
#define _VINFO_H_
#include <linux/amlogic/media/vfm/video_common.h>
/* the MSB is represent vmode set by vmode_init */
#define VMODE_INIT_BIT_MASK 0x8000
#define VMODE_MODE_BIT_MASK 0xff
@@ -57,6 +58,7 @@ struct hdr_info {
u32 lumi_max; /* RX EDID Lumi Max value */
u32 lumi_avg; /* RX EDID Lumi Avg value */
u32 lumi_min; /* RX EDID Lumi Min value */
u8 sink_flag; /*0 = hdmi, 1 = panel*/
};
enum eotf_type {
EOTF_T_NULL = 0,