From 7b2f0e9f485b6a89501aad99f974a353da828568 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 12 Dec 2018 16:33:29 +0800 Subject: [PATCH] lcd: update p2p config and pll setting for tl1 [1/1] PD#SWPL-3108 Problem: 1. tcon pll don't support spread spectrum yet 2. no p2p parameters config Solution: 1. add p2p config parameters 2. enable tl1 clk parameters auto generate 3. add tl1 tcon_pll spread spectrum support 4. update clk spread spectrum api: set ss_level(hex val): echo level >/sys/class/lcd/ss set ss_freq(hex val): echo freq >/sys/class/lcd/ss set ss_mode(hex val): echo mode >/sys/class/lcd/ss set ss advance(hex val, [15:12]=mode, [11:8]=freq, [7:0]=level): echo >/sys/class/lcd/ss show ss_level, ss_freq, ss_mode: cat /sys/class/lcd/ss Verify: x301 Change-Id: I99eeca84290403fe766b17673ba9b0f7429fae26 Signed-off-by: Evoke Zhang --- arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi | 161 ++++++- arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi | 382 +++++++++++++++- arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi | 159 ++++++- drivers/amlogic/media/vout/lcd/lcd_clk_config.c | 485 +++++++++++++++------ drivers/amlogic/media/vout/lcd/lcd_clk_config.h | 20 +- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 58 ++- drivers/amlogic/media/vout/lcd/lcd_common.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_debug.c | 136 ++++-- drivers/amlogic/media/vout/lcd/lcd_reg.c | 4 +- .../amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c | 31 +- drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 82 +++- drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 84 +++- drivers/amlogic/media/vout/lcd/lcd_vout.c | 21 +- include/linux/amlogic/media/vout/lcd/lcd_vout.h | 23 +- 14 files changed, 1384 insertions(+), 265 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi index 1a4171e..57d2023 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi @@ -226,7 +226,7 @@ basic_setting = < 3840 2160 /*h_active, v_active*/ 5000 2250 /*h_period, v_period*/ - 10 /*lcd_bits */ + 8 /*lcd_bits */ 16 9>; /*screen_widht, screen_height*/ range_setting = < 4240 5100 /*h_period_min, max*/ @@ -244,21 +244,166 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/>; + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < + 0 0 1 20 /*panel power on*/ 3 2 0 200 /* extern init voltage */ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index dc3b877..6c90d32 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -192,6 +192,228 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <0>; }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 1 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; p2p{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface @@ -200,7 +422,7 @@ basic_setting = < 3840 2160 /*h_active, v_active*/ 5000 2250 /*h_period, v_period*/ - 10 /*lcd_bits */ + 8 /*lcd_bits */ 16 9>; /*screen_widht, screen_height*/ range_setting = < 4240 5100 /*h_period_min, max*/ @@ -218,13 +440,157 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/>; + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index e112c36..28908e9 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -425,7 +425,7 @@ basic_setting = < 3840 2160 /*h_active, v_active*/ 5000 2250 /*h_period, v_period*/ - 10 /*lcd_bits */ + 8 /*lcd_bits */ 16 9>; /*screen_widht, screen_height*/ range_setting = < 4240 5100 /*h_period_min, max*/ @@ -443,13 +443,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/>; + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -463,6 +465,147 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; }; lcd_extern{ diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index e133ab7..b4fcb6f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -47,9 +47,11 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ .pll_od1_sel = 0, .pll_od2_sel = 0, .pll_od3_sel = 0, - .pll_pi_div_sel = 0, /* for tcon */ + .pll_tcon_div_sel = 0, .pll_level = 0, .ss_level = 0, + .ss_freq = 0, + .ss_mode = 0, .div_sel = 0, .xd = 0, .pll_fout = 0, @@ -162,7 +164,7 @@ pll_lock_end_g12a: return ret; } -static void lcd_set_pll_ss_txl(unsigned int ss_level) +static void lcd_set_pll_ss_level_txl(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4; @@ -171,15 +173,13 @@ static void lcd_set_pll_ss_txl(unsigned int ss_level) pll_ctrl3 &= ~((0xf << 10) | (1 << 14)); pll_ctrl4 &= ~(0x3 << 2); - ss_level = (ss_level >= SS_LEVEL_MAX_TXL) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txl[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txl[ss_level][1]; + pll_ctrl3 |= pll_ss_reg_txl[level][0]; + pll_ctrl4 |= pll_ss_reg_txl[level][1]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txl[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txl[level]); } static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) @@ -216,10 +216,10 @@ static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txl(cConf->ss_level); + lcd_set_pll_ss_level_txl(cConf->ss_level); } -static void lcd_set_pll_ss_txlx(unsigned int ss_level) +static void lcd_set_pll_ss_level_txlx(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4, pll_ctrl5; @@ -230,17 +230,15 @@ static void lcd_set_pll_ss_txlx(unsigned int ss_level) pll_ctrl4 &= ~(0x3 << 2); pll_ctrl5 &= ~(0x3 << 30); - ss_level = (ss_level >= SS_LEVEL_MAX_TXLX) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txlx[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txlx[ss_level][1]; - pll_ctrl5 |= pll_ss_reg_txlx[ss_level][2]; + pll_ctrl3 |= pll_ss_reg_txlx[level][0]; + pll_ctrl4 |= pll_ss_reg_txlx[level][1]; + pll_ctrl5 |= pll_ss_reg_txlx[level][2]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); lcd_hiu_write(HHI_HDMI_PLL_CNTL5, pll_ctrl5); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txlx[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txlx[level]); } static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) @@ -274,7 +272,7 @@ static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txlx(cConf->ss_level); + lcd_set_pll_ss_level_txlx(cConf->ss_level); } static void lcd_set_pll_axg(struct lcd_clk_config_s *cConf) @@ -476,40 +474,90 @@ static void lcd_set_hpll_g12b(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); } -static void lcd_set_pll_ss_tl1(unsigned int ss_level) +static void lcd_set_pll_ss_level_tl1(unsigned int level) { - LCDPR("%s: todo\n", __func__); + unsigned int pll_ctrl2; + unsigned int dep_sel, str_m; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~((1 << 15) | (0xf << 16) | (0xf << 28)); + + if (level > 0) { + dep_sel = pll_ss_reg_tl1[level][0]; + str_m = pll_ss_reg_tl1[level][1]; + dep_sel = (dep_sel > 10) ? 10 : dep_sel; + str_m = (str_m > 10) ? 10 : str_m; + pll_ctrl2 |= ((1 << 15) | (dep_sel << 28) | (str_m << 16)); + } + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_tl1[level]); +} + +static void lcd_set_pll_ss_advance_tl1(unsigned int freq, unsigned int mode) +{ + unsigned int pll_ctrl2; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~(0x7 << 24); /* ss_freq */ + pll_ctrl2 |= (freq << 24); + pll_ctrl2 &= ~(0x3 << 22); /* ss_mode */ + pll_ctrl2 |= (mode << 22); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: freq=%d, mode=%d\n", freq, mode); } static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { -#if 0 +#if 1 unsigned int pll_ctrl, pll_ctrl1; + unsigned int tcon_div_table[5][3] = { + {1, 0, 1}, + {0, 0, 1}, + {0, 1, 1}, + {0, 0, 0}, + {0, 1, 0}, + }; + unsigned int tcon_div_sel = cConf->pll_tcon_div_sel; int ret; if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); pll_ctrl = ((0x3 << 17) | /* gate ctrl */ - (1 << LCD_PLL_RST_TL1) | + (tcon_div_table[tcon_div_sel][2] << 16) | (cConf->pll_n << LCD_PLL_N_TL1) | (cConf->pll_m << LCD_PLL_M_TL1) | (cConf->pll_od3_sel << LCD_PLL_OD3_TL1) | (cConf->pll_od2_sel << LCD_PLL_OD2_TL1) | (cConf->pll_od1_sel << LCD_PLL_OD1_TL1)); - pll_ctrl1 = (1 << 28) | (1 << 23) | - ((1 << 20) | (cConf->pll_frac << 0)); + pll_ctrl1 = (1 << 28) | + (tcon_div_table[tcon_div_sel][0] << 22) | + (tcon_div_table[tcon_div_sel][1] << 21) | + ((1 << 20) | /* sdm_en */ + (cConf->pll_frac << 0)); lcd_hiu_write(HHI_TCON_PLL_CNTL0, pll_ctrl); + udelay(10); + lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_RST_TL1, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_EN_TL1, 1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, pll_ctrl1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x000100c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x008300c0); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); #else struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int ret; @@ -604,8 +652,10 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) lcd_hiu_setb(HHI_TCON_PLL_CNTL2, 1, 5, 1); } - if (cConf->ss_level > 0) - lcd_set_pll_ss_tl1(cConf->ss_level); + if (cConf->ss_level > 0) { + lcd_set_pll_ss_level_tl1(cConf->ss_level); + lcd_set_pll_ss_advance_tl1(cConf->ss_freq, cConf->ss_mode); + } } static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf) @@ -922,8 +972,7 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf, return done; } -static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fvco) +static int check_pll_vco(struct lcd_clk_config_s *cConf, unsigned int pll_fvco) { struct lcd_clk_data_s *data = cConf->data; unsigned int m, n; @@ -956,8 +1005,7 @@ static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, } #define PLL_FVCO_ERR_MAX 2 /* kHz */ -static int check_pll_od_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fout) +static int check_pll_od(struct lcd_clk_config_s *cConf, unsigned int pll_fout) { struct lcd_clk_data_s *data = cConf->data; unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3; @@ -1008,7 +1056,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) { unsigned int pll_fout, pll_fvco, bit_rate; unsigned int clk_div_in, clk_div_out; - unsigned int clk_div_sel, xd, pi_div_sel; + unsigned int clk_div_sel, xd, tcon_div_sel = 0, phy_div = 1; + unsigned int od1, od2, od3; struct lcd_clk_config_s *cConf = get_lcd_clk_config(); int done; @@ -1079,8 +1128,24 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel, pll_fout); } done = check_pll_txl(cConf, pll_fout); - if (done) + if (done == 0) goto generate_clk_done_txl; + done = 0; + if (pconf->lcd_control.lvds_config->dual_port) + phy_div = 2; + else + phy_div = 1; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == + phy_div * od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_VBYONE: cConf->div_sel_max = CLK_DIV_SEL_MAX; @@ -1112,12 +1177,25 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) cConf->div_sel); } done = check_pll_txl(cConf, pll_fout); + if (done == 0) + goto generate_clk_done_txl; + done = 0; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_MLVDS: bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; - for (pi_div_sel = 0; pi_div_sel < 2; pi_div_sel++) { - pll_fvco = bit_rate * pi_div_table[pi_div_sel] * 4; - done = check_pll_tl1_mlvds(cConf, pll_fvco); + for (tcon_div_sel = 1; tcon_div_sel < 3; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel] * 4; + done = check_pll_vco(cConf, pll_fvco); if (done) { clk_div_sel = CLK_DIV_SEL_1; cConf->xd_max = CRT_VID_DIV_MAX; @@ -1140,7 +1218,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) continue; cConf->xd = xd; cConf->div_sel = clk_div_sel; - cConf->pll_pi_div_sel = pi_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; pll_fout = clk_div_in; if (lcd_debug_print_flag == 2) { LCDPR("clk_div_sel=%s(%d)\n", @@ -1149,11 +1227,10 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel); LCDPR("pll_fout=%d\n", pll_fout); - LCDPR("pi_clk_sel=%d\n", - pi_div_sel); + LCDPR("tcon_div_sel=%d\n", + tcon_div_sel); } - done = check_pll_od_tl1_mlvds( - cConf, pll_fout); + done = check_pll_od(cConf, pll_fout); if (done) goto generate_clk_done_txl; } @@ -1161,28 +1238,49 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) } break; case LCD_P2P: - clk_div_sel = CLK_DIV_SEL_1; - xd = 1; - clk_div_out = cConf->fout * xd; - if (clk_div_out > cConf->data->div_out_fmax) - goto generate_clk_done_txl; - if (lcd_debug_print_flag == 2) { - LCDPR("fout=%d, xd=%d, clk_div_out=%d\n", - cConf->fout, xd, clk_div_out); - } - clk_div_in = clk_vid_pll_div_calc(clk_div_out, - clk_div_sel, CLK_DIV_O2I); - if (clk_div_in > cConf->data->div_in_fmax) - goto generate_clk_done_txl; - cConf->xd = xd; - cConf->div_sel = clk_div_sel; - pll_fout = clk_div_in; - if (lcd_debug_print_flag == 2) { - LCDPR("clk_div_sel=%s(index %d), pll_fout=%d\n", - lcd_clk_div_sel_table[clk_div_sel], - clk_div_sel, pll_fout); + bit_rate = pconf->lcd_control.p2p_config->bit_rate / 1000; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { + clk_div_in = clk_vid_pll_div_calc( + clk_div_out, clk_div_sel, + CLK_DIV_O2I); + if (clk_div_in > + cConf->data->div_in_fmax) + continue; + cConf->xd = xd; + cConf->div_sel = clk_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; + pll_fout = clk_div_in; + if (lcd_debug_print_flag == 2) { + LCDPR("clk_div_sel=%s(%d)\n", + lcd_clk_div_sel_table[clk_div_sel], + clk_div_sel); + LCDPR( + "pll_fout=%d, tcon_div_sel=%d\n", + pll_fout, tcon_div_sel); + } + done = check_pll_od(cConf, pll_fout); + if (done) + goto generate_clk_done_txl; + } + } } - done = check_pll_txl(cConf, pll_fout); if (done) goto generate_clk_done_txl; break; @@ -2009,7 +2107,9 @@ static void lcd_clk_config_init_print_dft(void) "div_in_fmax: %d\n" "div_out_fmax: %d\n" "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "ss_level_max: %d\n" + "ss_freq_max: %d\n" + "ss_mode_max: %d\n\n", data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, data->pll_od_fb, data->pll_frac_range, @@ -2018,7 +2118,8 @@ static void lcd_clk_config_init_print_dft(void) data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, data->div_in_fmax, data->div_out_fmax, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax, data->ss_level_max, + data->ss_freq_max, data->ss_mode_max); } static void lcd_clk_config_init_print_axg(void) @@ -2040,8 +2141,7 @@ static void lcd_clk_config_init_print_axg(void) "pll_vco_fmin: %d\n" "pll_out_fmax: %d\n" "pll_out_fmin: %d\n" - "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "xd_out_fmax: %d\n\n", data->vclk_sel, data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, @@ -2050,7 +2150,7 @@ static void lcd_clk_config_init_print_axg(void) data->pll_ref_fmax, data->pll_ref_fmin, data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax); } static int lcd_clk_config_print_dft(char *buf, int offset) @@ -2060,28 +2160,31 @@ static int lcd_clk_config_print_dft(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "lcd clk config:\n" - "pll_mode: %d\n" - "pll_m: %d\n" - "pll_n: %d\n" - "pll_frac: 0x%03x\n" - "pll_fvco: %dkHz\n" - "pll_od1: %d\n" - "pll_od2: %d\n" - "pll_od3: %d\n" - "pll_pi_div_sel: %d\n" - "pll_out: %dkHz\n" - "div_sel: %s(index %d)\n" - "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "pll_mode: %d\n" + "pll_m: %d\n" + "pll_n: %d\n" + "pll_frac: 0x%03x\n" + "pll_fvco: %dkHz\n" + "pll_od1: %d\n" + "pll_od2: %d\n" + "pll_od3: %d\n" + "pll_tcon_div_sel: %d\n" + "pll_out: %dkHz\n" + "div_sel: %s(index %d)\n" + "xd: %d\n" + "fout: %dkHz\n" + "ss_level: %d\n" + "ss_freq: %d\n" + "ss_mode: %d\n\n", clk_conf.pll_mode, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_od2_sel, - clk_conf.pll_od3_sel, clk_conf.pll_pi_div_sel, + clk_conf.pll_od3_sel, clk_conf.pll_tcon_div_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout, clk_conf.ss_level, + clk_conf.ss_freq, clk_conf.ss_mode); return len; } @@ -2100,12 +2203,11 @@ static int lcd_clk_config_print_axg(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); return len; } @@ -2126,13 +2228,12 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); } else { len += snprintf((buf+len), n, "lcd clk config:\n" @@ -2147,8 +2248,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_out: %dkHz\n" "div_sel: %s(index %d)\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, @@ -2156,7 +2256,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) clk_conf.pll_od3_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout); } return len; @@ -2177,43 +2277,100 @@ void lcd_clk_generate_parameter(struct lcd_config_s *pconf) clk_conf.data->clk_generate_parameter(pconf); } -static char lcd_ss_invalid_str[10] = {'i', 'n', 'v', 'a', 'l', 'i', 'd', '\0',}; -char *lcd_get_spread_spectrum(void) +int lcd_get_ss(char *buf) { - char *ss_str = lcd_ss_invalid_str; - unsigned int level; + unsigned int temp; + int len = 0; + + if (clk_conf.data == NULL) { + len += sprintf(buf+len, "lcd clk config data is null\n"); + return len; + } + if (clk_conf.data->ss_level_max == 0) { + len += sprintf(buf+len, "lcd spread spectrum is invalid\n"); + return len; + } - level = clk_conf.ss_level; - if (clk_conf.data) { - level = (level >= clk_conf.data->ss_level_max) ? 0 : level; - if (clk_conf.data->pll_ss_table) - ss_str = clk_conf.data->pll_ss_table[level]; + temp = (clk_conf.ss_level >= clk_conf.data->ss_level_max) ? + 0 : clk_conf.ss_level; + if (clk_conf.data->ss_level_table) { + len += sprintf(buf+len, "ss_level: %s\n", + clk_conf.data->ss_level_table[temp]); + } + temp = (clk_conf.ss_freq >= clk_conf.data->ss_freq_max) ? + 0 : clk_conf.ss_freq; + if (clk_conf.data->ss_freq_table) { + len += sprintf(buf+len, "ss_freq: %s\n", + clk_conf.data->ss_freq_table[temp]); + } + temp = (clk_conf.ss_mode >= clk_conf.data->ss_mode_max) ? + 0 : clk_conf.ss_mode; + if (clk_conf.data->ss_mode_table) { + len += sprintf(buf+len, "ss_mode: %s\n", + clk_conf.data->ss_mode_table[temp]); } - return ss_str; + return len; } -void lcd_set_spread_spectrum(unsigned int ss_level) +int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode) { unsigned long flags = 0; + int ret = -1; spin_lock_irqsave(&lcd_clk_lock, flags); if (clk_conf.data == NULL) { LCDERR("%s: clk config data is null\n", __func__); - goto lcd_set_spread_spectrum_end; + goto lcd_set_ss_end; + } + if (level < 0xff) { + if (level >= clk_conf.data->ss_level_max) { + LCDERR("%s: ss_level %d is out of support (max %d)\n", + __func__, level, clk_conf.data->ss_level_max); + goto lcd_set_ss_end; + } + } + if (freq < 0xff) { + if (freq >= clk_conf.data->ss_freq_max) { + LCDERR("%s: ss_freq %d is out of support (max %d)\n", + __func__, freq, clk_conf.data->ss_freq_max); + goto lcd_set_ss_end; + } + } + if (mode < 0xff) { + if (mode >= clk_conf.data->ss_freq_max) { + LCDERR("%s: ss_mode %d is out of support (max %d)\n", + __func__, mode, clk_conf.data->ss_mode_max); + goto lcd_set_ss_end; + } + } + + if (clk_conf.data->set_ss_level) { + if (level < 0xff) { + clk_conf.ss_level = level; + clk_conf.data->set_ss_level(level); + } } - clk_conf.ss_level = (ss_level >= clk_conf.data->ss_level_max) ? - 0 : ss_level; - if (clk_conf.data->set_spread_spectrum) - clk_conf.data->set_spread_spectrum(clk_conf.ss_level); + ret = 0; + if (clk_conf.data->set_ss_advance) { + if ((freq == 0xff) && (mode == 0xff)) + goto lcd_set_ss_end; + if (freq < 0xff) + clk_conf.ss_freq = freq; + if (mode < 0xff) + clk_conf.ss_mode = mode; + clk_conf.data->set_ss_advance(clk_conf.ss_freq, + clk_conf.ss_mode); + } -lcd_set_spread_spectrum_end: +lcd_set_ss_end: spin_unlock_irqrestore(&lcd_clk_lock, flags); if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + return ret; } int lcd_encl_clk_msr(void) @@ -2435,16 +2592,22 @@ static struct lcd_clk_data_s lcd_clk_data_gxl = { .div_in_fmax = CLK_DIV_IN_MAX_GXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_GXL, .xd_out_fmax = ENCL_CLK_IN_MAX_GXL, - .ss_level_max = SS_LEVEL_MAX_GXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, .clktree_probe = lcd_clktree_probe_dft, @@ -2470,16 +2633,22 @@ static struct lcd_clk_data_s lcd_clk_data_txl = { .div_in_fmax = CLK_DIV_IN_MAX_TXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXL, .xd_out_fmax = ENCL_CLK_IN_MAX_TXL, - .ss_level_max = SS_LEVEL_MAX_TXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txl, + + .ss_level_max = sizeof(lcd_ss_level_table_txl) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txl, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txl, + .set_ss_level = lcd_set_pll_ss_level_txl, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, .clktree_probe = lcd_clktree_probe_dft, @@ -2505,16 +2674,22 @@ static struct lcd_clk_data_s lcd_clk_data_txlx = { .div_in_fmax = CLK_DIV_IN_MAX_TXLX, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXLX, .xd_out_fmax = ENCL_CLK_IN_MAX_TXLX, - .ss_level_max = SS_LEVEL_MAX_TXLX, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txlx, + + .ss_level_max = sizeof(lcd_ss_level_table_txlx) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txlx, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txlx, + .set_ss_level = lcd_set_pll_ss_level_txlx, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txlx, .clk_gate_switch = lcd_clk_gate_switch_dft, .clktree_probe = lcd_clktree_probe_dft, @@ -2540,16 +2715,22 @@ static struct lcd_clk_data_s lcd_clk_data_axg = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_AXG, .xd_out_fmax = ENCL_CLK_IN_MAX_AXG, - .ss_level_max = SS_LEVEL_MAX_AXG, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_axg, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_axg, .clk_gate_switch = lcd_clk_gate_switch_axg, .clktree_probe = lcd_clktree_probe_axg, @@ -2575,16 +2756,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clktree_probe = lcd_clktree_probe_g12a, @@ -2610,16 +2797,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clktree_probe = lcd_clktree_probe_g12a, @@ -2645,16 +2838,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clktree_probe = lcd_clktree_probe_g12a, @@ -2680,16 +2879,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clktree_probe = lcd_clktree_probe_g12a, @@ -2715,16 +2920,22 @@ static struct lcd_clk_data_s lcd_clk_data_tl1 = { .div_in_fmax = CLK_DIV_IN_MAX_TL1, .div_out_fmax = CRT_VID_CLK_IN_MAX_TL1, .xd_out_fmax = ENCL_CLK_IN_MAX_TL1, - .ss_level_max = SS_LEVEL_MAX_TL1, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_tl1, - .pll_ss_table = NULL, + + .ss_level_max = sizeof(lcd_ss_level_table_tl1) / sizeof(char *), + .ss_freq_max = sizeof(lcd_ss_freq_table_tl1) / sizeof(char *), + .ss_mode_max = sizeof(lcd_ss_mode_table_tl1) / sizeof(char *), + .ss_level_table = lcd_ss_level_table_tl1, + .ss_freq_table = lcd_ss_freq_table_tl1, + .ss_mode_table = lcd_ss_mode_table_tl1, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = lcd_set_pll_ss_level_tl1, + .set_ss_advance = lcd_set_pll_ss_advance_tl1, .clk_set = lcd_clk_set_tl1, .clk_gate_switch = lcd_clk_gate_switch_tl1, .clktree_probe = lcd_clktree_probe_tl1, diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 8a52cda..41c7601 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -57,16 +57,22 @@ struct lcd_clk_data_s { unsigned int div_in_fmax; unsigned int div_out_fmax; unsigned int xd_out_fmax; - unsigned int ss_level_max; unsigned char clk_path_valid; unsigned char vclk_sel; struct lcd_clk_ctrl_s *pll_ctrl_table; - char **pll_ss_table; + + unsigned int ss_level_max; + unsigned int ss_freq_max; + unsigned int ss_mode_max; + char **ss_level_table; + char **ss_freq_table; + char **ss_mode_table; void (*clk_generate_parameter)(struct lcd_config_s *pconf); void (*pll_frac_generate)(struct lcd_config_s *pconf); - void (*set_spread_spectrum)(unsigned int ss_level); + void (*set_ss_level)(unsigned int level); + void (*set_ss_advance)(unsigned int freq, unsigned int mode); void (*clk_set)(struct lcd_config_s *pconf); void (*clk_gate_switch)(struct aml_lcd_drv_s *lcd_drv, int status); void (*clktree_probe)(void); @@ -89,11 +95,13 @@ struct lcd_clk_config_s { /* unit: kHz */ unsigned int pll_od1_sel; unsigned int pll_od2_sel; unsigned int pll_od3_sel; - unsigned int pll_pi_div_sel; /* for tcon */ + unsigned int pll_tcon_div_sel; unsigned int pll_level; unsigned int pll_frac; unsigned int pll_fout; unsigned int ss_level; + unsigned int ss_freq; + unsigned int ss_mode; unsigned int div_sel; unsigned int xd; unsigned int div_sel_max; @@ -127,8 +135,8 @@ extern struct lcd_clk_config_s *get_lcd_clk_config(void); extern int lcd_clk_config_print(char *buf, int offset); 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(unsigned int ss_level); +extern int lcd_get_ss(char *buf); +extern int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode); 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); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 4f67320..9028dfd 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -239,13 +239,8 @@ * Spread Spectrum * ********************************** */ -#define SS_LEVEL_MAX_GXL 0 -#define SS_LEVEL_MAX_AXG 0 -#define SS_LEVEL_MAX_GP0_G12A 0 -#define SS_LEVEL_MAX_HPLL_G12A 0 -#define SS_LEVEL_MAX_TXL 5 -static char *lcd_pll_ss_table_txl[] = { +static char *lcd_ss_level_table_txl[] = { "0, disable", "1, +/-0.3%", "2, +/-0.4%", @@ -253,8 +248,7 @@ static char *lcd_pll_ss_table_txl[] = { "4, +/-1.2%", }; -#define SS_LEVEL_MAX_TXLX 6 -static char *lcd_pll_ss_table_txlx[] = { +static char *lcd_ss_level_table_txlx[] = { "0, disable", "1, +/-0.3%", "2, +/-0.5%", @@ -263,7 +257,35 @@ static char *lcd_pll_ss_table_txlx[] = { "5, +/-3.0%", }; -#define SS_LEVEL_MAX_TL1 0 +static char *lcd_ss_level_table_tl1[] = { + "0, disable", + "1, 5000ppm", + "2, 10000ppm", + "3, 15000ppm", + "4, 20000ppm", + "5, 25000ppm", + "6, 30000ppm", + "7, 35000ppm", + "8, 40000ppm", + "9, 45000ppm", + "10, 50000ppm", +}; + +static char *lcd_ss_freq_table_tl1[] = { + "0, 29.5KHz", + "1, 31.5KHz", + "2, 50KHz", + "3, 75KHz", + "4, 100KHz", + "5, 150KHz", + "6, 200KHz", +}; + +static char *lcd_ss_mode_table_tl1[] = { + "0, center ss", + "1, up ss", + "2, down ss", +}; static unsigned int pll_ss_reg_txl[][2] = { @@ -275,7 +297,6 @@ static unsigned int pll_ss_reg_txl[][2] = { {((1 << 14) | (0xc << 10)), (0x3 << 2)}, /* 4: +/-1.2% */ }; - static unsigned int pll_ss_reg_txlx[][3] = { /* cntl3 cntl4 cntl5 */ { 0, 0, 0}, /* disable */ @@ -286,6 +307,21 @@ static unsigned int pll_ss_reg_txlx[][3] = { {((1 << 14) | (0xa << 10)), (0x3 << 2), (0x2 << 30)}, /* 5: +/-3.0% */ }; +static unsigned int pll_ss_reg_tl1[][2] = { + /* dep_sel, str_m */ + { 0, 0}, /* 0: disable */ + {10, 1}, /* 1: +/-0.25% */ + {10, 2}, /* 2: +/-0.50% */ + {10, 3}, /* 3: +/-0.75% */ + {10, 4}, /* 4: +/-1.00% */ + {10, 5}, /* 5: +/-1.25% */ + {10, 6}, /* 1: +/-1.50% */ + {10, 7}, /* 2: +/-1.75% */ + {10, 8}, /* 3: +/-2.00% */ + {10, 9}, /* 4: +/-2.25% */ + {10, 10}, /* 5: +/-2.50% */ +}; + /* ********************************** * pll control * ********************************** @@ -351,7 +387,7 @@ static const unsigned int od_table[6] = { 1, 2, 4, 8, 16, 32 }; -static const unsigned int pi_div_table[2] = {2, 4}; +static const unsigned int tcon_div_table[5] = {1, 2, 4, 8, 16}; static char *lcd_clk_div_sel_table[] = { "1", diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 8ecc3ca..3e790508 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -33,7 +33,8 @@ /* 20180827: add pinmux off support */ /* 20180928: tl1 support, optimize clk config */ /* 20181012: tl1 support tcon */ -#define LCD_DRV_VERSION "20181012" +/* 20181212: tl1 update p2p config and pll setting */ +#define LCD_DRV_VERSION "20181212" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 6179800..4d562b7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -101,9 +101,14 @@ static const char *lcd_common_usage_str = { "\n" " echo > test ; show lcd bist pattern(1~7), 0=disable bist\n" "\n" -" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" +" echo level > ss ; set lcd clk spread spectrum level\n" +" echo freq > ss ; set lcd clk spread spectrum freq\n" +" echo mode > ss ; set lcd clk spread spectrum mode\n" +" cat ss ; show lcd clk spread spectrum information\n" +"\n" +" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" "\n" " echo <0|1> > print ; 0=disable debug print; 1=enable debug print\n" " cat print ; read current debug print flag\n" @@ -462,26 +467,24 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, + "p2p_type %d\n" "lane_num %d\n" "channel_sel1 0x%08x\n" "channel_sel1 0x%08x\n" - "clk_phase 0x%04x\n" "pn_swap %u\n" "bit_swap %u\n" - "phy_vswing 0x%x\n" - "phy_preem 0x%x\n" "bit_rate %dHz\n" - "pi_clk_sel 0x%03x\n\n", + "phy_vswing 0x%x\n" + "phy_preem 0x%x\n\n", + pconf->lcd_control.p2p_config->p2p_type, pconf->lcd_control.p2p_config->lane_num, pconf->lcd_control.p2p_config->channel_sel0, pconf->lcd_control.p2p_config->channel_sel1, - pconf->lcd_control.p2p_config->clk_phase, pconf->lcd_control.p2p_config->pn_swap, pconf->lcd_control.p2p_config->bit_swap, - pconf->lcd_control.p2p_config->phy_vswing, - pconf->lcd_control.p2p_config->phy_preem, pconf->lcd_control.p2p_config->bit_rate, - pconf->lcd_control.p2p_config->pi_clk_sel); + pconf->lcd_control.p2p_config->phy_vswing, + pconf->lcd_control.p2p_config->phy_preem); len += lcd_tcon_info_print((buf+len), (len+offset)); @@ -2030,24 +2033,21 @@ static ssize_t lcd_debug_change_store(struct class *class, break; case 'p': p2p_conf = pconf->lcd_control.p2p_config; - ret = sscanf(buf, "p2p %d %x %x %x %d %d", + ret = sscanf(buf, "p2p %d %d %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { - p2p_conf->lane_num = val[0]; - p2p_conf->channel_sel0 = val[1]; - p2p_conf->channel_sel1 = val[2]; - p2p_conf->clk_phase = val[3]; + p2p_conf->p2p_type = val[0]; + p2p_conf->lane_num = val[1]; + p2p_conf->channel_sel0 = val[2]; + p2p_conf->channel_sel1 = val[3]; p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; pr_info("change p2p config:\n" - "lane_num=%d,\n" + "p2p_type=%d, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->lane_num, - p2p_conf->channel_sel0, - p2p_conf->channel_sel1, - p2p_conf->clk_phase, + p2p_conf->p2p_type, p2p_conf->lane_num, + p2p_conf->channel_sel0, p2p_conf->channel_sel1, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_change_clk_change(pconf->lcd_timing.lcd_clk); pconf->change_flag = 1; @@ -2283,24 +2283,81 @@ static ssize_t lcd_debug_fr_policy_store(struct class *class, static ssize_t lcd_debug_ss_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "get lcd pll spread spectrum: %s\n", - lcd_get_spread_spectrum()); + int len; + + len = lcd_get_ss(buf); + return len; } static ssize_t lcd_debug_ss_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; - unsigned int temp = 0; + unsigned int value = 0, temp; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - ret = kstrtouint(buf, 10, &temp); - if (ret) { - pr_info("invalid data\n"); - return -EINVAL; + temp = lcd_drv->lcd_config->lcd_timing.ss_level; + switch (buf[0]) { + case 'l': + ret = sscanf(buf, "level %x", &value); + if (ret == 1) { + value &= 0xff; + ret = lcd_set_ss(value, 0xff, 0xff); + if (ret == 0) { + temp &= ~(0xff); + temp |= value; + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'f': + ret = sscanf(buf, "freq %x", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, value, 0xff); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_FREQ) << 8); + temp |= ((value << LCD_CLK_SS_BIT_FREQ) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'm': + ret = sscanf(buf, "mode %x", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, 0xff, value); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_MODE) << 8); + temp |= ((value << LCD_CLK_SS_BIT_MODE) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + default: + ret = kstrtouint(buf, 16, &value); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } + value &= 0xffff; + temp = value >> 8; + ret = lcd_set_ss((value & 0xff), + ((temp >> LCD_CLK_SS_BIT_FREQ) & 0xf), + ((temp >> LCD_CLK_SS_BIT_MODE) & 0xf)); + if (ret == 0) + lcd_drv->lcd_config->lcd_timing.ss_level = value; + break; } - lcd_drv->lcd_config->lcd_timing.ss_level = temp; - lcd_set_spread_spectrum(temp); return count; } @@ -2423,9 +2480,9 @@ static ssize_t lcd_debug_mute_store(struct class *class, } static void lcd_debug_reg_write(unsigned int reg, unsigned int data, - unsigned int type) + unsigned int bus) { - switch (type) { + switch (bus) { case 0: /* vcbus */ lcd_vcbus_write(reg, data); pr_info("write vcbus [0x%04x] = 0x%08x, readback 0x%08x\n", @@ -3348,20 +3405,17 @@ static ssize_t lcd_p2p_debug_store(struct class *class, struct p2p_config_s *p2p_conf; p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; - ret = sscanf(buf, "%d %x %x %x %d %d", - &p2p_conf->lane_num, + ret = sscanf(buf, "%d %d %x %x %d %d", + &p2p_conf->p2p_type, &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, - &p2p_conf->clk_phase, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { - pr_info("set minilvds config:\n" - "lane_num=%d,\n" + pr_info("set p2p config:\n" + "p2p_type=%d, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->lane_num, + p2p_conf->p2p_type, p2p_conf->lane_num, p2p_conf->channel_sel0, p2p_conf->channel_sel1, - p2p_conf->clk_phase, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_config_update(); } else { diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.c b/drivers/amlogic/media/vout/lcd/lcd_reg.c index 690bc66..2824b04 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.c +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.c @@ -195,7 +195,7 @@ static inline void __iomem *check_lcd_tcon_reg(unsigned int _reg) reg_offset = LCD_REG_OFFSET(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; @@ -214,7 +214,7 @@ static inline void __iomem *check_lcd_tcon_reg_byte(unsigned int _reg) reg_offset = LCD_REG_OFFSET_BYTE(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 50814cc..7002b69 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -728,7 +728,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); if (para[3] > 0) { pconf->lcd_timing.lcd_clk = para[3]; @@ -1167,18 +1167,17 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; unsigned int sync_duration, h_period, v_period; - clk = pconf->lcd_timing.lcd_clk; + temp = pconf->lcd_timing.lcd_clk; h_period = pconf->lcd_basic.h_period; v_period = pconf->lcd_basic.v_period; - if (clk < 200) { /* regard as frame_rate */ - sync_duration = clk * 100; - pconf->lcd_timing.lcd_clk = clk * h_period * v_period; + if (temp < 200) { /* regard as frame_rate */ + sync_duration = temp * 100; + pconf->lcd_timing.lcd_clk = temp * h_period * v_period; } else { /* regard as pixel clock */ - sync_duration = ((clk / h_period) * 100) / v_period; + sync_duration = ((temp / h_period) * 100) / v_period; } pconf->lcd_timing.sync_duration_num = sync_duration; pconf->lcd_timing.sync_duration_den = 100; @@ -1191,13 +1190,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_tablet_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } lcd_tablet_config_post_update(pconf); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index eaab5e7..848f4f2 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -314,7 +314,15 @@ static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 30, 1); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + break; + } lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); } else { @@ -338,11 +346,22 @@ static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { + unsigned int lcd_bits; + lcd_vcbus_write(L_RGB_BASE_ADDR, 0); lcd_vcbus_write(L_RGB_COEFF_ADDR, 0x400); aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, NULL); - switch (pconf->lcd_basic.lcd_bits) { + switch (pconf->lcd_basic.lcd_type) { + case LCD_MLVDS: + case LCD_P2P: + lcd_bits = 10; + break; + default: + lcd_bits = pconf->lcd_basic.lcd_bits; + break; + } + switch (lcd_bits) { case 8: lcd_vcbus_write(L_DITH_CNTL_ADDR, 0x400); break; @@ -1477,10 +1496,22 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int reg_cntl0, reg_cntl1; + unsigned int phy_div; + unsigned int channel_sel0, channel_sel1; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + /* phy_div: 0=div6, 1=div 7, 2=div8, 3=div10 */ + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: /* 8/10 coding */ + phy_div = 3; + break; + default: + phy_div = 2; + break; + } + switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; @@ -1493,7 +1524,7 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) } /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ - lcd_hiu_write(reg_cntl0, (2 << 6)); + lcd_hiu_write(reg_cntl0, (phy_div << 6)); /* serializer_en[27:16] */ lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); /* pn swap[2] */ @@ -1505,9 +1536,11 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) lcd_hiu_setb(reg_cntl1, 1, 31, 1); /* channel swap default no swap */ - lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); - lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); - lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); + channel_sel0 = pconf->lcd_control.p2p_config->channel_sel0; + channel_sel1 = pconf->lcd_control.p2p_config->channel_sel1; + lcd_vcbus_write(LVDS_CH_SWAP0, (channel_sel0 & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP1, ((channel_sel0 >> 8) & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP2, (channel_sel1 & 0xff)); lcd_tcon_enable(pconf); } @@ -1641,6 +1674,35 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) } } +static void lcd_p2p_config_set(struct lcd_config_s *pconf) +{ + unsigned int bit_rate, pclk; + unsigned int lcd_bits, lane_num; + + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + + lcd_bits = pconf->lcd_basic.lcd_bits; + lane_num = pconf->lcd_control.p2p_config->lane_num; + pclk = pconf->lcd_timing.lcd_clk / 1000; + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: /* 8/10 coding */ + bit_rate = (pclk * 3 * lcd_bits * 10 / 8) / lane_num; + break; + default: + bit_rate = pclk * 3 * lcd_bits / lane_num; + break; + } + + pconf->lcd_control.p2p_config->bit_rate = bit_rate * 1000; + + if (lcd_debug_print_flag) { + LCDPR("lane_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", + lane_num, (bit_rate / 1000), (bit_rate % 1000), + (pclk / 1000), (pclk % 1000)); + } +} + void lcd_tv_clk_config_change(struct lcd_config_s *pconf) { #ifdef CONFIG_AMLOGIC_VPU @@ -1653,6 +1715,9 @@ void lcd_tv_clk_config_change(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1693,6 +1758,9 @@ void lcd_tv_config_update(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1790,8 +1858,8 @@ int lcd_tv_driver_init(void) break; case LCD_P2P: lcd_tcon_pinmux_set(1); - lcd_p2p_control_set(pconf); lcd_p2p_phy_set(pconf, 1); + lcd_p2p_control_set(pconf); break; default: break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index 7943a6f..581cc1d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -810,6 +810,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, struct device_node *child; struct lvds_config_s *lvdsconf; struct vbyone_config_s *vx1_conf; + struct p2p_config_s *p2p_conf; child = of_get_child_by_name(dev->of_node, pconf->lcd_propname); if (child == NULL) { @@ -886,9 +887,9 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); - pconf->lcd_timing.lcd_clk = (unsigned char)(para[3]); + pconf->lcd_timing.lcd_clk = para[3]; } switch (pconf->lcd_basic.lcd_type) { @@ -1015,6 +1016,33 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } break; case LCD_P2P: + p2p_conf = pconf->lcd_control.p2p_config; + ret = of_property_read_u32_array(child, "p2p_attr", + ¶[0], 6); + if (ret) { + LCDERR("failed to get p2p_attr\n"); + } else { + p2p_conf->p2p_type = para[0]; + p2p_conf->lane_num = para[1]; + p2p_conf->channel_sel0 = para[2]; + p2p_conf->channel_sel1 = para[3]; + p2p_conf->pn_swap = para[4]; + p2p_conf->bit_swap = para[5]; + } + ret = of_property_read_u32_array(child, "phy_attr", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get phy_attr\n"); + } else { + p2p_conf->phy_vswing = para[0]; + p2p_conf->phy_preem = para[1]; + if (lcd_debug_print_flag) { + LCDPR("phy vswing=0x%x, preem=0x%x\n", + p2p_conf->phy_vswing, + p2p_conf->phy_preem); + } + } break; default: LCDERR("invalid lcd type\n"); @@ -1036,6 +1064,7 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) struct aml_lcd_unifykey_header_s lcd_header; struct lvds_config_s *lvdsconf = pconf->lcd_control.lvds_config; struct vbyone_config_s *vx1_conf = pconf->lcd_control.vbyone_config; + struct p2p_config_s *p2p_conf = pconf->lcd_control.p2p_config; int ret; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_LCD_SIZE), GFP_KERNEL); @@ -1210,6 +1239,27 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; lvdsconf->lane_reverse = 0; } + } else if (pconf->lcd_basic.lcd_type == LCD_P2P) { + p2p_conf->p2p_type = (*(p + LCD_UKEY_IF_ATTR_0) | + ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)); + p2p_conf->lane_num = (*(p + LCD_UKEY_IF_ATTR_1) | + ((*(p + LCD_UKEY_IF_ATTR_1 + 1)) << 8)); + p2p_conf->channel_sel0 = (*(p + LCD_UKEY_IF_ATTR_2) | + ((*(p + LCD_UKEY_IF_ATTR_2 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_3) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_3 + 1)) << 24)); + p2p_conf->channel_sel1 = (*(p + LCD_UKEY_IF_ATTR_4) | + ((*(p + LCD_UKEY_IF_ATTR_4 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_5) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_5 + 1)) << 24)); + p2p_conf->pn_swap = (*(p + LCD_UKEY_IF_ATTR_6) | + ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)); + p2p_conf->bit_swap = (*(p + LCD_UKEY_IF_ATTR_7) | + ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)); + p2p_conf->phy_vswing = (*(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8)); + p2p_conf->phy_preem = (*(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8)); } else LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); @@ -1274,19 +1324,19 @@ static void lcd_vmode_init(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; if (pconf->lcd_timing.lcd_clk == 0) /* default 0 for 60hz */ pconf->lcd_timing.lcd_clk = 60; else LCDPR("custome clk: %d\n", pconf->lcd_timing.lcd_clk); - clk = pconf->lcd_timing.lcd_clk; - if (clk < 200) { /* regard as frame_rate */ - pconf->lcd_timing.lcd_clk = clk * pconf->lcd_basic.h_period * + temp = pconf->lcd_timing.lcd_clk; + if (temp < 200) { /* regard as frame_rate */ + pconf->lcd_timing.lcd_clk = temp * pconf->lcd_basic.h_period * pconf->lcd_basic.v_period; - } else /* regard as pixel clock */ - pconf->lcd_timing.lcd_clk = clk; + } else { /* regard as pixel clock */ + pconf->lcd_timing.lcd_clk = temp; + } pconf->lcd_timing.lcd_clk_dft = pconf->lcd_timing.lcd_clk; pconf->lcd_timing.h_period_dft = pconf->lcd_basic.h_period; @@ -1296,13 +1346,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_vmode_init(pconf); lcd_tv_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 3645228..ff3205c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -47,6 +47,7 @@ #endif #include "lcd_reg.h" #include "lcd_common.h" +#include "lcd_clk_config.h" #define LCD_CDEV_NAME "lcd" @@ -130,17 +131,14 @@ static struct mlvds_config_s lcd_mlvds_config = { static struct p2p_config_s lcd_p2p_config = { .p2p_type = P2P_MAX, - .port_num = 6, .lane_num = 12, .channel_sel0 = 0x76543210, .channel_sel1 = 0xba98, - .clk_phase = 0, .pn_swap = 0, .bit_swap = 0, .phy_vswing = 0, .phy_preem = 0, - .pi_clk_sel = 0, .bit_rate = 0, }; @@ -263,7 +261,7 @@ static void lcd_power_ctrl(int status) #ifdef CONFIG_AMLOGIC_LCD_EXTERN struct aml_lcd_extern_driver_s *ext_drv; #endif - int i, index; + unsigned int i, index, value, temp; int ret = 0; LCDPR("%s: %d\n", __func__, status); @@ -315,6 +313,21 @@ static void lcd_power_ctrl(int status) } break; #endif + case LCD_POWER_TYPE_WAIT_GPIO: + break; + case LCD_POWER_TYPE_CLK_SS: + temp = lcd_driver->lcd_config->lcd_timing.ss_level; + value = (power_step->value) & 0xff; + ret = lcd_set_ss(0xff, + (value >> LCD_CLK_SS_BIT_FREQ) & 0xf, + (value >> LCD_CLK_SS_BIT_MODE) & 0xf); + if (ret == 0) { + temp &= ~(0xff << 8); + temp |= (value << 8); + lcd_driver->lcd_config->lcd_timing.ss_level = + temp; + } + break; default: break; } diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 62808b4..0097b78 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -134,17 +134,18 @@ struct lcd_basic_s { #define LCD_CLK_PLL_CHANGE (1 << 1) struct lcd_timing_s { unsigned char clk_auto; /* clk parameters auto generation */ + unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */ + unsigned char clk_change; /* internal used */ 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 ss_level; /* [15:12]: ss_freq, [11:8]: ss_mode, + * [7:0]: ss_level + */ unsigned int sync_duration_num; unsigned int sync_duration_den; @@ -338,25 +339,24 @@ struct mlvds_config_s { enum p2p_type_e { P2P_CEDS = 0, + P2P_CSPI, + P2P_CMPI, + P2P_ISP, + P2P_CHPI, P2P_MAX, }; struct p2p_config_s { unsigned int p2p_type; - unsigned int port_num; unsigned int lane_num; unsigned int channel_sel0; unsigned int channel_sel1; - unsigned int clk_phase; /* [13:12]=clk01_pi_sel, - * [11:8]=pi2, [7:4]=pi1, [3:0]=pi0 - */ unsigned int pn_swap; unsigned int bit_swap; /* MSB/LSB reverse */ unsigned int phy_vswing; unsigned int phy_preem; /* internal used */ - unsigned int pi_clk_sel; /* bit[9:0] */ unsigned int bit_rate; /* Hz */ }; @@ -379,6 +379,8 @@ enum lcd_power_type_e { LCD_POWER_TYPE_PMU, LCD_POWER_TYPE_SIGNAL, LCD_POWER_TYPE_EXTERN, + LCD_POWER_TYPE_WAIT_GPIO, + LCD_POWER_TYPE_CLK_SS, LCD_POWER_TYPE_MAX, }; @@ -391,6 +393,9 @@ enum lcd_pmu_gpio_e { LCD_PMU_GPIO_MAX, }; +#define LCD_CLK_SS_BIT_FREQ 0 +#define LCD_CLK_SS_BIT_MODE 4 + #define LCD_GPIO_MAX 0xff #define LCD_GPIO_OUTPUT_LOW 0 #define LCD_GPIO_OUTPUT_HIGH 1 -- 2.7.4