blob: 97a18dba3dd56a5d406282bd5dc0daa2612826fc [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/amlogic/media/vout/hdmi_tx21/hdmi_tx_module.h>
#include "common.h"
#ifdef CONFIG_AMLOGIC_VPU
#include <linux/amlogic/media/vpu/vpu.h>
#endif
/* local frac_rate flag */
static u32 frac_rate;
static void set_crt_video_enc(u32 vidx, u32 in_sel, u32 div_n);
static void set_crt_video_enc2(u32 vidx, u32 in_sel, u32 div_n);
/*
* HDMITX Clock configuration
*/
static inline int check_div(u32 div)
{
if (div == -1)
return -1;
switch (div) {
case 1:
div = 0;
break;
case 2:
div = 1;
break;
case 4:
div = 2;
break;
case 6:
div = 3;
break;
case 12:
div = 4;
break;
default:
break;
}
return div;
}
static void hdmitx_disable_encp_clk(struct hdmitx_dev *hdev)
{
//hd21_set_reg_bits(CLKCTRL_VID_CLK_CTRL2, 0, 2, 1);
}
static void hdmitx_enable_encp_clk(struct hdmitx_dev *hdev)
{
//hd21_set_reg_bits(CLKCTRL_VID_CLK_CTRL2, 1, 2, 1);
}
static void hdmitx_disable_enci_clk(struct hdmitx_dev *hdev)
{
//hd21_set_reg_bits(CLKCTRL_VID_CLK_CTRL2, 0, 0, 1);
if (hdev->hdmitx_clk_tree.venci_top_gate)
clk_disable_unprepare(hdev->hdmitx_clk_tree.venci_top_gate);
if (hdev->hdmitx_clk_tree.venci_0_gate)
clk_disable_unprepare(hdev->hdmitx_clk_tree.venci_0_gate);
if (hdev->hdmitx_clk_tree.venci_1_gate)
clk_disable_unprepare(hdev->hdmitx_clk_tree.venci_1_gate);
}
static void hdmitx_disable_tx_pixel_clk(struct hdmitx_dev *hdev)
{
//hd21_set_reg_bits(CLKCTRL_VID_CLK_CTRL2, 0, 5, 1);
}
void hdmitx21_set_audioclk(bool en)
{
u32 data32;
// Enable hdmitx_aud_clk
// [10: 9] clk_sel for cts_hdmitx_aud_clk: 2=fclk_div3
// [ 8] clk_en for cts_hdmitx_aud_clk
// [ 6: 0] clk_div for cts_hdmitx_aud_clk: fclk_div3/aud_clk_div
data32 = 0;
data32 |= (2 << 9);
data32 |= (0 << 8);
data32 |= ((18 - 1) << 0);
hd21_write_reg(CLKCTRL_HTX_CLK_CTRL1, data32);
// [ 8] clk_en for cts_hdmitx_aud_clk
hd21_set_reg_bits(CLKCTRL_HTX_CLK_CTRL1, en, 8, 1);
}
void hdmitx21_set_default_clk(void)
{
u32 data32;
// Enable clk81_hdmitx_pclk
hd21_set_reg_bits(CLKCTRL_SYS_CLK_EN0_REG2, 1, 4, 1);
// Enable fixed hdmitx_sys_clk
data32 = 0;
data32 |= (3 << 9); // [10: 9] clk_sel for cts_hdmitx_sys_clk: 3=fclk_div5
data32 |= (0 << 8); // [ 8] clk_en for cts_hdmitx_sys_clk
data32 |= (1 << 0); // [ 6: 0] clk_div for cts_hdmitx_sys_clk: fclk_dvi5/2=400/2=200M
hd21_write_reg(CLKCTRL_HDMI_CLK_CTRL, data32);
data32 |= (1 << 8); // [ 8] clk_en for cts_hdmitx_sys_clk
hd21_write_reg(CLKCTRL_HDMI_CLK_CTRL, data32);
// Enable fixed hdmitx_prif_clk, hdmitx_200m_clk
data32 = 0;
data32 |= (3 << 25); // [26:25] clk_sel for cts_hdmitx_200m_clk: 3=fclk_div5
data32 |= (0 << 24); // [ 24] clk_en for cts_hdmitx_200m_clk
data32 |= (1 << 16); // [22:16] clk_div for cts_hdmitx_200m_clk: fclk_dvi5/16=400/16=25M
data32 |= (3 << 9); // [10: 9] clk_sel for cts_hdmitx_prif_clk: 3=fclk_div5
data32 |= (0 << 8); // [ 8] clk_en for cts_hdmitx_prif_clk
data32 |= (1 << 0); // [ 6: 0] clk_div for cts_hdmitx_prif_clk: fclk_dvi5/2=400/2=200M
hd21_write_reg(CLKCTRL_HTX_CLK_CTRL0, data32);
data32 |= (1 << 24); // [ 24] clk_en for cts_hdmitx_200m_clk
data32 |= (1 << 8); // [ 8] clk_en for cts_hdmitx_prif_clk
hd21_write_reg(CLKCTRL_HTX_CLK_CTRL0, data32);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 0, 0, 5);
// wire wr_enable = control[3];
// wire fifo_enable = control[2];
// assign phy_clk_en = control[1];
hd21_set_reg_bits(ANACTRL_HDMIPHY_CTRL1, 1, 1, 1); // Enable tmds_clk
hd21_set_reg_bits(ANACTRL_HDMIPHY_CTRL1, 1, 2, 1); // Enable the decoupling FIFO
// Enable enable the write/read decoupling state machine
hd21_set_reg_bits(ANACTRL_HDMIPHY_CTRL1, 1, 3, 1);
// Bring HDMITX MEM output of power down
hd21_set_reg_bits(PWRCTRL_MEM_PD11, 0, 8, 8);
// Bring out of reset
hdmitx21_wr_reg(HDMITX_TOP_SW_RESET, 0);
// Test after initial out of reset, cannot write to IP register, unless enable access
hdmitx21_wr_reg(INTR3_MASK_IVCTX, 0xff);
hdmitx21_wr_reg(HDMITX_TOP_SEC_SCRATCH, 1);
}
void hdmitx21_set_cts_hdcp22_clk(struct hdmitx_dev *hdev)
{
//hd21_write_reg(CLKCTRL_HDCP22_CLK_CTRL, 0x01000100);
}
void hdmitx21_set_hdcp_pclk(struct hdmitx_dev *hdev)
{
/* top hdcp pixel clock */
hd21_set_reg_bits(CLKCTRL_SYS_CLK_EN0_REG2, 1, 3, 1);
}
static void set_hpll_clk_out(u32 clk)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
pr_info("config HPLL = %d frac_rate = %d\n", clk, frac_rate);
switch (hdev->data->chip_type) {
case MESON_CPU_ID_T7:
set21_t7_hpll_clk_out(frac_rate, clk);
default:
break;
}
pr_info("config HPLL done\n");
}
/* HERE MUST BE BIT OPERATION!!! */
static void set_hpll_sspll(enum hdmi_vic vic)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
switch (hdev->data->chip_type) {
case MESON_CPU_ID_T7:
set21_hpll_sspll_t7(vic);
break;
default:
break;
}
}
static void set_hpll_od1(u32 div)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
switch (hdev->data->chip_type) {
case MESON_CPU_ID_T7:
default:
set21_hpll_od1_t7(div);
break;
}
}
static void set_hpll_od2(u32 div)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
switch (hdev->data->chip_type) {
case MESON_CPU_ID_T7:
default:
set21_hpll_od2_t7(div);
break;
}
}
static void set_hpll_od3(u32 div)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
switch (hdev->data->chip_type) {
case MESON_CPU_ID_T7:
default:
set21_hpll_od3_t7(div);
break;
}
}
/* --------------------------------------------------
* clocks_set_vid_clk_div
* --------------------------------------------------
* wire clk_final_en = control[19];
* wire clk_div1 = control[18];
* wire [1:0] clk_sel = control[17:16];
* wire set_preset = control[15];
* wire [14:0] shift_preset = control[14:0];
*/
static void clocks_set_vid_clk_div_for_hdmi(int div_sel)
{
int shift_val = 0;
int shift_sel = 0;
u32 reg_vid_pll = CLKCTRL_HDMI_VID_PLL_CLK_DIV;
struct hdmitx_dev *hdev = get_hdmitx21_device();
pr_info("%s[%d] div = %d\n", __func__, __LINE__, div_sel);
/* Disable the output clock */
hd21_set_reg_bits(reg_vid_pll, 0, 18, 2);
hd21_set_reg_bits(reg_vid_pll, 0, 15, 1);
if (hdev->enc_idx == 2)
hd21_set_reg_bits(reg_vid_pll, 1, 25, 1); /* vid_pll2_clk_sel_hdmi */
else
hd21_set_reg_bits(reg_vid_pll, 1, 24, 1); /* vid_pll2_clk_sel_hdmi */
switch (div_sel) {
case VID_PLL_DIV_1:
shift_val = 0xFFFF;
shift_sel = 0;
break;
case VID_PLL_DIV_2:
shift_val = 0x0aaa;
shift_sel = 0;
break;
case VID_PLL_DIV_3:
shift_val = 0x0db6;
shift_sel = 0;
break;
case VID_PLL_DIV_3p5:
shift_val = 0x36cc;
shift_sel = 1;
break;
case VID_PLL_DIV_3p75:
shift_val = 0x6666;
shift_sel = 2;
break;
case VID_PLL_DIV_4:
shift_val = 0x0ccc;
shift_sel = 0;
break;
case VID_PLL_DIV_5:
shift_val = 0x739c;
shift_sel = 2;
break;
case VID_PLL_DIV_6:
shift_val = 0x0e38;
shift_sel = 0;
break;
case VID_PLL_DIV_6p25:
shift_val = 0x0000;
shift_sel = 3;
break;
case VID_PLL_DIV_7:
shift_val = 0x3c78;
shift_sel = 1;
break;
case VID_PLL_DIV_7p5:
shift_val = 0x78f0;
shift_sel = 2;
break;
case VID_PLL_DIV_12:
shift_val = 0x0fc0;
shift_sel = 0;
break;
case VID_PLL_DIV_14:
shift_val = 0x3f80;
shift_sel = 1;
break;
case VID_PLL_DIV_15:
shift_val = 0x7f80;
shift_sel = 2;
break;
case VID_PLL_DIV_2p5:
shift_val = 0x5294;
shift_sel = 2;
break;
case VID_PLL_DIV_3p25:
shift_val = 0x66cc;
shift_sel = 2;
break;
default:
pr_info("Error: clocks_set_vid_clk_div: Invalid parameter\n");
break;
}
if (shift_val == 0xffff) { /* if divide by 1 */
hd21_set_reg_bits(reg_vid_pll, 1, 18, 1);
} else {
hd21_set_reg_bits(reg_vid_pll, 0, 18, 1);
hd21_set_reg_bits(reg_vid_pll, 0, 16, 2);
hd21_set_reg_bits(reg_vid_pll, 0, 15, 1);
hd21_set_reg_bits(reg_vid_pll, 0, 0, 15);
hd21_set_reg_bits(reg_vid_pll, shift_sel, 16, 2);
hd21_set_reg_bits(reg_vid_pll, 1, 15, 1);
hd21_set_reg_bits(reg_vid_pll, shift_val, 0, 15);
hd21_set_reg_bits(reg_vid_pll, 0, 15, 1);
}
/* Enable the final output clock */
hd21_set_reg_bits(reg_vid_pll, 1, 19, 1);
}
static void set_vid_clk_div(struct hdmitx_dev *hdev, u32 div)
{
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 0, 16, 3);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_DIV, div - 1, 0, 8);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 7, 0, 3);
}
static void set_hdmitx_enc_div(struct hdmitx_dev *hdev, u32 div)
{
div = check_div(div);
if (div == -1)
return;
hd21_set_reg_bits(CLKCTRL_VID_CLK0_DIV, div, 12, 4);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL2, 1, 3, 1);
}
static void set_hdmitx_fe_div(struct hdmitx_dev *hdev, u32 div)
{
div = check_div(div);
if (div == -1)
return;
hd21_set_reg_bits(CLKCTRL_ENC0_HDMI_CLK_CTRL, div, 20, 4);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL2, 1, 9, 1);
}
static void set_hdmitx_pnx_div(struct hdmitx_dev *hdev, u32 div)
{
div = check_div(div);
if (div == -1)
return;
hd21_set_reg_bits(CLKCTRL_ENC0_HDMI_CLK_CTRL, div, 24, 4);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL2, 1, 10, 1);
}
static void set_hdmitx_pixel_div(struct hdmitx_dev *hdev, u32 div)
{
div = check_div(div);
if (div == -1)
return;
hd21_set_reg_bits(CLKCTRL_ENC0_HDMI_CLK_CTRL, div, 16, 4);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL2, 1, 5, 1);
}
/* mode hpll_clk_out od1 od2(PHY) od3
* vid_pll_div vid_clk_div hdmi_tx_pixel_div encp_div enci_div
*/
static struct hw_enc_clk_val_group setting_enc_clk_val_24[] = {
{{HDMI_7_720x480i60_16x9,
HDMI_6_720x480i60_4x3,
HDMI_22_720x576i50_16x9,
HDMI_21_720x576i50_4x3,
HDMI_18_720x576p50_16x9,
HDMI_17_720x576p50_4x3,
HDMI_3_720x480p60_16x9,
HDMI_2_720x480p60_4x3,
HDMI_VIC_END},
4324320, 4, 4, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_19_1280x720p50_16x9,
HDMI_4_1280x720p60_16x9,
HDMI_5_1920x1080i60_16x9,
HDMI_20_1920x1080i50_16x9,
HDMI_VIC_END},
5940000, 4, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_16_1920x1080p60_16x9,
HDMI_31_1920x1080p50_16x9,
HDMI_VIC_END},
5940000, 4, 1, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_34_1920x1080p30_16x9,
HDMI_32_1920x1080p24_16x9,
HDMI_33_1920x1080p25_16x9,
HDMI_VIC_END},
5940000, 4, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_89_2560x1080p50_64x27,
HDMI_VIC_END},
3712500, 2, 1, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_90_2560x1080p60_64x27,
HDMI_VIC_END},
3960000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_95_3840x2160p30_16x9,
HDMI_94_3840x2160p25_16x9,
HDMI_93_3840x2160p24_16x9,
HDMI_63_1920x1080p120_16x9,
HDMI_98_4096x2160p24_256x135,
HDMI_99_4096x2160p25_256x135,
HDMI_100_4096x2160p30_256x135,
HDMI_VIC_END},
5940000, 2, 1, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_97_3840x2160p60_16x9,
HDMI_96_3840x2160p50_16x9,
HDMI_102_4096x2160p60_256x135,
HDMI_101_4096x2160p50_256x135,
HDMI_VIC_END},
5940000, 1, 1, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_VIC_FAKE,
HDMI_VIC_END},
3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
/* pll setting for VESA modes */
{{HDMIV_640x480p60hz, /* 4.028G / 16 = 251.75M */
HDMI_VIC_END},
4028000, 4, 4, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_800x480p60hz,
HDMI_VIC_END},
4761600, 4, 4, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_800x600p60hz,
HDMI_VIC_END},
3200000, 4, 2, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_852x480p60hz,
HDMIV_854x480p60hz,
HDMI_VIC_END},
4838400, 4, 4, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1024x600p60hz,
HDMI_VIC_END},
4032000, 4, 2, 1, VID_PLL_DIV_5, 1, 2, 2, 1, 1},
{{HDMIV_1024x768p60hz,
HDMI_VIC_END},
5200000, 4, 2, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1280x768p60hz,
HDMI_VIC_END},
3180000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1280x800p60hz,
HDMI_VIC_END},
5680000, 4, 2, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1152x864p75hz,
HDMIV_1280x960p60hz,
HDMIV_1280x1024p60hz,
HDMIV_1600x900p60hz,
HDMI_VIC_END},
4320000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1600x1200p60hz,
HDMI_VIC_END},
3240000, 2, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1360x768p60hz,
HDMIV_1366x768p60hz,
HDMI_VIC_END},
3420000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1400x1050p60hz,
HDMI_VIC_END},
4870000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1440x900p60hz,
HDMI_VIC_END},
4260000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1440x2560p60hz,
HDMI_VIC_END},
4897000, 2, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1680x1050p60hz,
HDMI_VIC_END},
5850000, 4, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_1920x1200p60hz,
HDMI_VIC_END},
3865000, 2, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_2160x1200p90hz,
HDMI_VIC_END},
5371100, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMIV_2560x1600p60hz,
HDMI_VIC_END},
3485000, 1, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_3440x1440p60hz,
HDMI_VIC_END},
3197500, 1, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
{{HDMIV_2400x1200p90hz,
HDMI_VIC_END},
5600000, 2, 1, 1, VID_PLL_DIV_5, 2, 1, 1, 1, 1},
};
/* For colordepth 10bits */
static struct hw_enc_clk_val_group setting_enc_clk_val_30[] = {
{{HDMI_7_720x480i60_16x9,
HDMI_6_720x480i60_4x3,
HDMI_22_720x576i50_16x9,
HDMI_21_720x576i50_4x3,
HDMI_18_720x576p50_16x9,
HDMI_17_720x576p50_4x3,
HDMI_3_720x480p60_16x9,
HDMI_2_720x480p60_4x3,
HDMI_VIC_END},
5405400, 4, 4, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_19_1280x720p50_16x9,
HDMI_4_1280x720p60_16x9,
HDMI_5_1920x1080i60_16x9,
HDMI_20_1920x1080i50_16x9,
HDMI_VIC_END},
3712500, 4, 1, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_16_1920x1080p60_16x9,
HDMI_31_1920x1080p50_16x9,
HDMI_VIC_END},
3712500, 2, 1, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_34_1920x1080p30_16x9,
HDMI_32_1920x1080p24_16x9,
HDMI_33_1920x1080p25_16x9,
HDMI_VIC_END},
3712500, 2, 2, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_89_2560x1080p50_64x27,
HDMI_VIC_END},
4640625, 2, 1, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_90_2560x1080p60_64x27,
HDMI_VIC_END},
4950000, 1, 2, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_95_3840x2160p30_16x9,
HDMI_94_3840x2160p25_16x9,
HDMI_93_3840x2160p24_16x9,
HDMI_63_1920x1080p120_16x9,
HDMI_98_4096x2160p24_256x135,
HDMI_99_4096x2160p25_256x135,
HDMI_100_4096x2160p30_256x135,
HDMI_VIC_END},
3712500, 1, 1, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_97_3840x2160p60_16x9,
HDMI_96_3840x2160p50_16x9,
HDMI_102_4096x2160p60_256x135,
HDMI_101_4096x2160p50_256x135,
HDMI_VIC_END},
3712500, 1, 1, 2, VID_PLL_DIV_6p25, 1, 1, 1, 1, 1},
{{HDMI_VIC_FAKE,
HDMI_VIC_END},
3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
};
/* For colordepth 12bits */
static struct hw_enc_clk_val_group setting_enc_clk_val_36[] = {
{{HDMI_7_720x480i60_16x9,
HDMI_6_720x480i60_4x3,
HDMI_22_720x576i50_16x9,
HDMI_21_720x576i50_4x3,
HDMI_18_720x576p50_16x9,
HDMI_17_720x576p50_4x3,
HDMI_3_720x480p60_16x9,
HDMI_2_720x480p60_4x3,
HDMI_VIC_END},
3243240, 4, 2, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_19_1280x720p50_16x9,
HDMI_4_1280x720p60_16x9,
HDMI_5_1920x1080i60_16x9,
HDMI_20_1920x1080i50_16x9,
HDMI_VIC_END},
4455000, 4, 1, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_16_1920x1080p60_16x9,
HDMI_31_1920x1080p50_16x9,
HDMI_VIC_END},
4455000, 2, 1, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_34_1920x1080p30_16x9,
HDMI_32_1920x1080p24_16x9,
HDMI_33_1920x1080p25_16x9,
HDMI_VIC_END},
4455000, 2, 2, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_89_2560x1080p50_64x27,
HDMI_VIC_END},
5568750, 2, 1, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_90_2560x1080p60_64x27,
HDMI_VIC_END},
5940000, 1, 2, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_95_3840x2160p30_16x9,
HDMI_94_3840x2160p25_16x9,
HDMI_93_3840x2160p24_16x9,
HDMI_63_1920x1080p120_16x9,
HDMI_98_4096x2160p24_256x135,
HDMI_99_4096x2160p25_256x135,
HDMI_100_4096x2160p30_256x135,
HDMI_VIC_END},
4455000, 1, 1, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_102_4096x2160p60_256x135,
HDMI_101_4096x2160p50_256x135,
HDMI_97_3840x2160p60_16x9,
HDMI_96_3840x2160p50_16x9,
HDMI_VIC_END},
4455000, 1, 1, 2, VID_PLL_DIV_7p5, 1, 1, 1, 1, 1},
{{HDMI_VIC_FAKE,
HDMI_VIC_END},
3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
};
/* For 3D Frame Packing Clock Setting
* mode hpll_clk_out od1 od2(PHY) od3
* vid_pll_div vid_clk_div hdmi_tx_pixel_div encp_div enci_div
*/
static struct hw_enc_clk_val_group setting_3dfp_enc_clk_val[] = {
{{HDMI_16_1920x1080p60_16x9,
HDMI_31_1920x1080p50_16x9,
HDMI_VIC_END},
5940000, 2, 1, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
{{HDMI_19_1280x720p50_16x9,
HDMI_4_1280x720p60_16x9,
HDMI_34_1920x1080p30_16x9,
HDMI_32_1920x1080p24_16x9,
HDMI_33_1920x1080p25_16x9,
HDMI_VIC_END},
5940000, 2, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
/* NO 2160p mode*/
{{HDMI_VIC_FAKE,
HDMI_VIC_END},
3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, 1, 1},
};
static void hdmitx21_set_clk_(struct hdmitx_dev *hdev)
{
int i = 0;
int j = 0;
struct hw_enc_clk_val_group *p_enc = NULL;
enum hdmi_vic vic = hdev->para->timing.vic;
enum hdmi_colorspace cs = hdev->para->cs;
enum hdmi_color_depth cd = hdev->para->cd;
struct hw_enc_clk_val_group tmp_clk = {0};
/* YUV 422 always use 24B mode */
if (cs == HDMI_COLORSPACE_YUV422)
cd = COLORDEPTH_24B;
if (hdev->flag_3dfp) {
p_enc = &setting_3dfp_enc_clk_val[0];
for (j = 0; j < sizeof(setting_3dfp_enc_clk_val)
/ sizeof(struct hw_enc_clk_val_group); j++) {
for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i]
!= HDMI_VIC_END)); i++) {
if (vic == p_enc[j].group[i])
goto next;
}
}
if (j == sizeof(setting_3dfp_enc_clk_val)
/ sizeof(struct hw_enc_clk_val_group)) {
pr_info("Not find VIC = %d for hpll setting\n", vic);
return;
}
} else if (cd == COLORDEPTH_24B) {
p_enc = &setting_enc_clk_val_24[0];
for (j = 0; j < sizeof(setting_enc_clk_val_24)
/ sizeof(struct hw_enc_clk_val_group); j++) {
for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i]
!= HDMI_VIC_END)); i++) {
if (vic == p_enc[j].group[i])
goto next;
}
}
if (j == sizeof(setting_enc_clk_val_24)
/ sizeof(struct hw_enc_clk_val_group)) {
pr_info("Not find VIC = %d for hpll setting\n", vic);
return;
}
} else if (cd == COLORDEPTH_30B) {
p_enc = &setting_enc_clk_val_30[0];
for (j = 0; j < sizeof(setting_enc_clk_val_30)
/ sizeof(struct hw_enc_clk_val_group); j++) {
for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i]
!= HDMI_VIC_END)); i++) {
if (vic == p_enc[j].group[i])
goto next;
}
}
if (j == sizeof(setting_enc_clk_val_30) /
sizeof(struct hw_enc_clk_val_group)) {
pr_info("Not find VIC = %d for hpll setting\n", vic);
return;
}
} else if (cd == COLORDEPTH_36B) {
p_enc = &setting_enc_clk_val_36[0];
for (j = 0; j < sizeof(setting_enc_clk_val_36)
/ sizeof(struct hw_enc_clk_val_group); j++) {
for (i = 0; ((i < GROUP_MAX) && (p_enc[j].group[i]
!= HDMI_VIC_END)); i++) {
if (vic == p_enc[j].group[i])
goto next;
}
}
if (j == sizeof(setting_enc_clk_val_36) /
sizeof(struct hw_enc_clk_val_group)) {
pr_info("Not find VIC = %d for hpll setting\n", vic);
return;
}
} else {
pr_info("not support colordepth 48bits\n");
return;
}
next:
memcpy(&tmp_clk, &p_enc[j], sizeof(struct hw_enc_clk_val_group));
if (cs == HDMI_COLORSPACE_YUV420) {
/* adjust the sub-clock under Y420 */
if (cd == COLORDEPTH_24B)
tmp_clk.od1 = 2;
tmp_clk.od3 = 1;
tmp_clk.pnx_div = 2;
tmp_clk.pixel_div = 2;
}
pr_info("hdmitx sub-clock: %d %d %d %d %d %d %d %d %d %d\n",
tmp_clk.hpll_clk_out, tmp_clk.od1, tmp_clk.od2, tmp_clk.od3,
tmp_clk.vid_pll_div, tmp_clk.vid_clk_div, tmp_clk.enc_div,
tmp_clk.fe_div, tmp_clk.pnx_div, tmp_clk.pixel_div);
set_hpll_clk_out(tmp_clk.hpll_clk_out);
if (cd == COLORDEPTH_24B && hdev->sspll)
set_hpll_sspll(vic);
set_hpll_od1(tmp_clk.od1);
set_hpll_od2(tmp_clk.od2);
set_hpll_od3(tmp_clk.od3);
clocks_set_vid_clk_div_for_hdmi(tmp_clk.vid_pll_div);
pr_info("j = %d vid_clk_div = %d\n", j, tmp_clk.vid_clk_div);
set_vid_clk_div(hdev, tmp_clk.vid_clk_div);
set_hdmitx_enc_div(hdev, tmp_clk.enc_div);
set_hdmitx_fe_div(hdev, tmp_clk.fe_div);
set_hdmitx_pnx_div(hdev, tmp_clk.pnx_div);
set_hdmitx_pixel_div(hdev, tmp_clk.pixel_div);
hdmitx_enable_encp_clk(hdev);
//configure crt_video V1: in_sel=vid_pll_clk(0),div_n=xd)
set_crt_video_enc(0, 0, 1);
if (hdev->enc_idx == 2)
set_crt_video_enc2(0, 0, 1);
}
static int likely_frac_rate_mode(char *m)
{
if (strstr(m, "24hz") || strstr(m, "30hz") || strstr(m, "60hz") ||
strstr(m, "120hz") || strstr(m, "240hz"))
return 1;
else
return 0;
}
static void hdmitx_check_frac_rate(struct hdmitx_dev *hdev)
{
struct hdmi_format_para *para = hdev->para;
frac_rate = hdev->frac_rate_policy;
if (para && para->timing.name && likely_frac_rate_mode(para->timing.name)) {
;
} else {
pr_info("this mode doesn't have frac_rate\n");
frac_rate = 0;
}
pr_info("frac_rate = %d\n", hdev->frac_rate_policy);
}
void hdmitx21_set_clk(struct hdmitx_dev *hdev)
{
hdmitx_check_frac_rate(hdev);
pr_info("%s[%d]\n", __func__, __LINE__);
hdmitx21_set_clk_(hdev);
}
void hdmitx21_disable_clk(struct hdmitx_dev *hdev)
{
/* cts_encp/enci_clk */
if (hdev->para->hdmitx_vinfo.viu_mux == VIU_MUX_ENCI)
hdmitx_disable_enci_clk(hdev);
else
hdmitx_disable_encp_clk(hdev);
/* hdmi_tx_pixel_clk */
hdmitx_disable_tx_pixel_clk(hdev);
}
//===============================================================
// CRT_VIDEO SETTING FUNCTIONS
//===============================================================
static void set_crt_video_enc(u32 vidx, u32 in_sel, u32 div_n)
//input :
//vidx : 0:V1; 1:V2; there have 2 parallel set clock generator: V1 and V2
//in_sel : 0:vid_pll_clk; 1:fclk_div4; 2:flck_div3; 3:fclk_div5;
// 4:vid_pll2_clk; 5:fclk_div7; 6:vid_pll2_clk;
//div_n : clock divider for enci_clk/encp_clk/encl_clk/vda_clk/hdmi_tx_pixel_clk;
{
if (vidx == 0) { //V1
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 0, 19, 1); //[19] -disable clk_div0
udelay(2);
// [18:16] - cntl_clk_in_sel
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, in_sel, 16, 3);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_DIV, div_n - 1, 0, 8); // [7:0] - cntl_xd0
udelay(5);
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 1, 19, 1); //[19] -enable clk_div0
} else { //V2
hd21_set_reg_bits(CLKCTRL_VIID_CLK0_CTRL, 0, 19, 1); //[19] -disable clk_div0
udelay(2);
// [18:16] - cntl_clk_in_sel
hd21_set_reg_bits(CLKCTRL_VIID_CLK0_CTRL, in_sel, 16, 3);
hd21_set_reg_bits(CLKCTRL_VIID_CLK0_DIV, div_n - 1, 0, 8); // [7:0] - cntl_xd0
udelay(5);
hd21_set_reg_bits(CLKCTRL_VIID_CLK0_CTRL, 1, 19, 1); //[19] -enable clk_div0
}
}
//===============================================================
// CRT_VIDEO SETTING FUNCTIONS
//===============================================================
static void set_crt_video_enc2(u32 vidx, u32 in_sel, u32 div_n)
//input :
//vidx : 0:V1; 1:V2; there have 2 parallel set clock generator: V1 and V2
//in_sel : 0:vid_pll_clk; 1:fclk_div4; 2:flck_div3; 3:fclk_div5;
// 4:vid_pll2_clk; 5:fclk_div7; 6:vid_pll2_clk;
//div_n : clock divider for enci_clk/encp_clk/encl_clk/vda_clk/hdmi_tx_pixel_clk;
{
if (vidx == 0) { //V1
hd21_set_reg_bits(CLKCTRL_VID_CLK2_CTRL, 0, 19, 1); //[19] -disable clk_div0
udelay(2);
// [18:16] - cntl_clk_in_sel
hd21_set_reg_bits(CLKCTRL_VID_CLK2_CTRL, in_sel, 16, 3);
hd21_set_reg_bits(CLKCTRL_VID_CLK2_DIV, (div_n - 1), 0, 8); // [7:0] - cntl_xd0
udelay(5);
hd21_set_reg_bits(CLKCTRL_VID_CLK2_CTRL, 1, 19, 1); //[19] -enable clk_div0
} else { //V2
hd21_set_reg_bits(CLKCTRL_VIID_CLK2_CTRL, 0, 19, 1); //[19] -disable clk_div0
udelay(2);
// [18:16] - cntl_clk_in_sel
hd21_set_reg_bits(CLKCTRL_VIID_CLK2_CTRL, in_sel, 16, 3);
// [7:0] - cntl_xd0
hd21_set_reg_bits(CLKCTRL_VIID_CLK2_DIV, (div_n - 1), 0, 8);
udelay(5);
hd21_set_reg_bits(CLKCTRL_VIID_CLK2_CTRL, 1, 19, 1); //[19] -enable clk_div0
}
}