blob: 6270eeccaddbe7f5c21b10c01b4016a5f9f7f33f [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
*
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
*
*/
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#include <linux/clk.h>
#ifdef CONFIG_AMLOGIC_VPU
#include <linux/amlogic/media/vpu/vpu.h>
#endif
#include "lcd_reg.h"
#include "lcd_common.h"
#include "lcd_clk_config.h"
#include "lcd_clk_ctrl.h"
/* for lcd clk init */
spinlock_t lcd_clk_lock;
struct lcd_clk_config_s *get_lcd_clk_config(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (!pdrv->clk_conf) {
LCDERR("[%d]: %s: clk_config is null\n", pdrv->index, __func__);
return NULL;
}
cconf = (struct lcd_clk_config_s *)pdrv->clk_conf;
if (!cconf->data) {
LCDERR("[%d]: %s: clk config data is null\n",
pdrv->index, __func__);
return NULL;
}
return cconf;
}
/* ****************************************************
* lcd pll & clk operation
* ****************************************************
*/
static unsigned int error_abs(unsigned int a, unsigned int b)
{
if (a >= b)
return (a - b);
else
return (b - a);
}
#define PLL_CLK_CHECK_MAX 2000000 /* Hz */
static int lcd_clk_msr_check(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int encl_clk_msr;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return 0;
if (cconf->data->enc_clk_msr_id == -1)
return 0;
encl_clk_msr = lcd_encl_clk_msr(pdrv);
if (error_abs((cconf->fout * 1000), encl_clk_msr) >= PLL_CLK_CHECK_MAX) {
LCDERR("[%d]: %s: expected:%d, msr:%d\n",
pdrv->index, __func__,
(cconf->fout * 1000), encl_clk_msr);
return -1;
}
return 0;
}
static int lcd_pll_ss_level_generate(unsigned int *data, unsigned int level, unsigned int step)
{
unsigned int max = 10, val;
unsigned int dep_sel, str_m, temp, min;
if (!data)
return -1;
val = level * 1000;
min = val;
for (dep_sel = 1; dep_sel <= max; dep_sel++) { //dep_sel
for (str_m = 1; str_m <= max; str_m++) { //str_m
temp = error_abs((dep_sel * str_m * step), val);
if (min > temp) {
min = temp;
data[0] = dep_sel;
data[1] = str_m;
}
}
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s: dep_sel=%d, str_m=%d, error=%d\n", __func__, data[0], data[1], min);
return 0;
}
static int lcd_pll_wait_lock(unsigned int reg, unsigned int lock_bit)
{
unsigned int pll_lock;
int wait_loop = PLL_WAIT_LOCK_CNT; /* 200 */
int ret = 0;
do {
udelay(50);
pll_lock = lcd_ana_getb(reg, lock_bit, 1);
wait_loop--;
} while ((pll_lock == 0) && (wait_loop > 0));
if (pll_lock == 0)
ret = -1;
LCDPR("%s: pll_lock=%d, wait_loop=%d\n",
__func__, pll_lock, (PLL_WAIT_LOCK_CNT - wait_loop));
return ret;
}
#define PLL_WAIT_LOCK_CNT_G12A 1000
static int lcd_pll_wait_lock_g12a(int path)
{
unsigned int pll_ctrl, pll_ctrl3, pll_ctrl6;
unsigned int pll_lock;
int wait_loop = PLL_WAIT_LOCK_CNT_G12A; /* 200 */
int ret = 0;
if (path) {
pll_ctrl = HHI_GP0_PLL_CNTL0;
pll_ctrl3 = HHI_GP0_PLL_CNTL3;
pll_ctrl6 = HHI_GP0_PLL_CNTL6;
} else {
pll_ctrl = HHI_HDMI_PLL_CNTL0;
pll_ctrl3 = HHI_HDMI_PLL_CNTL3;
pll_ctrl6 = HHI_HDMI_PLL_CNTL6;
}
do {
udelay(50);
pll_lock = lcd_ana_getb(pll_ctrl, 31, 1);
wait_loop--;
} while ((pll_lock != 1) && (wait_loop > 0));
if (pll_lock == 1) {
goto pll_lock_end_g12a;
} else {
LCDPR("path: %d, pll try 1, lock: %d\n", path, pll_lock);
lcd_ana_setb(pll_ctrl3, 1, 31, 1);
wait_loop = PLL_WAIT_LOCK_CNT_G12A;
do {
udelay(50);
pll_lock = lcd_ana_getb(pll_ctrl, 31, 1);
wait_loop--;
} while ((pll_lock != 1) && (wait_loop > 0));
}
if (pll_lock == 1) {
goto pll_lock_end_g12a;
} else {
LCDPR("path: %d, pll try 2, lock: %d\n", path, pll_lock);
lcd_ana_write(pll_ctrl6, 0x55540000);
wait_loop = PLL_WAIT_LOCK_CNT_G12A;
do {
udelay(50);
pll_lock = lcd_ana_getb(pll_ctrl, 31, 1);
wait_loop--;
} while ((pll_lock != 1) && (wait_loop > 0));
}
if (pll_lock != 1)
ret = -1;
pll_lock_end_g12a:
LCDPR("%s: path=%d, pll_lock=%d, wait_loop=%d\n",
__func__, path, pll_lock, (PLL_WAIT_LOCK_CNT_G12A - wait_loop));
return ret;
}
static void lcd_set_gp0_pll_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
pll_ctrl = ((1 << LCD_PLL_EN_GP0_G12A) |
(cconf->pll_n << LCD_PLL_N_GP0_G12A) |
(cconf->pll_m << LCD_PLL_M_GP0_G12A) |
(cconf->pll_od1_sel << LCD_PLL_OD_GP0_G12A));
pll_ctrl1 = (cconf->pll_frac << 0);
if (cconf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl3 = 0x6a285c00;
pll_ctrl4 = 0x65771290;
pll_ctrl6 = 0x56540000;
} else {
pll_ctrl3 = 0x48681c00;
pll_ctrl4 = 0x33771290;
pll_ctrl6 = 0x56540000;
}
set_gp0_pll_retry_g12a:
lcd_ana_write(HHI_GP0_PLL_CNTL0, pll_ctrl);
lcd_ana_write(HHI_GP0_PLL_CNTL1, pll_ctrl1);
lcd_ana_write(HHI_GP0_PLL_CNTL2, 0x00);
lcd_ana_write(HHI_GP0_PLL_CNTL3, pll_ctrl3);
lcd_ana_write(HHI_GP0_PLL_CNTL4, pll_ctrl4);
lcd_ana_write(HHI_GP0_PLL_CNTL5, 0x39272000);
lcd_ana_write(HHI_GP0_PLL_CNTL6, pll_ctrl6);
lcd_ana_setb(HHI_GP0_PLL_CNTL0, 1, LCD_PLL_RST_GP0_G12A, 1);
udelay(100);
lcd_ana_setb(HHI_GP0_PLL_CNTL0, 0, LCD_PLL_RST_GP0_G12A, 1);
ret = lcd_pll_wait_lock_g12a(1);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_gp0_pll_retry_g12a;
LCDERR("gp0_pll lock failed\n");
}
}
static void lcd_set_hpll_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
pll_ctrl = ((1 << LCD_PLL_EN_HPLL_G12A) |
(1 << 25) | /* clk out gate */
(cconf->pll_n << LCD_PLL_N_HPLL_G12A) |
(cconf->pll_m << LCD_PLL_M_HPLL_G12A) |
(cconf->pll_od1_sel << LCD_PLL_OD1_HPLL_G12A) |
(cconf->pll_od2_sel << LCD_PLL_OD2_HPLL_G12A) |
(cconf->pll_od3_sel << LCD_PLL_OD3_HPLL_G12A));
pll_ctrl1 = (cconf->pll_frac << 0);
if (cconf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl3 = 0x6a285c00;
pll_ctrl4 = 0x65771290;
pll_ctrl6 = 0x56540000;
} else {
pll_ctrl3 = 0x48681c00;
pll_ctrl4 = 0x33771290;
pll_ctrl6 = 0x56540000;
}
set_hpll_pll_retry_g12a:
lcd_ana_write(HHI_HDMI_PLL_CNTL0, pll_ctrl);
lcd_ana_write(HHI_HDMI_PLL_CNTL1, pll_ctrl1);
lcd_ana_write(HHI_HDMI_PLL_CNTL2, 0x00);
lcd_ana_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3);
lcd_ana_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4);
lcd_ana_write(HHI_HDMI_PLL_CNTL5, 0x39272000);
lcd_ana_write(HHI_HDMI_PLL_CNTL6, pll_ctrl6);
lcd_ana_setb(HHI_HDMI_PLL_CNTL0, 1, LCD_PLL_RST_HPLL_G12A, 1);
udelay(100);
lcd_ana_setb(HHI_HDMI_PLL_CNTL0, 0, LCD_PLL_RST_HPLL_G12A, 1);
ret = lcd_pll_wait_lock_g12a(0);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_hpll_pll_retry_g12a;
LCDERR("hpll lock failed\n");
}
}
static void lcd_set_gp0_pll_g12b(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
pll_ctrl = ((1 << LCD_PLL_EN_GP0_G12A) |
(cconf->pll_n << LCD_PLL_N_GP0_G12A) |
(cconf->pll_m << LCD_PLL_M_GP0_G12A) |
(cconf->pll_od1_sel << LCD_PLL_OD_GP0_G12A));
pll_ctrl1 = (cconf->pll_frac << 0);
if (cconf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl3 = 0x6a285c00;
pll_ctrl4 = 0x65771290;
pll_ctrl6 = 0x56540000;
} else {
pll_ctrl3 = 0x48681c00;
pll_ctrl4 = 0x33771290;
pll_ctrl6 = 0x56540000;
}
set_gp0_pll_retry_g12b:
lcd_ana_write(HHI_GP0_PLL_CNTL0, pll_ctrl);
lcd_ana_write(HHI_GP0_PLL_CNTL1, pll_ctrl1);
lcd_ana_write(HHI_GP0_PLL_CNTL2, 0x00);
lcd_ana_write(HHI_GP0_PLL_CNTL3, pll_ctrl3);
lcd_ana_write(HHI_GP0_PLL_CNTL4, pll_ctrl4);
lcd_ana_write(HHI_GP0_PLL_CNTL5, 0x39272000);
lcd_ana_write(HHI_GP0_PLL_CNTL6, pll_ctrl6);
lcd_ana_setb(HHI_GP0_PLL_CNTL0, 1, LCD_PLL_RST_GP0_G12A, 1);
udelay(100);
lcd_ana_setb(HHI_GP0_PLL_CNTL0, 0, LCD_PLL_RST_GP0_G12A, 1);
ret = lcd_pll_wait_lock(HHI_GP0_PLL_CNTL0, LCD_PLL_LOCK_GP0_G12A);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_gp0_pll_retry_g12b;
LCDERR("gp0_pll lock failed\n");
}
}
static void lcd_set_hpll_g12b(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
pll_ctrl = ((1 << LCD_PLL_EN_HPLL_G12A) |
(1 << 25) | /* clk out gate */
(cconf->pll_n << LCD_PLL_N_HPLL_G12A) |
(cconf->pll_m << LCD_PLL_M_HPLL_G12A) |
(cconf->pll_od1_sel << LCD_PLL_OD1_HPLL_G12A) |
(cconf->pll_od2_sel << LCD_PLL_OD2_HPLL_G12A) |
(cconf->pll_od3_sel << LCD_PLL_OD3_HPLL_G12A));
pll_ctrl1 = (cconf->pll_frac << 0);
if (cconf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl3 = 0x6a285c00;
pll_ctrl4 = 0x65771290;
pll_ctrl6 = 0x56540000;
} else {
pll_ctrl3 = 0x48681c00;
pll_ctrl4 = 0x33771290;
pll_ctrl6 = 0x56540000;
}
set_hpll_pll_retry_g12b:
lcd_ana_write(HHI_HDMI_PLL_CNTL0, pll_ctrl);
lcd_ana_write(HHI_HDMI_PLL_CNTL1, pll_ctrl1);
lcd_ana_write(HHI_HDMI_PLL_CNTL2, 0x00);
lcd_ana_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3);
lcd_ana_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4);
lcd_ana_write(HHI_HDMI_PLL_CNTL5, 0x39272000);
lcd_ana_write(HHI_HDMI_PLL_CNTL6, pll_ctrl6);
lcd_ana_setb(HHI_HDMI_PLL_CNTL0, 1, LCD_PLL_RST_HPLL_G12A, 1);
udelay(100);
lcd_ana_setb(HHI_HDMI_PLL_CNTL0, 0, LCD_PLL_RST_HPLL_G12A, 1);
ret = lcd_pll_wait_lock(HHI_HDMI_PLL_CNTL0, LCD_PLL_LOCK_HPLL_G12A);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_hpll_pll_retry_g12b;
LCDERR("hpll lock failed\n");
}
}
static void lcd_pll_ss_enable_tl1(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl2;
unsigned int level, flag;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
level = cconf->ss_level;
pll_ctrl2 = lcd_ana_read(HHI_TCON_PLL_CNTL2);
if (status) {
if (level > 0)
flag = 1;
else
flag = 0;
} else {
flag = 0;
}
if (flag) {
cconf->ss_en = 1;
pll_ctrl2 |= (1 << 15);
LCDPR("pll ss enable: %s\n", lcd_ss_level_table_tl1[level]);
} else {
cconf->ss_en = 0;
pll_ctrl2 &= ~(1 << 15);
LCDPR("pll ss disable\n");
}
lcd_ana_write(HHI_TCON_PLL_CNTL2, pll_ctrl2);
}
static void lcd_set_pll_ss_level_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int level, pll_ctrl2;
unsigned int dep_sel, str_m;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
level = cconf->ss_level;
pll_ctrl2 = lcd_ana_read(HHI_TCON_PLL_CNTL2);
pll_ctrl2 &= ~((1 << 15) | (0xf << 16) | (0xf << 28));
if (level > 0) {
cconf->ss_en = 1;
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));
} else {
cconf->ss_en = 0;
}
lcd_ana_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(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl2;
unsigned int freq, mode;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
freq = cconf->ss_freq;
mode = cconf->ss_mode;
pll_ctrl2 = lcd_ana_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_ana_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 aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1;
unsigned int tcon_div_sel;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
tcon_div_sel = cconf->pll_tcon_div_sel;
pll_ctrl = ((0x3 << 17) | /* gate ctrl */
(tcon_div[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) |
(tcon_div[tcon_div_sel][0] << 22) |
(tcon_div[tcon_div_sel][1] << 21) |
((1 << 20) | /* sdm_en */
(cconf->pll_frac << 0));
set_pll_retry_tl1:
lcd_ana_write(HHI_TCON_PLL_CNTL0, pll_ctrl);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_EN_TL1, 1);
udelay(10);
lcd_ana_write(HHI_TCON_PLL_CNTL1, pll_ctrl1);
udelay(10);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x0000110c);
udelay(10);
lcd_ana_write(HHI_TCON_PLL_CNTL3, 0x10051400);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL4, 0x0100c0, 0, 24);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL4, 0x8300c0, 0, 24);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1);
udelay(10);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x0000300c);
ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_pll_retry_tl1;
LCDERR("hpll lock failed\n");
} else {
udelay(100);
lcd_ana_setb(HHI_TCON_PLL_CNTL2, 1, 5, 1);
}
if (cconf->ss_level > 0) {
lcd_set_pll_ss_level_tl1(pdrv);
lcd_set_pll_ss_advance_tl1(pdrv);
}
}
static void lcd_pll_ss_enable_t7(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl2, offset;
unsigned int level, flag;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
level = cconf->ss_level;
offset = cconf->pll_offset;
pll_ctrl2 = lcd_ana_read(ANACTRL_TCON_PLL0_CNTL2 + offset);
if (status) {
if (level > 0)
flag = 1;
else
flag = 0;
} else {
flag = 0;
}
if (flag) {
cconf->ss_en = 1;
pll_ctrl2 |= (1 << 15);
LCDPR("[%d]: pll ss enable: %dppm\n", pdrv->index, (level * 1000));
} else {
cconf->ss_en = 0;
pll_ctrl2 &= ~(1 << 15);
LCDPR("[%d]: pll ss disable\n", pdrv->index);
}
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, pll_ctrl2);
}
static void lcd_set_pll_ss_level_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl2, offset;
unsigned int level, dep_sel, str_m;
unsigned int data[2] = {0, 0};
int ret;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
level = cconf->ss_level;
offset = cconf->pll_offset;
pll_ctrl2 = lcd_ana_read(ANACTRL_TCON_PLL0_CNTL2 + offset);
pll_ctrl2 &= ~((1 << 15) | (0xf << 16) | (0xf << 28));
if (level > 0) {
cconf->ss_en = 1;
ret = lcd_pll_ss_level_generate(data, level, 500);
if (ret == 0) {
dep_sel = data[0];
str_m = data[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));
}
} else {
cconf->ss_en = 0;
}
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, pll_ctrl2);
if (level > 0) {
LCDPR("[%d]: set pll spread spectrum: %dppm\n",
pdrv->index, (level * 1000));
} else {
LCDPR("[%d]: set pll spread spectrum: disable\n", pdrv->index);
}
}
static void lcd_set_pll_ss_advance_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl2, offset;
unsigned int freq, mode;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
freq = cconf->ss_freq;
mode = cconf->ss_mode;
offset = cconf->pll_offset;
pll_ctrl2 = lcd_ana_read(ANACTRL_TCON_PLL0_CNTL2 + offset);
pll_ctrl2 &= ~(0x7 << 24); /* ss_freq */
pll_ctrl2 |= (freq << 24);
pll_ctrl2 &= ~(0x3 << 22); /* ss_mode */
pll_ctrl2 |= (mode << 22);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, pll_ctrl2);
LCDPR("[%d]: set pll spread spectrum: freq=%d, mode=%d\n",
pdrv->index, freq, mode);
}
static void lcd_set_pll_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_stts, offset;
unsigned int tcon_div_sel;
int ret, cnt = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
tcon_div_sel = cconf->pll_tcon_div_sel;
pll_ctrl = ((0x3 << 17) | /* gate ctrl */
(tcon_div[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_T7) |
(cconf->pll_od2_sel << LCD_PLL_OD2_T7) |
(cconf->pll_od1_sel << LCD_PLL_OD1_T7));
pll_ctrl1 = (1 << 28) |
(tcon_div[tcon_div_sel][0] << 22) |
(tcon_div[tcon_div_sel][1] << 21) |
((1 << 20) | /* sdm_en */
(cconf->pll_frac << 0));
offset = cconf->pll_offset;
switch (cconf->pll_id) {
case 1:
pll_stts = ANACTRL_TCON_PLL1_STS;
break;
case 2:
pll_stts = ANACTRL_TCON_PLL2_STS;
break;
case 0:
default:
pll_stts = ANACTRL_TCON_PLL0_STS;
break;
}
set_pll_retry_t7:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, pll_ctrl);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_EN_TL1, 1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1 + offset, pll_ctrl1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x0000110c);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3 + offset, 0x10051400);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x0100c0, 0, 24);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x8300c0, 0, 24);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, 26, 1);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 0, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x0000300c);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_pll_retry_t7;
LCDERR("[%d]: pll lock failed\n", pdrv->index);
} else {
udelay(100);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL2 + offset, 1, 5, 1);
}
if (cconf->ss_level > 0) {
lcd_set_pll_ss_level_t7(pdrv);
lcd_set_pll_ss_advance_t7(pdrv);
}
}
static void lcd_set_pll_t3(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_ctrl, pll_ctrl1, pll_stts, offset;
unsigned int tcon_div_sel;
int ret, cnt = 0;
if (pdrv->index) /* clk_path1 invalid */
return;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
tcon_div_sel = cconf->pll_tcon_div_sel;
pll_ctrl = ((0x3 << 17) | /* gate ctrl */
(tcon_div[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_T7) |
(cconf->pll_od2_sel << LCD_PLL_OD2_T7) |
(cconf->pll_od1_sel << LCD_PLL_OD1_T7));
pll_ctrl1 = (1 << 28) |
(tcon_div[tcon_div_sel][0] << 22) |
(tcon_div[tcon_div_sel][1] << 21) |
((1 << 20) | /* sdm_en */
(cconf->pll_frac << 0));
offset = cconf->pll_offset;
pll_stts = ANACTRL_TCON_PLL0_STS;
set_pll_retry_t7:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, pll_ctrl);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_EN_TL1, 1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1 + offset, pll_ctrl1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x0000110c);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3 + offset, 0x10051400);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x0100c0, 0, 24);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x8300c0, 0, 24);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, 26, 1);
udelay(10);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 0, LCD_PLL_RST_TL1, 1);
udelay(10);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x0000300c);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto set_pll_retry_t7;
LCDERR("[%d]: pll lock failed\n", pdrv->index);
} else {
udelay(100);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL2 + offset, 1, 5, 1);
}
if (cconf->ss_level > 0) {
lcd_set_pll_ss_level_t7(pdrv);
lcd_set_pll_ss_advance_t7(pdrv);
}
}
static void lcd_prbs_set_pll_vx1_tl1(struct aml_lcd_drv_s *pdrv)
{
int cnt = 0, ret;
lcd_prbs_retry_pll_vx1_tl1:
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x000f04f7);
usleep_range(10, 12);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_EN_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL1, 0x10110000);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00001108);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL3, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL4, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL4, 0x038300c0);
usleep_range(10, 12);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1);
usleep_range(10, 12);
lcd_ana_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00003008);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00003028);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_vx1_tl1;
LCDERR("pll lock failed\n");
}
/* pll_div */
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 19, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 18, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 0, 14);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 2, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0x739c, 0, 15);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
/* Enable the final output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 19, 1);
}
static void lcd_prbs_set_pll_lvds_tl1(struct aml_lcd_drv_s *pdrv)
{
int cnt = 0, ret;
lcd_prbs_retry_pll_lvds_tl1:
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x008e049f);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x208e049f);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x3006049f);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL1, 0x10000000);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00001102);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL3, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL4, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL4, 0x038300c0);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x348e049f);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL0, 0x148e049f);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00003002);
usleep_range(10, 12);
lcd_ana_write(HHI_TCON_PLL_CNTL2, 0x00003022);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_lvds_tl1;
LCDERR("pll lock failed\n");
}
/* pll_div */
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 19, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 18, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 0, 14);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0x3c78, 0, 15);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
/* Enable the final output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 19, 1);
}
void lcd_prbs_config_clk_tl1(struct aml_lcd_drv_s *pdrv, unsigned int lcd_prbs_mode)
{
if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) {
lcd_prbs_set_pll_vx1_tl1(pdrv);
} else if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) {
lcd_prbs_set_pll_lvds_tl1(pdrv);
} else {
LCDERR("%s: unsupport lcd_prbs_mode %d\n",
__func__, lcd_prbs_mode);
return;
}
lcd_clk_setb(HHI_VIID_CLK_DIV, 0, VCLK2_XD, 8);
usleep_range(5, 10);
/* select vid_pll_clk */
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_CLK_IN_SEL, 3);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_EN, 1);
usleep_range(5, 10);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(HHI_VIID_CLK_DIV, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(HHI_VIID_CLK_DIV, 1, VCLK2_XD_EN, 2);
usleep_range(5, 10);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_SOFT_RST, 1);
usleep_range(10, 12);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_SOFT_RST, 1);
usleep_range(5, 10);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(HHI_VID_CLK_CNTL2, 1, ENCL_GATE_VCLK, 1);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s ok\n", __func__);
}
static void lcd_prbs_set_pll_vx1_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_stts, offset;
unsigned int reg_vid_pll_div, reg_vid2_clk_ctrl;
int cnt = 0, ret;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
offset = cconf->pll_offset;
switch (cconf->pll_id) {
case 1:
pll_stts = ANACTRL_TCON_PLL1_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL1_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
break;
case 2:
pll_stts = ANACTRL_TCON_PLL2_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL2_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
break;
case 0:
default:
pll_stts = ANACTRL_TCON_PLL0_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
break;
}
lcd_prbs_retry_pll_vx1_t7:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x000f04f7);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, LCD_PLL_EN_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1 + offset, 0x10110000);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00001108);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3 + offset, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x038300c0);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 1, 26, 1);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0 + offset, 0, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00003008);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00003028);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_vx1_t7;
LCDERR("[%d]: pll lock failed\n", pdrv->index);
}
/* pll_div */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 19, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 18, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 0, 14);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 2, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0x739c, 0, 15);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
/* Enable the final output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 19, 1);
}
static void lcd_prbs_set_pll_lvds_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int pll_stts, offset;
unsigned int reg_vid_pll_div, reg_vid2_clk_ctrl;
int cnt = 0, ret;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
offset = cconf->pll_offset;
switch (cconf->pll_id) {
case 1:
pll_stts = ANACTRL_TCON_PLL1_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL1_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
break;
case 2:
pll_stts = ANACTRL_TCON_PLL2_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL2_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
break;
case 0:
default:
pll_stts = ANACTRL_TCON_PLL0_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
break;
}
lcd_prbs_retry_pll_lvds_t7:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x008e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x208e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x3006049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1 + offset, 0x10000000);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00001102);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3 + offset, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4 + offset, 0x038300c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x348e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0 + offset, 0x148e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00003002);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2 + offset, 0x00003022);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_lvds_t7;
LCDERR("[%d]: pll lock failed\n", pdrv->index);
}
/* pll_div */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 19, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 18, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 0, 14);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0x3c78, 0, 15);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
/* Enable the final output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 19, 1);
}
static void lcd_prbs_config_clk_t7(struct aml_lcd_drv_s *pdrv, unsigned int lcd_prbs_mode)
{
struct lcd_clk_config_s *cconf;
unsigned int reg_vid2_clk_div, reg_vid2_clk_ctrl, reg_vid_clk_ctrl2;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
switch (cconf->pll_id) {
case 1:
reg_vid2_clk_div = CLKCTRL_VIID_CLK1_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK1_CTRL2;
break;
case 2:
reg_vid2_clk_div = CLKCTRL_VIID_CLK2_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK2_CTRL2;
break;
case 0:
default:
reg_vid2_clk_div = CLKCTRL_VIID_CLK0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK0_CTRL2;
break;
}
if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) {
lcd_prbs_set_pll_vx1_t7(pdrv);
} else if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) {
lcd_prbs_set_pll_lvds_t7(pdrv);
} else {
LCDERR("[%d]: %s: unsupport lcd_prbs_mode %d\n",
pdrv->index, __func__, lcd_prbs_mode);
return;
}
lcd_clk_setb(reg_vid2_clk_div, 0, VCLK2_XD, 8);
usleep_range(5, 10);
/* select vid_pll_clk */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_CLK_IN_SEL, 3);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_EN, 1);
usleep_range(5, 10);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(reg_vid2_clk_div, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(reg_vid2_clk_div, 1, VCLK2_XD_EN, 2);
usleep_range(5, 10);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_SOFT_RST, 1);
usleep_range(10, 12);
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_SOFT_RST, 1);
usleep_range(5, 10);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(reg_vid_clk_ctrl2, 1, ENCL_GATE_VCLK, 1);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s ok\n", pdrv->index, __func__);
}
static void lcd_prbs_set_pll_vx1_t3(struct aml_lcd_drv_s *pdrv)
{
unsigned int pll_stts;
unsigned int reg_vid_pll_div, reg_vid2_clk_ctrl;
int cnt = 0, ret;
pll_stts = ANACTRL_TCON_PLL0_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
lcd_prbs_retry_pll_vx1_t3:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x000f04f7);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0, 1, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0, 1, LCD_PLL_EN_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1, 0x10110000);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00001108);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4, 0x038300c0);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0, 1, 26, 1);
usleep_range(10, 12);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL0, 0, LCD_PLL_RST_TL1, 1);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00003008);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00003028);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_vx1_t3;
LCDERR("pll lock failed\n");
}
/* pll_div */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_ana_setb(reg_vid_pll_div, 0, 19, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 18, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 16, 2);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 0, 14);
lcd_ana_setb(reg_vid_pll_div, 2, 16, 2);
lcd_ana_setb(reg_vid_pll_div, 1, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0x739c, 0, 15);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
/* Enable the final output clock */
lcd_ana_setb(reg_vid_pll_div, 1, 19, 1);
}
static void lcd_prbs_set_pll_lvds_t3(struct aml_lcd_drv_s *pdrv)
{
unsigned int pll_stts;
unsigned int reg_vid_pll_div, reg_vid2_clk_ctrl;
int cnt = 0, ret;
pll_stts = ANACTRL_TCON_PLL0_STS;
reg_vid_pll_div = COMBO_DPHY_VID_PLL0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
lcd_prbs_retry_pll_lvds_t3:
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x008e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x208e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x3006049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL1, 0x10000000);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00001102);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL3, 0x10051400);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4, 0x010100c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL4, 0x038300c0);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x348e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL0, 0x148e049f);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00003002);
usleep_range(10, 12);
lcd_ana_write(ANACTRL_TCON_PLL0_CNTL2, 0x00003022);
usleep_range(10, 12);
ret = lcd_pll_wait_lock(pll_stts, LCD_PLL_LOCK_T7);
if (ret) {
if (cnt++ < PLL_RETRY_MAX)
goto lcd_prbs_retry_pll_lvds_t3;
LCDERR("[%d]: pll lock failed\n", pdrv->index);
}
/* pll_div */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
usleep_range(5, 10);
/* Disable the div output clock */
lcd_ana_setb(reg_vid_pll_div, 0, 19, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 18, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 16, 2);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0, 0, 14);
lcd_ana_setb(reg_vid_pll_div, 1, 16, 2);
lcd_ana_setb(reg_vid_pll_div, 1, 15, 1);
lcd_ana_setb(reg_vid_pll_div, 0x3c78, 0, 15);
lcd_ana_setb(reg_vid_pll_div, 0, 15, 1);
/* Enable the final output clock */
lcd_ana_setb(reg_vid_pll_div, 1, 19, 1);
}
static void lcd_prbs_config_clk_t3(struct aml_lcd_drv_s *pdrv, unsigned int lcd_prbs_mode)
{
unsigned int reg_vid2_clk_div, reg_vid2_clk_ctrl, reg_vid_clk_ctrl2;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
reg_vid2_clk_div = CLKCTRL_VIID_CLK0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK0_CTRL2;
if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) {
lcd_prbs_set_pll_vx1_t3(pdrv);
} else if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) {
lcd_prbs_set_pll_lvds_t3(pdrv);
} else {
LCDERR("[%d]: %s: unsupport lcd_prbs_mode %d\n",
pdrv->index, __func__, lcd_prbs_mode);
return;
}
lcd_clk_setb(reg_vid2_clk_div, 0, VCLK2_XD, 8);
usleep_range(5, 10);
/* select vid_pll_clk */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_CLK_IN_SEL, 3);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_EN, 1);
usleep_range(5, 10);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(reg_vid2_clk_div, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(reg_vid2_clk_div, 1, VCLK2_XD_EN, 2);
usleep_range(5, 10);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_SOFT_RST, 1);
usleep_range(10, 12);
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_SOFT_RST, 1);
usleep_range(5, 10);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(reg_vid_clk_ctrl2, 1, ENCL_GATE_VCLK, 1);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s ok\n", pdrv->index, __func__);
}
static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cconf)
{
unsigned int shift_val, shift_sel;
int i;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1);
udelay(5);
/* Disable the div output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 19, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
i = 0;
while (lcd_clk_div_table[i][0] != CLK_DIV_SEL_MAX) {
if (cconf->div_sel == lcd_clk_div_table[i][0])
break;
i++;
}
if (lcd_clk_div_table[i][0] == CLK_DIV_SEL_MAX)
LCDERR("invalid clk divider\n");
shift_val = lcd_clk_div_table[i][1];
shift_sel = lcd_clk_div_table[i][2];
if (shift_val == 0xffff) { /* if divide by 1 */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 18, 1);
} else {
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 18, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 0, 14);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, shift_sel, 16, 2);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 15, 1);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, shift_val, 0, 15);
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1);
}
/* Enable the final output clock */
lcd_ana_setb(HHI_VID_PLL_CLK_DIV, 1, 19, 1);
}
static void lcd_set_phy_dig_div_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int reg_edp_clk_div, reg_dphy_tx_ctrl1;
unsigned int port_sel, bit_div_en, bit_div0, bit_div1, bit_rst;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
reg_edp_clk_div = COMBO_DPHY_EDP_PIXEL_CLK_DIV;
switch (cconf->pll_id) {
case 1:
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
port_sel = 1;
bit_div_en = 25;
bit_div0 = 8;
bit_div1 = 12;
bit_rst = 20;
break;
case 2:
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL1;
port_sel = 2;
bit_div_en = 26;
bit_div0 = 0;
bit_div1 = 4;
bit_rst = 7;
break;
case 0:
default:
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
port_sel = 0;
bit_div_en = 24;
bit_div0 = 0;
bit_div1 = 4;
bit_rst = 19;
break;
}
lcd_reset_setb(pdrv, RESETCTRL_RESET1_MASK, 0, bit_rst, 1);
lcd_reset_setb(pdrv, RESETCTRL_RESET1_LEVEL, 0, bit_rst, 1);
udelay(1);
lcd_reset_setb(pdrv, RESETCTRL_RESET1_LEVEL, 1, bit_rst, 1);
udelay(10);
// Enable dphy clock
lcd_combo_dphy_setb(pdrv, reg_dphy_tx_ctrl1, 1, 0, 1);
switch (pdrv->config.basic.lcd_type) {
case LCD_EDP:
if (port_sel == 2) {
LCDERR("[%d]: %s: invalid port: %d\n",
pdrv->index, __func__, port_sel);
return;
}
// Disable edp_div clock
lcd_combo_dphy_setb(pdrv, reg_edp_clk_div, 0, bit_div_en, 1);
lcd_combo_dphy_setb(pdrv, reg_edp_clk_div, cconf->edp_div0, bit_div0, 4);
lcd_combo_dphy_setb(pdrv, reg_edp_clk_div, cconf->edp_div1, bit_div1, 4);
// Enable edp_div clock
lcd_combo_dphy_setb(pdrv, reg_edp_clk_div, 1, bit_div_en, 1);
// sel edp_div clock
lcd_combo_dphy_setb(pdrv, reg_dphy_tx_ctrl1, 1, 4, 1);
break;
case LCD_MIPI:
case LCD_VBYONE:
if (port_sel == 2) {
LCDERR("[%d]: %s: invalid port: %d\n",
pdrv->index, __func__, port_sel);
return;
}
// sel pll clock
lcd_combo_dphy_setb(pdrv, reg_dphy_tx_ctrl1, 0, 4, 1);
break;
default:
// sel pll clock
lcd_combo_dphy_setb(pdrv, reg_dphy_tx_ctrl1, 0, 4, 1);
break;
}
// sel tcon_pll clock
lcd_combo_dphy_setb(pdrv, reg_dphy_tx_ctrl1, 0, 5, 1);
}
static void lcd_set_vid_pll_div_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int reg_vid_pll_div, reg_vid2_clk_ctrl;
unsigned int shift_val, shift_sel;
int i;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
switch (cconf->pll_id) {
case 1:
reg_vid_pll_div = COMBO_DPHY_VID_PLL1_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
break;
case 2:
reg_vid_pll_div = COMBO_DPHY_VID_PLL2_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
break;
case 0:
default:
reg_vid_pll_div = COMBO_DPHY_VID_PLL0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
break;
}
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
udelay(5);
/* Disable the div output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 19, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
i = 0;
while (lcd_clk_div_table[i][0] != CLK_DIV_SEL_MAX) {
if (cconf->div_sel == lcd_clk_div_table[i][0])
break;
i++;
}
if (lcd_clk_div_table[i][0] == CLK_DIV_SEL_MAX)
LCDERR("[%d]: invalid clk divider\n", pdrv->index);
shift_val = lcd_clk_div_table[i][1];
shift_sel = lcd_clk_div_table[i][2];
if (shift_val == 0xffff) { /* if divide by 1 */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 18, 1);
} else {
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 18, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 0, 14);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, shift_sel, 16, 2);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 15, 1);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, shift_val, 0, 15);
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 0, 15, 1);
}
/* Enable the final output clock */
lcd_combo_dphy_setb(pdrv, reg_vid_pll_div, 1, 19, 1);
}
static void lcd_set_vid_pll_div_t3(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int shift_val, shift_sel;
int i;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
if (cconf->pll_id) {
/* only crt_video valid for clk path1 */
lcd_clk_setb(CLKCTRL_VIID_CLK1_CTRL, 0, VCLK2_EN, 1);
udelay(5);
return;
}
lcd_clk_setb(CLKCTRL_VIID_CLK0_CTRL, 0, VCLK2_EN, 1);
udelay(5);
/* Disable the div output clock */
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 19, 1);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 15, 1);
i = 0;
while (lcd_clk_div_table[i][0] != CLK_DIV_SEL_MAX) {
if (cconf->div_sel == lcd_clk_div_table[i][0])
break;
i++;
}
if (lcd_clk_div_table[i][0] == CLK_DIV_SEL_MAX)
LCDERR("[%d]: invalid clk divider\n", pdrv->index);
shift_val = lcd_clk_div_table[i][1];
shift_sel = lcd_clk_div_table[i][2];
if (shift_val == 0xffff) { /* if divide by 1 */
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 1, 18, 1);
} else {
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 18, 1);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 20, 1);/*div8_25*/
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 16, 2);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 15, 1);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 0, 15);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, shift_sel, 16, 2);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 1, 15, 1);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, shift_val, 0, 15);
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 0, 15, 1);
}
/* Enable the final output clock */
lcd_ana_setb(ANACTRL_VID_PLL_CLK_DIV, 1, 19, 1);
}
static void lcd_set_vclk_crt(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (pdrv->lcd_pxp) {
/* setup the XD divider value */
lcd_clk_setb(HHI_VIID_CLK_DIV, cconf->xd, VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(HHI_VIID_CLK_CNTL, 7, VCLK2_CLK_IN_SEL, 3);
} else {
/* setup the XD divider value */
lcd_clk_setb(HHI_VIID_CLK_DIV, (cconf->xd - 1), VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(HHI_VIID_CLK_CNTL, cconf->data->vclk_sel, VCLK2_CLK_IN_SEL, 3);
}
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_EN, 1);
udelay(2);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(HHI_VIID_CLK_DIV, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(HHI_VIID_CLK_DIV, 1, VCLK2_XD_EN, 2);
udelay(5);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_SOFT_RST, 1);
udelay(10);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_SOFT_RST, 1);
udelay(5);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(HHI_VID_CLK_CNTL2, 1, ENCL_GATE_VCLK, 1);
}
static void lcd_set_vclk_crt_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int reg_vid2_clk_div, reg_vid2_clk_ctrl, reg_vid_clk_ctrl2;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
switch (cconf->pll_id) {
case 1:
reg_vid2_clk_div = CLKCTRL_VIID_CLK1_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK1_CTRL2;
break;
case 2:
reg_vid2_clk_div = CLKCTRL_VIID_CLK2_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK2_CTRL2;
break;
case 0:
default:
reg_vid2_clk_div = CLKCTRL_VIID_CLK0_DIV;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK0_CTRL2;
break;
}
lcd_clk_write(reg_vid_clk_ctrl2, 0);
lcd_clk_write(reg_vid2_clk_ctrl, 0);
lcd_clk_write(reg_vid2_clk_div, 0);
udelay(5);
if (pdrv->lcd_pxp) {
/* setup the XD divider value */
lcd_clk_setb(reg_vid2_clk_div, cconf->xd, VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(reg_vid2_clk_ctrl, 7, VCLK2_CLK_IN_SEL, 3);
} else {
/* setup the XD divider value */
lcd_clk_setb(reg_vid2_clk_div, (cconf->xd - 1), VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(reg_vid2_clk_ctrl, cconf->data->vclk_sel, VCLK2_CLK_IN_SEL, 3);
}
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_EN, 1);
udelay(2);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(reg_vid2_clk_div, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(reg_vid2_clk_div, 1, VCLK2_XD_EN, 2);
udelay(5);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(reg_vid2_clk_ctrl, 1, VCLK2_SOFT_RST, 1);
udelay(10);
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_SOFT_RST, 1);
udelay(5);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(reg_vid_clk_ctrl2, 1, ENCL_GATE_VCLK, 1);
}
static void lcd_set_vclk_crt_t5w(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (pdrv->lcd_pxp) {
/* setup the XD divider value */
lcd_clk_setb(HHI_VIID_CLK0_DIV, cconf->xd, VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(HHI_VIID_CLK0_CTRL, 7, VCLK2_CLK_IN_SEL, 3);
} else {
/* setup the XD divider value */
lcd_clk_setb(HHI_VIID_CLK0_DIV, (cconf->xd - 1),
VCLK2_XD, 8);
udelay(5);
/* select vid_pll_clk */
lcd_clk_setb(HHI_VIID_CLK0_CTRL, cconf->data->vclk_sel,
VCLK2_CLK_IN_SEL, 3);
}
lcd_clk_setb(HHI_VIID_CLK0_CTRL, 1, VCLK2_EN, 1);
udelay(2);
/* [15:12] encl_clk_sel, select vclk2_div1 */
lcd_clk_setb(HHI_VIID_CLK0_DIV, 8, ENCL_CLK_SEL, 4);
/* release vclk2_div_reset and enable vclk2_div */
lcd_clk_setb(HHI_VIID_CLK0_DIV, 1, VCLK2_XD_EN, 2);
udelay(5);
lcd_clk_setb(HHI_VIID_CLK0_CTRL, 1, VCLK2_DIV1_EN, 1);
lcd_clk_setb(HHI_VIID_CLK0_CTRL, 1, VCLK2_SOFT_RST, 1);
udelay(10);
lcd_clk_setb(HHI_VIID_CLK0_CTRL, 0, VCLK2_SOFT_RST, 1);
udelay(5);
/* enable CTS_ENCL clk gate */
lcd_clk_setb(HHI_VID_CLK0_CTRL2, 1, ENCL_GATE_VCLK, 1);
}
static void lcd_set_dsi_meas_clk(void)
{
lcd_clk_setb(HHI_VDIN_MEAS_CLK_CNTL, 0, 21, 3);
lcd_clk_setb(HHI_VDIN_MEAS_CLK_CNTL, 0, 12, 7);
lcd_clk_setb(HHI_VDIN_MEAS_CLK_CNTL, 1, 20, 1);
}
static void lcd_set_dsi_phy_clk(int sel)
{
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s\n", __func__);
lcd_clk_setb(HHI_MIPIDSI_PHY_CLK_CNTL, sel, 12, 3);
lcd_clk_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 1, 8, 1);
lcd_clk_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 0, 0, 7);
}
static void lcd_set_dsi_meas_clk_t7(int index)
{
if (index) {
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 7, 12, 7);
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 0, 21, 3);
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 1, 20, 1);
} else {
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 7, 0, 7);
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 0, 9, 3);
lcd_clk_setb(CLKCTRL_MIPI_DSI_MEAS_CLK_CTRL, 1, 8, 1);
}
}
static void lcd_set_dsi_phy_clk_t7(int index)
{
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("[%d]: %s\n", index, __func__);
if (index) {
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 0, 16, 7);
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 0, 25, 3);
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 1, 24, 1);
} else {
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 0, 0, 7);
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 0, 12, 3);
lcd_clk_setb(CLKCTRL_MIPIDSI_PHY_CLK_CTRL, 1, 8, 1);
}
}
static void lcd_set_tcon_clk_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int freq, val;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
switch (pconf->basic.lcd_type) {
case LCD_MLVDS:
val = pconf->control.mlvds_cfg.clk_phase & 0xfff;
lcd_ana_setb(HHI_TCON_PLL_CNTL1, (val & 0xf), 24, 4);
lcd_ana_setb(HHI_TCON_PLL_CNTL4, ((val >> 4) & 0xf), 28, 4);
lcd_ana_setb(HHI_TCON_PLL_CNTL4, ((val >> 8) & 0xf), 24, 4);
/* tcon_clk */
if (pconf->timing.lcd_clk >= 100000000) /* 25M */
freq = 25000000;
else /* 12.5M */
freq = 12500000;
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk)) {
clk_set_rate(cconf->clktree.tcon_clk, freq);
clk_prepare_enable(cconf->clktree.tcon_clk);
}
break;
case LCD_P2P:
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk)) {
clk_set_rate(cconf->clktree.tcon_clk, 50000000);
clk_prepare_enable(cconf->clktree.tcon_clk);
}
break;
default:
break;
}
}
static void lcd_set_tcon_clk_t5(struct aml_lcd_drv_s *pdrv)
{
if (pdrv->config.basic.lcd_type != LCD_MLVDS &&
pdrv->config.basic.lcd_type != LCD_P2P)
return;
lcd_set_tcon_clk_tl1(pdrv);
lcd_tcon_global_reset(pdrv);
}
static void lcd_set_tcon_clk_t3(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int freq, val;
if (pdrv->index > 0) /* tcon_clk only valid for lcd0 */
return;
if (pdrv->config.basic.lcd_type != LCD_MLVDS &&
pdrv->config.basic.lcd_type != LCD_P2P)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s\n", __func__);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
switch (pconf->basic.lcd_type) {
case LCD_MLVDS:
val = pconf->control.mlvds_cfg.clk_phase & 0xfff;
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL1, (val & 0xf), 24, 4);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4, ((val >> 4) & 0xf), 28, 4);
lcd_ana_setb(ANACTRL_TCON_PLL0_CNTL4, ((val >> 8) & 0xf), 24, 4);
/* tcon_clk */
if (pconf->timing.lcd_clk >= 100000000) /* 25M */
freq = 25000000;
else /* 12.5M */
freq = 12500000;
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk)) {
clk_set_rate(cconf->clktree.tcon_clk, freq);
clk_prepare_enable(cconf->clktree.tcon_clk);
}
break;
case LCD_P2P:
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk)) {
clk_set_rate(cconf->clktree.tcon_clk, 50000000);
clk_prepare_enable(cconf->clktree.tcon_clk);
}
break;
default:
break;
}
lcd_tcon_global_reset(pdrv);
}
/* ****************************************************
* lcd clk parameters calculate
* ****************************************************
*/
static unsigned int clk_vid_pll_div_calc(unsigned int clk,
unsigned int div_sel, int dir)
{
unsigned int clk_ret;
switch (div_sel) {
case CLK_DIV_SEL_1:
clk_ret = clk;
break;
case CLK_DIV_SEL_2:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 2;
else
clk_ret = clk * 2;
break;
case CLK_DIV_SEL_3:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 3;
else
clk_ret = clk * 3;
break;
case CLK_DIV_SEL_3p5:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 2 / 7;
else
clk_ret = clk * 7 / 2;
break;
case CLK_DIV_SEL_3p75:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 4 / 15;
else
clk_ret = clk * 15 / 4;
break;
case CLK_DIV_SEL_4:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 4;
else
clk_ret = clk * 4;
break;
case CLK_DIV_SEL_5:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 5;
else
clk_ret = clk * 5;
break;
case CLK_DIV_SEL_6:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 6;
else
clk_ret = clk * 6;
break;
case CLK_DIV_SEL_6p25:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 4 / 25;
else
clk_ret = clk * 25 / 4;
break;
case CLK_DIV_SEL_7:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 7;
else
clk_ret = clk * 7;
break;
case CLK_DIV_SEL_7p5:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 2 / 15;
else
clk_ret = clk * 15 / 2;
break;
case CLK_DIV_SEL_12:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 12;
else
clk_ret = clk * 12;
break;
case CLK_DIV_SEL_14:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 14;
else
clk_ret = clk * 14;
break;
case CLK_DIV_SEL_15:
if (dir == CLK_DIV_I2O)
clk_ret = clk / 15;
else
clk_ret = clk * 15;
break;
case CLK_DIV_SEL_2p5:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 2 / 5;
else
clk_ret = clk * 5 / 2;
break;
case CLK_DIV_SEL_4p67:
if (dir == CLK_DIV_I2O)
clk_ret = clk * 3 / 14;
else
clk_ret = clk * 14 / 3;
break;
default:
clk_ret = clk;
LCDERR("clk_div_sel: Invalid parameter\n");
break;
}
return clk_ret;
}
static unsigned int clk_vid_pll_div_get(unsigned int clk_div)
{
unsigned int div_sel;
/* div * 100 */
switch (clk_div) {
case 375:
div_sel = CLK_DIV_SEL_3p75;
break;
case 750:
div_sel = CLK_DIV_SEL_7p5;
break;
case 1500:
div_sel = CLK_DIV_SEL_15;
break;
case 500:
div_sel = CLK_DIV_SEL_5;
break;
default:
div_sel = CLK_DIV_SEL_MAX;
break;
}
return div_sel;
}
static int check_pll_3od(struct lcd_clk_config_s *cconf,
unsigned int pll_fout)
{
struct lcd_clk_data_s *data = cconf->data;
unsigned int m, n;
unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3;
unsigned int pll_fod2_in, pll_fod3_in, pll_fvco;
unsigned int od_fb = 0, frac_range, pll_frac;
int done;
done = 0;
if (pll_fout > data->pll_out_fmax ||
pll_fout < data->pll_out_fmin) {
return done;
}
frac_range = data->pll_frac_range;
for (od3_sel = data->pll_od_sel_max; od3_sel > 0; od3_sel--) {
od3 = od_table[od3_sel - 1];
pll_fod3_in = pll_fout * od3;
for (od2_sel = od3_sel; od2_sel > 0; od2_sel--) {
od2 = od_table[od2_sel - 1];
pll_fod2_in = pll_fod3_in * od2;
for (od1_sel = od2_sel; od1_sel > 0; od1_sel--) {
od1 = od_table[od1_sel - 1];
pll_fvco = pll_fod2_in * od1;
if (pll_fvco < data->pll_vco_fmin ||
pll_fvco > data->pll_vco_fmax) {
continue;
}
cconf->pll_od1_sel = od1_sel - 1;
cconf->pll_od2_sel = od2_sel - 1;
cconf->pll_od3_sel = od3_sel - 1;
cconf->pll_fout = pll_fout;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("od1=%d, od2=%d, od3=%d, pll_fvco=%d\n",
(od1_sel - 1), (od2_sel - 1),
(od3_sel - 1), pll_fvco);
}
cconf->pll_fvco = pll_fvco;
n = 1;
od_fb = cconf->pll_od_fb;
pll_fvco = pll_fvco / od_fb_table[od_fb];
m = pll_fvco / cconf->fin;
pll_frac = (pll_fvco % cconf->fin) * frac_range / cconf->fin;
if (cconf->pll_mode & LCD_PLL_MODE_FRAC_SHIFT) {
if ((pll_frac == (frac_range >> 1)) ||
(pll_frac == (frac_range >> 2))) {
pll_frac |= 0x66;
cconf->pll_frac_half_shift = 1;
} else {
cconf->pll_frac_half_shift = 0;
}
}
cconf->pll_m = m;
cconf->pll_n = n;
cconf->pll_frac = pll_frac;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("m=%d, n=%d, frac=0x%x\n", m, n, pll_frac);
done = 1;
break;
}
}
}
return done;
}
static int check_pll_1od(struct lcd_clk_config_s *cconf, unsigned int pll_fout)
{
struct lcd_clk_data_s *data = cconf->data;
unsigned int m, n, od_sel, od;
unsigned int pll_fvco;
unsigned int od_fb = 0, pll_frac;
int done = 0;
if (pll_fout > data->pll_out_fmax || pll_fout < data->pll_out_fmin)
return done;
for (od_sel = data->pll_od_sel_max; od_sel > 0; od_sel--) {
od = od_table[od_sel - 1];
pll_fvco = pll_fout * od;
if (pll_fvco < data->pll_vco_fmin || pll_fvco > data->pll_vco_fmax)
continue;
cconf->pll_od1_sel = od_sel - 1;
cconf->pll_fout = pll_fout;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("od_sel=%d, pll_fvco=%d\n", (od_sel - 1), pll_fvco);
cconf->pll_fvco = pll_fvco;
n = 1;
od_fb = cconf->pll_od_fb;
pll_fvco = pll_fvco / od_fb_table[od_fb];
m = pll_fvco / cconf->fin;
pll_frac = (pll_fvco % cconf->fin) * data->pll_frac_range / cconf->fin;
cconf->pll_m = m;
cconf->pll_n = n;
cconf->pll_frac = pll_frac;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("pll_m=%d, pll_n=%d, pll_frac=0x%x\n", m, n, pll_frac);
done = 1;
break;
}
return done;
}
static int check_vco(struct lcd_clk_config_s *cconf, unsigned int pll_fvco)
{
struct lcd_clk_data_s *data = cconf->data;
unsigned int m, n;
unsigned int od_fb = 0, pll_frac;
int done = 0;
if (pll_fvco < data->pll_vco_fmin || pll_fvco > data->pll_vco_fmax) {
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("pll_fvco %d is out of range\n", pll_fvco);
return done;
}
cconf->pll_fvco = pll_fvco;
n = 1;
od_fb = cconf->pll_od_fb;
pll_fvco = pll_fvco / od_fb_table[od_fb];
m = pll_fvco / cconf->fin;
pll_frac = (pll_fvco % cconf->fin) * data->pll_frac_range / cconf->fin;
cconf->pll_m = m;
cconf->pll_n = n;
cconf->pll_frac = pll_frac;
if (cconf->pll_mode & LCD_PLL_MODE_FRAC_SHIFT) {
if ((pll_frac == (data->pll_frac_range >> 1)) ||
(pll_frac == (data->pll_frac_range >> 2))) {
pll_frac |= 0x66;
cconf->pll_frac_half_shift = 1;
} else {
cconf->pll_frac_half_shift = 0;
}
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("m=%d, n=%d, frac=0x%x, pll_fvco=%d\n",
m, n, pll_frac, pll_fvco);
}
done = 1;
return done;
}
#define PLL_FVCO_ERR_MAX 2 /* kHz */
static int check_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;
unsigned int pll_fod2_in, pll_fod3_in, pll_fvco;
int done = 0;
if (pll_fout > data->pll_out_fmax ||
pll_fout < data->pll_out_fmin) {
return done;
}
for (od3_sel = data->pll_od_sel_max; od3_sel > 0; od3_sel--) {
od3 = od_table[od3_sel - 1];
pll_fod3_in = pll_fout * od3;
for (od2_sel = od3_sel; od2_sel > 0; od2_sel--) {
od2 = od_table[od2_sel - 1];
pll_fod2_in = pll_fod3_in * od2;
for (od1_sel = od2_sel; od1_sel > 0; od1_sel--) {
od1 = od_table[od1_sel - 1];
pll_fvco = pll_fod2_in * od1;
if (pll_fvco < data->pll_vco_fmin ||
pll_fvco > data->pll_vco_fmax) {
continue;
}
if (error_abs(pll_fvco, cconf->pll_fvco) <
PLL_FVCO_ERR_MAX) {
cconf->pll_od1_sel = od1_sel - 1;
cconf->pll_od2_sel = od2_sel - 1;
cconf->pll_od3_sel = od3_sel - 1;
cconf->pll_fout = pll_fout;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("od1=%d, od2=%d, od3=%d\n",
(od1_sel - 1),
(od2_sel - 1),
(od3_sel - 1));
}
done = 1;
break;
}
}
}
}
return done;
}
static int edp_div_check(struct lcd_clk_config_s *cconf, unsigned int bit_rate)
{
unsigned int edp_div0, edp_div1, tmp_div, tmp;
for (edp_div0 = 0; edp_div0 < 15; edp_div0++) {
for (edp_div1 = 0; edp_div1 < 10; edp_div1++) {
tmp_div = edp_div0_table[edp_div0] * edp_div1_table[edp_div1];
tmp = bit_rate / tmp_div;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("fout=%d, _clk=%d, tmp_div=%d, edp_div0=%d, edp_div1=%d\n",
cconf->fout, tmp, tmp_div, edp_div0, edp_div1);
}
tmp = error_abs(tmp, cconf->fout);
if (cconf->err_fmin > tmp) {
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("err=%d, edp_div0=%d, edp_div1=%d\n",
tmp, edp_div0, edp_div1);
}
cconf->err_fmin = tmp;
cconf->edp_div0 = edp_div0;
cconf->edp_div1 = edp_div1;
}
}
}
return 0;
}
static void lcd_clk_generate_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int pll_fout, pll_fvco, bit_rate;
unsigned int clk_div_in, clk_div_out;
unsigned int clk_div_sel, xd, tcon_div_sel = 0, phy_div = 1;
unsigned int od1, od2, od3;
unsigned int dsi_bit_rate_max = 0, dsi_bit_rate_min = 0, tmp;
unsigned int tmp_div;
int done;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
done = 0;
cconf->fout = pconf->timing.lcd_clk / 1000; /* kHz */
cconf->err_fmin = MAX_ERROR;
if (cconf->fout > cconf->data->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n", __func__, cconf->fout);
goto generate_clk_done_tl1;
}
bit_rate = pconf->timing.bit_rate / 1000;
cconf->pll_mode = pconf->timing.clk_auto;
switch (pconf->basic.lcd_type) {
case LCD_TTL:
clk_div_sel = CLK_DIV_SEL_1;
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 & LCD_DBG_PR_CLK) {
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)
continue;
cconf->xd = xd;
cconf->div_sel = clk_div_sel;
pll_fout = clk_div_in;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("clk_div_sel=%s(index %d), pll_fout=%d\n",
lcd_clk_div_sel_table[clk_div_sel],
clk_div_sel, pll_fout);
}
done = check_pll_3od(cconf, pll_fout);
if (done)
goto generate_clk_done_tl1;
}
break;
case LCD_LVDS:
clk_div_sel = CLK_DIV_SEL_7;
xd = 1;
clk_div_out = cconf->fout * xd;
if (clk_div_out > cconf->data->div_out_fmax)
goto generate_clk_done_tl1;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
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_tl1;
cconf->xd = xd;
cconf->div_sel = clk_div_sel;
pll_fout = clk_div_in;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("clk_div_sel=%s(index %d), pll_fout=%d\n",
lcd_clk_div_sel_table[clk_div_sel],
clk_div_sel, pll_fout);
}
done = check_pll_3od(cconf, pll_fout);
if (done == 0)
goto generate_clk_done_tl1;
done = 0;
if (pconf->control.lvds_cfg.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;
cconf->xd_max = CRT_VID_DIV_MAX;
pll_fout = bit_rate;
clk_div_in = pll_fout;
if (clk_div_in > cconf->data->div_in_fmax)
goto generate_clk_done_tl1;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("pll_fout=%d\n", pll_fout);
if ((clk_div_in / cconf->fout) > 15)
cconf->xd = 4;
else
cconf->xd = 1;
clk_div_out = cconf->fout * cconf->xd;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("clk_div_in=%d, fout=%d, xd=%d, clk_div_out=%d\n",
clk_div_in, cconf->fout, cconf->xd, clk_div_out);
}
if (clk_div_out > cconf->data->div_out_fmax)
goto generate_clk_done_tl1;
clk_div_sel = clk_vid_pll_div_get(clk_div_in * 100 / clk_div_out);
if (clk_div_sel == CLK_DIV_SEL_MAX) {
clk_div_sel = CLK_DIV_SEL_1;
cconf->xd *= clk_div_in / clk_div_out;
} else {
cconf->div_sel = clk_div_sel;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("clk_div_sel=%s(index %d), xd=%d\n",
lcd_clk_div_sel_table[clk_div_sel],
cconf->div_sel, cconf->xd);
}
done = check_pll_3od(cconf, pll_fout);
if (done == 0)
goto generate_clk_done_tl1;
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:
/* must go through div4 for clk phase */
for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) {
pll_fvco = bit_rate * tcon_div_table[tcon_div_sel];
done = check_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 & LCD_DBG_PR_CLK) {
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 & LCD_DBG_PR_CLK) {
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_od(cconf, pll_fout);
if (done)
goto generate_clk_done_tl1;
}
}
}
break;
case LCD_P2P:
for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) {
pll_fvco = bit_rate * tcon_div_table[tcon_div_sel];
done = check_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 & LCD_DBG_PR_CLK) {
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 & LCD_DBG_PR_CLK) {
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_od(cconf, pll_fout);
if (done)
goto generate_clk_done_tl1;
}
}
}
break;
case LCD_MIPI:
cconf->xd_max = CRT_VID_DIV_MAX;
tmp = pconf->control.mipi_cfg.bit_rate_max;
dsi_bit_rate_max = tmp * 1000; /* change to kHz */
dsi_bit_rate_min = dsi_bit_rate_max - cconf->fout;
clk_div_sel = CLK_DIV_SEL_1;
for (xd = 1; xd <= cconf->xd_max; xd++) {
pll_fout = cconf->fout * xd;
if (pll_fout > dsi_bit_rate_max || pll_fout < dsi_bit_rate_min)
continue;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("fout=%d, xd=%d\n", cconf->fout, xd);
pconf->timing.bit_rate = pll_fout * 1000;
pconf->control.mipi_cfg.clk_factor = xd;
cconf->xd = xd;
cconf->div_sel = clk_div_sel;
cconf->pll_tcon_div_sel = 2;
done = check_pll_3od(cconf, pll_fout);
if (done)
goto generate_clk_done_tl1;
}
break;
case LCD_EDP:
switch (pconf->control.edp_cfg.link_rate) {
case 0: /* 1.62G */
cconf->pll_n = 1;
cconf->pll_m = 135;
cconf->pll_frac = 0x0;
cconf->pll_fvco = 3240000;
cconf->pll_fout = 1620000;
bit_rate = 1620000;
break;
case 1: /* 2.7G */
default:
cconf->pll_n = 1;
cconf->pll_m = 225;
cconf->pll_frac = 0x0;
cconf->pll_fvco = 5400000;
cconf->pll_fout = 2700000;
bit_rate = 2700000;
break;
}
cconf->pll_od1_sel = 1;
cconf->pll_od2_sel = 0;
cconf->pll_od3_sel = 0;
cconf->pll_frac_half_shift = 0;
cconf->div_sel = CLK_DIV_SEL_1;
cconf->xd = 1;
cconf->err_fmin = 10000; /* 10M basic error */
for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) {
if (tcon_div_table[tcon_div_sel] != cconf->pll_fvco / bit_rate)
continue;
cconf->pll_tcon_div_sel = tcon_div_sel;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("bit_rate=%d, tcon_div=%d\n",
bit_rate, tcon_div_table[tcon_div_sel]);
}
if (edp_div_check(cconf, bit_rate) == 0)
done = 1;
}
if (done == 0)
break;
tmp_div = edp_div0_table[cconf->edp_div0] * edp_div1_table[cconf->edp_div1];
cconf->fout = bit_rate / tmp_div;
pconf->timing.lcd_clk = cconf->fout * 1000; /* Hz */
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("final fout=%d, tmp_div=%d, edp_div0=%d, edp_div1=%d\n",
cconf->fout, tmp_div,
cconf->edp_div0, cconf->edp_div1);
}
break;
default:
break;
}
generate_clk_done_tl1:
if (done) {
pconf->timing.pll_ctrl =
(cconf->pll_od1_sel << PLL_CTRL_OD1) |
(cconf->pll_od2_sel << PLL_CTRL_OD2) |
(cconf->pll_od3_sel << PLL_CTRL_OD3) |
(cconf->pll_n << PLL_CTRL_N) |
(cconf->pll_m << PLL_CTRL_M);
pconf->timing.div_ctrl =
(cconf->div_sel << DIV_CTRL_DIV_SEL) |
(cconf->xd << DIV_CTRL_XD);
pconf->timing.clk_ctrl =
(cconf->pll_frac << CLK_CTRL_FRAC) |
(cconf->pll_frac_half_shift << CLK_CTRL_FRAC_SHIFT);
cconf->done = 1;
} else {
pconf->timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_OD2) |
(1 << PLL_CTRL_OD3) |
(1 << PLL_CTRL_N) |
(50 << PLL_CTRL_M);
pconf->timing.div_ctrl =
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(7 << DIV_CTRL_XD);
pconf->timing.clk_ctrl = (0 << CLK_CTRL_FRAC);
cconf->done = 0;
LCDERR("[%d]: %s: Out of clock range\n", pdrv->index, __func__);
}
}
static void lcd_pll_frac_generate_dft(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int pll_fout;
unsigned int clk_div_in, clk_div_out, clk_div_sel;
unsigned int od1, od2, od3, pll_fvco;
unsigned int m, n, od_fb, frac_range, frac, offset, temp;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->fout = pconf->timing.lcd_clk / 1000; /* kHz */
clk_div_sel = cconf->div_sel;
od1 = od_table[cconf->pll_od1_sel];
od2 = od_table[cconf->pll_od2_sel];
od3 = od_table[cconf->pll_od3_sel];
m = cconf->pll_m;
n = cconf->pll_n;
od_fb = cconf->pll_od_fb;
frac_range = cconf->data->pll_frac_range;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("m=%d, n=%d, od1=%d, od2=%d, od3=%d\n",
m, n, cconf->pll_od1_sel, cconf->pll_od2_sel,
cconf->pll_od3_sel);
LCDPR("clk_div_sel=%s(index %d), xd=%d\n",
lcd_clk_div_sel_table[clk_div_sel],
clk_div_sel, cconf->xd);
}
if (cconf->fout > cconf->data->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n",
__func__, cconf->fout);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pclk=%d\n", __func__, cconf->fout);
clk_div_out = cconf->fout * cconf->xd;
if (clk_div_out > cconf->data->div_out_fmax) {
LCDERR("%s: wrong clk_div_out value %dkHz\n",
__func__, clk_div_out);
return;
}
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) {
LCDERR("%s: wrong clk_div_in value %dkHz\n",
__func__, clk_div_in);
return;
}
pll_fout = clk_div_in;
if (pll_fout > cconf->data->pll_out_fmax ||
pll_fout < cconf->data->pll_out_fmin) {
LCDERR("%s: wrong pll_fout value %dkHz\n", __func__, pll_fout);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pll_fout=%d\n", __func__, pll_fout);
pll_fvco = pll_fout * od1 * od2 * od3;
if (pll_fvco < cconf->data->pll_vco_fmin ||
pll_fvco > cconf->data->pll_vco_fmax) {
LCDERR("%s: wrong pll_fvco value %dkHz\n", __func__, pll_fvco);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pll_fvco=%d\n", __func__, pll_fvco);
cconf->pll_fvco = pll_fvco;
pll_fvco = pll_fvco / od_fb_table[od_fb];
temp = cconf->fin * m / n;
if (pll_fvco >= temp) {
temp = pll_fvco - temp;
offset = 0;
} else {
temp = temp - pll_fvco;
offset = 1;
}
if (temp >= (2 * cconf->fin)) {
LCDERR("%s: pll changing %dkHz is too much\n",
__func__, temp);
return;
}
frac = temp * frac_range * n / cconf->fin;
if (cconf->pll_mode & LCD_PLL_MODE_FRAC_SHIFT) {
if ((frac == (frac_range >> 1)) || (frac == (frac_range >> 2))) {
frac |= 0x66;
cconf->pll_frac_half_shift = 1;
} else {
cconf->pll_frac_half_shift = 0;
}
}
cconf->pll_frac = frac | (offset << cconf->data->pll_frac_sign_bit);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_pll_frac_generate: frac=0x%x\n", frac);
}
static void lcd_clk_generate_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int pll_fout;
unsigned int xd;
unsigned int dsi_bit_rate_max = 0, dsi_bit_rate_min = 0;
unsigned int tmp;
int done = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->fout = pconf->timing.lcd_clk / 1000; /* kHz */
cconf->err_fmin = MAX_ERROR;
if (cconf->fout > cconf->data->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n", __func__, cconf->fout);
goto generate_clk_done_g12a;
}
switch (pconf->basic.lcd_type) {
case LCD_MIPI:
cconf->xd_max = CRT_VID_DIV_MAX;
tmp = pconf->control.mipi_cfg.bit_rate_max;
dsi_bit_rate_max = tmp * 1000; /* change to kHz */
dsi_bit_rate_min = dsi_bit_rate_max - cconf->fout;
for (xd = 1; xd <= cconf->xd_max; xd++) {
pll_fout = cconf->fout * xd;
if (pll_fout > dsi_bit_rate_max || pll_fout < dsi_bit_rate_min)
continue;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("fout=%d, xd=%d\n", cconf->fout, xd);
pconf->timing.bit_rate = pll_fout * 1000;
pconf->control.mipi_cfg.clk_factor = xd;
cconf->xd = xd;
done = check_pll_1od(cconf, pll_fout);
if (done)
goto generate_clk_done_g12a;
}
break;
default:
break;
}
generate_clk_done_g12a:
if (done) {
pconf->timing.pll_ctrl =
(cconf->pll_od1_sel << PLL_CTRL_OD1) |
(cconf->pll_n << PLL_CTRL_N) |
(cconf->pll_m << PLL_CTRL_M);
pconf->timing.div_ctrl =
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(cconf->xd << DIV_CTRL_XD);
pconf->timing.clk_ctrl =
(cconf->pll_frac << CLK_CTRL_FRAC);
cconf->done = 1;
} else {
pconf->timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_N) |
(50 << PLL_CTRL_M);
pconf->timing.div_ctrl =
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(7 << DIV_CTRL_XD);
pconf->timing.clk_ctrl = (0 << CLK_CTRL_FRAC);
cconf->done = 0;
LCDERR("Out of clock range\n");
}
}
static void lcd_pll_frac_generate_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int pll_fout;
unsigned int od, pll_fvco;
unsigned int m, n, od_fb, frac, offset, temp;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->fout = pconf->timing.lcd_clk / 1000; /* kHz */
od = od_table[cconf->pll_od1_sel];
m = cconf->pll_m;
n = cconf->pll_n;
od_fb = cconf->pll_od_fb;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("m=%d, n=%d, od=%d, xd=%d\n", m, n, cconf->pll_od1_sel, cconf->xd);
if (cconf->fout > cconf->data->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n", __func__, cconf->fout);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pclk=%d\n", __func__, cconf->fout);
pll_fout = cconf->fout * cconf->xd;
if (pll_fout > cconf->data->pll_out_fmax ||
pll_fout < cconf->data->pll_out_fmin) {
LCDERR("%s: wrong pll_fout value %dkHz\n", __func__, pll_fout);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pll_fout=%d\n", __func__, pll_fout);
pll_fvco = pll_fout * od;
if (pll_fvco < cconf->data->pll_vco_fmin ||
pll_fvco > cconf->data->pll_vco_fmax) {
LCDERR("%s: wrong pll_fvco value %dkHz\n", __func__, pll_fvco);
return;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("%s pll_fvco=%d\n", __func__, pll_fvco);
cconf->pll_fvco = pll_fvco;
pll_fvco = pll_fvco / od_fb_table[od_fb];
temp = cconf->fin * m / n;
if (pll_fvco >= temp) {
temp = pll_fvco - temp;
offset = 0;
} else {
temp = temp - pll_fvco;
offset = 1;
}
if (temp >= (2 * cconf->fin)) {
LCDERR("%s: pll changing %dkHz is too much\n", __func__, temp);
return;
}
frac = temp * cconf->data->pll_frac_range * n / cconf->fin;
cconf->pll_frac = frac | (offset << 11);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_pll_frac_generate: frac=0x%x\n", frac);
}
static void lcd_clk_generate_hpll_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_config_s *pconf = &pdrv->config;
unsigned int pll_fout;
unsigned int clk_div_sel, xd;
unsigned int dsi_bit_rate_max = 0, dsi_bit_rate_min = 0;
unsigned int tmp;
int done = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->fout = pconf->timing.lcd_clk / 1000; /* kHz */
cconf->err_fmin = MAX_ERROR;
if (cconf->fout > cconf->data->xd_out_fmax)
LCDERR("%s: wrong lcd_clk value %dkHz\n", __func__, cconf->fout);
switch (pconf->basic.lcd_type) {
case LCD_MIPI:
cconf->xd_max = CRT_VID_DIV_MAX;
tmp = pconf->control.mipi_cfg.bit_rate_max;
dsi_bit_rate_max = tmp * 1000; /* change to kHz */
dsi_bit_rate_min = dsi_bit_rate_max - cconf->fout;
clk_div_sel = CLK_DIV_SEL_1;
for (xd = 1; xd <= cconf->xd_max; xd++) {
pll_fout = cconf->fout * xd;
if (pll_fout > dsi_bit_rate_max ||
pll_fout < dsi_bit_rate_min) {
continue;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK)
LCDPR("fout=%d, xd=%d\n", cconf->fout, xd);
pconf->timing.bit_rate = pll_fout * 1000;
pconf->control.mipi_cfg.clk_factor = xd;
cconf->xd = xd;
cconf->div_sel = clk_div_sel;
done = check_pll_3od(cconf, pll_fout);
if (done)
goto generate_clk_done_hpll_g12a;
}
break;
default:
break;
}
generate_clk_done_hpll_g12a:
if (done) {
pconf->timing.pll_ctrl =
(cconf->pll_od1_sel << PLL_CTRL_OD1) |
(cconf->pll_od2_sel << PLL_CTRL_OD2) |
(cconf->pll_od3_sel << PLL_CTRL_OD3) |
(cconf->pll_n << PLL_CTRL_N) |
(cconf->pll_m << PLL_CTRL_M);
pconf->timing.div_ctrl =
(cconf->div_sel << DIV_CTRL_DIV_SEL) |
(cconf->xd << DIV_CTRL_XD);
pconf->timing.clk_ctrl =
(cconf->pll_frac << CLK_CTRL_FRAC);
cconf->done = 1;
} else {
pconf->timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_OD2) |
(1 << PLL_CTRL_OD3) |
(1 << PLL_CTRL_N) |
(50 << PLL_CTRL_M);
pconf->timing.div_ctrl =
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(7 << DIV_CTRL_XD);
pconf->timing.clk_ctrl = (0 << CLK_CTRL_FRAC);
cconf->done = 0;
LCDERR("Out of clock range\n");
}
}
/* ****************************************************
* lcd clk match function
* ****************************************************
*/
static void lcd_clk_set_g12a_path0(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_set_hpll_g12a(pdrv);
lcd_set_vid_pll_div(cconf);
lcd_set_dsi_meas_clk();
lcd_set_dsi_phy_clk(0);
}
static void lcd_clk_set_g12a_path1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_set_gp0_pll_g12a(pdrv);
lcd_set_dsi_meas_clk();
lcd_set_dsi_phy_clk(1);
}
static void lcd_clk_set_g12b_path0(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_set_hpll_g12b(pdrv);
lcd_set_vid_pll_div(cconf);
lcd_set_dsi_meas_clk();
lcd_set_dsi_phy_clk(0);
}
static void lcd_clk_set_g12b_path1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_set_gp0_pll_g12b(pdrv);
lcd_set_dsi_meas_clk();
lcd_set_dsi_phy_clk(1);
}
static void lcd_clk_set_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_set_pll_tl1(pdrv);
lcd_set_vid_pll_div(cconf);
}
static void lcd_clk_set_t7(struct aml_lcd_drv_s *pdrv)
{
lcd_set_pll_t7(pdrv);
lcd_set_phy_dig_div_t7(pdrv);
lcd_set_vid_pll_div_t7(pdrv);
if (pdrv->config.basic.lcd_type == LCD_MIPI) {
lcd_set_dsi_meas_clk_t7(pdrv->index);
lcd_set_dsi_phy_clk_t7(pdrv->index);
}
}
static void lcd_clk_set_t3(struct aml_lcd_drv_s *pdrv)
{
lcd_set_pll_t3(pdrv);
lcd_set_vid_pll_div_t3(pdrv);
}
static void lcd_clk_disable_dft(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
int i = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
lcd_clk_setb(HHI_VID_CLK_CNTL2, 0, ENCL_GATE_VCLK, 1);
/* close vclk2_div gate: 0x104b[4:0] */
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, 0, 5);
lcd_clk_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1);
if (!cconf->data->pll_ctrl_table)
return;
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_END)
break;
if (table[i].flag == LCD_CLK_CTRL_EN)
lcd_ana_setb(table[i].reg, 0, table[i].bit, table[i].len);
else if (table[i].flag == LCD_CLK_CTRL_RST)
lcd_ana_setb(table[i].reg, 1, table[i].bit, table[i].len);
i++;
}
}
static void lcd_clk_disable_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
unsigned int reg_vid_clk_ctrl2, reg_vid2_clk_ctrl, offset;
int i = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
switch (cconf->pll_id) {
case 1:
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK1_CTRL2;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK1_CTRL;
break;
case 2:
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK2_CTRL2;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK2_CTRL;
break;
case 0:
default:
reg_vid_clk_ctrl2 = CLKCTRL_VID_CLK0_CTRL2;
reg_vid2_clk_ctrl = CLKCTRL_VIID_CLK0_CTRL;
break;
}
offset = cconf->pll_offset;
lcd_clk_setb(reg_vid_clk_ctrl2, 0, ENCL_GATE_VCLK, 1);
/* close vclk2_div gate: [4:0] */
lcd_clk_setb(reg_vid2_clk_ctrl, 0, 0, 5);
lcd_clk_setb(reg_vid2_clk_ctrl, 0, VCLK2_EN, 1);
if (!cconf->data->pll_ctrl_table)
return;
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_END)
break;
if (table[i].flag == LCD_CLK_CTRL_EN)
lcd_ana_setb(table[i].reg + offset, 0, table[i].bit, table[i].len);
else if (table[i].flag == LCD_CLK_CTRL_RST)
lcd_ana_setb(table[i].reg + offset, 1, table[i].bit, table[i].len);
i++;
}
}
static void lcd_clk_gate_switch_dft(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (status) {
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: encl_top_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.encl_top_gate);
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: encl_int_gata\n", __func__);
else
clk_prepare_enable(cconf->clktree.encl_int_gate);
} else {
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: encl_int_gata\n", __func__);
else
clk_disable_unprepare(cconf->clktree.encl_int_gate);
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: encl_top_gata\n", __func__);
else
clk_disable_unprepare(cconf->clktree.encl_top_gate);
}
}
static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (status) {
if (cconf->data->vclk_sel) {
if (IS_ERR_OR_NULL(cconf->clktree.gp0_pll))
LCDERR("%s: gp0_pll\n", __func__);
else
clk_prepare_enable(cconf->clktree.gp0_pll);
}
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: dsi_host_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_host_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: dsi_phy_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_phy_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: dsi_meas\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_meas);
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: encl_top_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.encl_top_gate);
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: encl_int_gata\n", __func__);
else
clk_prepare_enable(cconf->clktree.encl_int_gate);
} else {
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: dsi_host_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_host_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: dsi_phy_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_phy_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: dsi_meas\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_meas);
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: encl_int_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.encl_int_gate);
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: encl_top_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.encl_top_gate);
if (cconf->data->vclk_sel) {
if (IS_ERR_OR_NULL(cconf->clktree.gp0_pll))
LCDERR("%s: gp0_pll\n", __func__);
else
clk_disable_unprepare(cconf->clktree.gp0_pll);
}
}
}
static void lcd_clk_gate_switch_t7(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (status) {
switch (pdrv->config.basic.lcd_type) {
case LCD_MIPI:
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: dsi_host_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_host_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: dsi_phy_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_phy_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: dsi_meas\n", __func__);
else
clk_prepare_enable(cconf->clktree.dsi_meas);
break;
default:
break;
}
} else {
switch (pdrv->config.basic.lcd_type) {
case LCD_MIPI:
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: dsi_host_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_host_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: dsi_phy_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_phy_gate);
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: dsi_meas\n", __func__);
else
clk_disable_unprepare(cconf->clktree.dsi_meas);
break;
default:
break;
}
}
}
static void lcd_clk_gate_optional_switch_tl1(struct aml_lcd_drv_s *pdrv,
int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (status) {
switch (pdrv->config.basic.lcd_type) {
case LCD_MLVDS:
case LCD_P2P:
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
LCDERR("%s: tcon_gate\n", __func__);
else
clk_prepare_enable(cconf->clktree.tcon_gate);
if (IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
LCDERR("%s: tcon_clk\n", __func__);
else
clk_prepare_enable(cconf->clktree.tcon_clk);
cconf->clktree.clk_gate_optional_state = 1;
break;
default:
break;
}
} else {
switch (pdrv->config.basic.lcd_type) {
case LCD_MLVDS:
case LCD_P2P:
if (IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
LCDERR("%s: tcon_clk\n", __func__);
else
clk_disable_unprepare(cconf->clktree.tcon_clk);
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
LCDERR("%s: tcon_gate\n", __func__);
else
clk_disable_unprepare(cconf->clktree.tcon_gate);
cconf->clktree.clk_gate_optional_state = 0;
break;
default:
break;
}
}
}
static void lcd_clktree_probe_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->clktree.clk_gate_state = 0;
cconf->clktree.dsi_host_gate = devm_clk_get(pdrv->dev, "dsi_host_gate");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: clk dsi_host_gate\n", __func__);
cconf->clktree.dsi_phy_gate = devm_clk_get(pdrv->dev, "dsi_phy_gate");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: clk dsi_phy_gate\n", __func__);
cconf->clktree.dsi_meas = devm_clk_get(pdrv->dev, "dsi_meas");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: clk dsi_meas\n", __func__);
cconf->clktree.encl_top_gate = devm_clk_get(pdrv->dev, "encl_top_gate");
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: clk encl_top_gate\n", __func__);
cconf->clktree.encl_int_gate = devm_clk_get(pdrv->dev, "encl_int_gate");
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: clk encl_int_gate\n", __func__);
cconf->clktree.gp0_pll = devm_clk_get(pdrv->dev, "gp0_pll");
if (IS_ERR_OR_NULL(cconf->clktree.gp0_pll))
LCDERR("%s: clk gp0_pll\n", __func__);
LCDPR("lcd_clktree_probe\n");
}
static void lcd_clktree_probe_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct clk *temp_clk;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->clktree.clk_gate_state = 0;
cconf->clktree.encl_top_gate = devm_clk_get(pdrv->dev, "encl_top_gate");
if (IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
LCDERR("%s: get encl_top_gate error\n", __func__);
cconf->clktree.encl_int_gate = devm_clk_get(pdrv->dev, "encl_int_gate");
if (IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
LCDERR("%s: get encl_int_gate error\n", __func__);
cconf->clktree.tcon_gate = devm_clk_get(pdrv->dev, "tcon_gate");
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
LCDERR("%s: get tcon_gate error\n", __func__);
temp_clk = devm_clk_get(pdrv->dev, "fclk_div5");
if (IS_ERR_OR_NULL(temp_clk)) {
LCDERR("%s: clk fclk_div5\n", __func__);
return;
}
cconf->clktree.tcon_clk = devm_clk_get(pdrv->dev, "clk_tcon");
if (IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
LCDERR("%s: clk clk_tcon\n", __func__);
else
clk_set_parent(cconf->clktree.tcon_clk, temp_clk);
LCDPR("lcd_clktree_probe\n");
}
static void lcd_clktree_probe_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
cconf->clktree.clk_gate_state = 0;
cconf->clktree.dsi_host_gate = devm_clk_get(pdrv->dev, "dsi_host_gate");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
LCDERR("%s: clk dsi_host_gate\n", __func__);
cconf->clktree.dsi_phy_gate = devm_clk_get(pdrv->dev, "dsi_phy_gate");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
LCDERR("%s: clk dsi_phy_gate\n", __func__);
cconf->clktree.dsi_meas = devm_clk_get(pdrv->dev, "dsi_meas");
if (IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
LCDERR("%s: clk dsi_meas\n", __func__);
LCDPR("lcd_clktree_probe\n");
}
static void lcd_clktree_probe_t3(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct clk *temp_clk;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (pdrv->index > 0) /* tcon_clk invalid for lcd1 */
return;
cconf->clktree.clk_gate_state = 0;
cconf->clktree.tcon_gate = devm_clk_get(pdrv->dev, "tcon_gate");
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
LCDERR("%s: get tcon_gate error\n", __func__);
temp_clk = devm_clk_get(pdrv->dev, "fclk_div5");
if (IS_ERR_OR_NULL(temp_clk)) {
LCDERR("%s: clk fclk_div5\n", __func__);
return;
}
cconf->clktree.tcon_clk = devm_clk_get(pdrv->dev, "clk_tcon");
if (IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
LCDERR("%s: clk clk_tcon\n", __func__);
else
clk_set_parent(cconf->clktree.tcon_clk, temp_clk);
LCDPR("lcd_clktree_probe\n");
}
static void lcd_clktree_remove_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_clktree_remove\n");
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_host_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_phy_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_meas);
if (!IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
devm_clk_put(pdrv->dev, cconf->clktree.encl_top_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
devm_clk_put(pdrv->dev, cconf->clktree.encl_int_gate);
}
static void lcd_clktree_remove_tl1(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_clktree_remove\n");
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (!IS_ERR_OR_NULL(cconf->clktree.encl_top_gate))
devm_clk_put(pdrv->dev, cconf->clktree.encl_top_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.encl_int_gate))
devm_clk_put(pdrv->dev, cconf->clktree.encl_int_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
devm_clk_put(pdrv->dev, cconf->clktree.tcon_clk);
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
devm_clk_put(pdrv->dev, cconf->clktree.tcon_gate);
}
static void lcd_clktree_remove_t7(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_clktree_remove\n");
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_host_gate))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_host_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_phy_gate))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_phy_gate);
if (!IS_ERR_OR_NULL(cconf->clktree.dsi_meas))
devm_clk_put(pdrv->dev, cconf->clktree.dsi_meas);
}
static void lcd_clktree_remove_t3(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("lcd_clktree_remove\n");
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (pdrv->index > 0) /* tcon_clk invalid for lcd1 */
return;
if (!IS_ERR_OR_NULL(cconf->clktree.tcon_clk))
devm_clk_put(pdrv->dev, cconf->clktree.tcon_clk);
if (IS_ERR_OR_NULL(cconf->clktree.tcon_gate))
devm_clk_put(pdrv->dev, cconf->clktree.tcon_gate);
}
static void lcd_clk_config_init_print_dft(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_data_s *data;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
data = cconf->data;
LCDPR("lcd%d clk config data init:\n"
"pll_m_max: %d\n"
"pll_m_min: %d\n"
"pll_n_max: %d\n"
"pll_n_min: %d\n"
"pll_od_fb: %d\n"
"pll_frac_range: %d\n"
"pll_od_sel_max: %d\n"
"pll_ref_fmax: %d\n"
"pll_ref_fmin: %d\n"
"pll_vco_fmax: %d\n"
"pll_vco_fmin: %d\n"
"pll_out_fmax: %d\n"
"pll_out_fmin: %d\n"
"div_in_fmax: %d\n"
"div_out_fmax: %d\n"
"xd_out_fmax: %d\n"
"ss_level_max: %d\n"
"ss_freq_max: %d\n"
"ss_mode_max: %d\n\n",
pdrv->index,
data->pll_m_max, data->pll_m_min,
data->pll_n_max, data->pll_n_min,
data->pll_od_fb, data->pll_frac_range,
data->pll_od_sel_max,
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->div_in_fmax, data->div_out_fmax,
data->xd_out_fmax, data->ss_level_max,
data->ss_freq_max, data->ss_mode_max);
}
static void lcd_clk_config_init_print_g12a(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_data_s *data;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
data = cconf->data;
LCDPR("lcd clk config data init:\n"
"vclk_sel: %d\n"
"pll_m_max: %d\n"
"pll_m_min: %d\n"
"pll_n_max: %d\n"
"pll_n_min: %d\n"
"pll_od_fb: %d\n"
"pll_frac_range: %d\n"
"pll_od_sel_max: %d\n"
"pll_ref_fmax: %d\n"
"pll_ref_fmin: %d\n"
"pll_vco_fmax: %d\n"
"pll_vco_fmin: %d\n"
"pll_out_fmax: %d\n"
"pll_out_fmin: %d\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,
data->pll_od_fb, data->pll_frac_range,
data->pll_od_sel_max,
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);
}
static int lcd_clk_config_print_dft(struct aml_lcd_drv_s *pdrv, char *buf, int offset)
{
struct lcd_clk_config_s *cconf;
int n, len = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return -1;
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n,
"lcd%d clk config:\n"
"pll_id: %d\n"
"pll_offset: %d\n"
"pll_mode: %d\n"
"pll_m: %d\n"
"pll_n: %d\n"
"pll_frac: 0x%03x\n"
"pll_frac_half_shift: %d\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"
"edp_div0: %d\n"
"edp_div1: %d\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"
"ss_en: %d\n",
pdrv->index,
cconf->pll_id, cconf->pll_offset,
cconf->pll_mode, cconf->pll_m, cconf->pll_n,
cconf->pll_frac, cconf->pll_frac_half_shift,
cconf->pll_fvco,
cconf->pll_od1_sel, cconf->pll_od2_sel,
cconf->pll_od3_sel, cconf->pll_tcon_div_sel,
cconf->pll_fout,
cconf->edp_div0, cconf->edp_div1,
lcd_clk_div_sel_table[cconf->div_sel],
cconf->div_sel, cconf->xd,
cconf->fout, cconf->ss_level,
cconf->ss_freq, cconf->ss_mode, cconf->ss_en);
return len;
}
static int lcd_clk_config_print_g12a(struct aml_lcd_drv_s *pdrv, char *buf, int offset)
{
struct lcd_clk_config_s *cconf;
int n, len = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return -1;
n = lcd_debug_info_len(len + offset);
if (cconf->data->vclk_sel) {
len += snprintf((buf + len), n,
"lcd clk config:\n"
"vclk_sel %d\n"
"pll_m: %d\n"
"pll_n: %d\n"
"pll_frac: 0x%03x\n"
"pll_fvco: %dkHz\n"
"pll_od: %d\n"
"pll_out: %dkHz\n"
"xd: %d\n"
"fout: %dkHz\n\n",
cconf->data->vclk_sel,
cconf->pll_m, cconf->pll_n,
cconf->pll_frac, cconf->pll_fvco,
cconf->pll_od1_sel, cconf->pll_fout,
cconf->xd, cconf->fout);
} else {
len += snprintf((buf + len), n,
"lcd clk config:\n"
"vclk_sel %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_out: %dkHz\n"
"div_sel: %s(index %d)\n"
"xd: %d\n"
"fout: %dkHz\n\n",
cconf->data->vclk_sel,
cconf->pll_m, cconf->pll_n,
cconf->pll_frac, cconf->pll_fvco,
cconf->pll_od1_sel, cconf->pll_od2_sel,
cconf->pll_od3_sel, cconf->pll_fout,
lcd_clk_div_sel_table[cconf->div_sel],
cconf->div_sel, cconf->xd,
cconf->fout);
}
return len;
}
/* ****************************************************
* lcd clk function api
* ****************************************************
*/
void lcd_clk_generate_parameter(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned int ss_level, ss_freq, ss_mode;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (cconf->data->clk_generate_parameter)
cconf->data->clk_generate_parameter(pdrv);
ss_level = pdrv->config.timing.ss_level;
cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? 0 : ss_level;
ss_freq = pdrv->config.timing.ss_freq;
cconf->ss_freq = (ss_freq >= cconf->data->ss_freq_max) ? 0 : ss_freq;
ss_mode = pdrv->config.timing.ss_mode;
cconf->ss_mode = (ss_mode >= cconf->data->ss_mode_max) ? 0 : ss_mode;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("[%d]: %s: ss_level=%d, ss_freq=%d, ss_mode=%d\n",
pdrv->index, __func__,
cconf->ss_level, cconf->ss_freq, cconf->ss_mode);
}
}
int lcd_get_ss(struct aml_lcd_drv_s *pdrv, char *buf)
{
struct lcd_clk_config_s *cconf;
unsigned int temp;
int len = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf) {
len += sprintf(buf + len, "[%d]: clk config data is null\n", pdrv->index);
return len;
}
if (cconf->data->ss_level_max == 0) {
len += sprintf(buf + len, "[%d]: spread spectrum is invalid\n", pdrv->index);
return len;
}
temp = (cconf->ss_level >= cconf->data->ss_level_max) ?
0 : cconf->ss_level;
if (cconf->data->ss_level_table)
len += sprintf(buf + len, "ss_level: %s\n", cconf->data->ss_level_table[temp]);
temp = (cconf->ss_freq >= cconf->data->ss_freq_max) ? 0 : cconf->ss_freq;
if (cconf->data->ss_freq_table)
len += sprintf(buf + len, "ss_freq: %s\n", cconf->data->ss_freq_table[temp]);
temp = (cconf->ss_mode >= cconf->data->ss_mode_max) ? 0 : cconf->ss_mode;
if (cconf->data->ss_mode_table)
len += sprintf(buf + len, "ss_mode: %s\n", cconf->data->ss_mode_table[temp]);
return len;
}
void lcd_clk_ss_config_update(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf = get_lcd_clk_config(pdrv);
unsigned int temp;
if (!cconf || !cconf->data)
return;
temp = pdrv->config.timing.ss_level & 0xff;
cconf->ss_level = (temp >= cconf->data->ss_level_max) ? 0 : temp;
temp = (pdrv->config.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 = (pdrv->config.timing.ss_level >> 8) & 0xff;
temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf;
cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? 0 : temp;
}
int lcd_set_ss(struct aml_lcd_drv_s *pdrv, unsigned int level, unsigned int freq, unsigned int mode)
{
struct lcd_clk_config_s *cconf;
unsigned long flags = 0;
int ret = -1;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return -1;
spin_lock_irqsave(&lcd_clk_lock, flags);
if (level < 0xff) {
if (level >= cconf->data->ss_level_max) {
LCDERR("[%d]: %s: ss_level %d is out of support (max %d)\n",
pdrv->index, __func__, level,
(cconf->data->ss_level_max - 1));
goto lcd_set_ss_end;
}
}
if (freq < 0xff) {
if (freq >= cconf->data->ss_freq_max) {
LCDERR("[%d]: %s: ss_freq %d is out of support (max %d)\n",
pdrv->index, __func__, freq,
(cconf->data->ss_freq_max - 1));
goto lcd_set_ss_end;
}
}
if (mode < 0xff) {
if (mode >= cconf->data->ss_mode_max) {
LCDERR("[%d]: %s: ss_mode %d is out of support (max %d)\n",
pdrv->index, __func__, mode,
(cconf->data->ss_mode_max - 1));
goto lcd_set_ss_end;
}
}
if (cconf->data->set_ss_level) {
if (level < 0xff) {
if (level > cconf->data->ss_level_max)
cconf->ss_level = cconf->data->ss_level_max;
else
cconf->ss_level = level;
cconf->data->set_ss_level(pdrv);
}
}
ret = 0;
if (cconf->data->set_ss_advance) {
if (freq == 0xff && mode == 0xff)
goto lcd_set_ss_end;
if (freq < 0xff) {
if (freq > cconf->data->ss_freq_max)
cconf->ss_freq = cconf->data->ss_freq_max;
else
cconf->ss_freq = freq;
}
if (mode < 0xff) {
if (mode > cconf->data->ss_mode_max)
cconf->ss_mode = cconf->data->ss_mode_max;
else
cconf->ss_mode = mode;
}
cconf->data->set_ss_advance(pdrv);
}
lcd_set_ss_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
return ret;
}
/* design for vlock, don't save ss_level to clk_config */
int lcd_ss_enable(int index, unsigned int flag)
{
struct aml_lcd_drv_s *pdrv;
struct lcd_clk_config_s *cconf;
unsigned long flags = 0;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", index, __func__);
spin_lock_irqsave(&lcd_clk_lock, flags);
pdrv = aml_lcd_get_driver(index);
if (!pdrv) {
LCDERR("[%d]: %s: drv is null\n", index, __func__);
goto lcd_ss_enable_end;
}
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
goto lcd_ss_enable_end;
if (cconf->data->clk_ss_enable)
cconf->data->clk_ss_enable(pdrv, flag);
lcd_ss_enable_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
return 0;
}
int lcd_encl_clk_msr(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
int clk_mux;
int encl_clk = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return 0;
clk_mux = cconf->data->enc_clk_msr_id;
if (clk_mux == -1)
return 0;
encl_clk = meson_clk_measure(clk_mux);
return encl_clk;
}
void lcd_pll_reset(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
int i = 0;
unsigned long flags = 0;
spin_lock_irqsave(&lcd_clk_lock, flags);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
goto lcd_pll_reset_end;
if (!cconf->data->pll_ctrl_table)
goto lcd_pll_reset_end;
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_END)
break;
if (table[i].flag == LCD_CLK_CTRL_RST) {
lcd_ana_setb(table[i].reg, 1, table[i].bit, table[i].len);
udelay(10);
lcd_ana_setb(table[i].reg, 0, table[i].bit, table[i].len);
}
i++;
}
lcd_pll_reset_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
LCDPR("[%d]: %s\n", pdrv->index, __func__);
}
void lcd_vlock_m_update(int index, unsigned int vlock_m)
{
struct aml_lcd_drv_s *pdrv;
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
int i = 0;
unsigned long flags = 0;
spin_lock_irqsave(&lcd_clk_lock, flags);
pdrv = aml_lcd_get_driver(index);
if (!pdrv) {
LCDERR("[%d]: %s: drv is null\n", index, __func__);
goto lcd_vlock_m_update_end;
}
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
goto lcd_vlock_m_update_end;
if (!cconf->data->pll_ctrl_table) {
LCDERR("[%d]: %s: pll_ctrl_table null\n",
index, __func__);
goto lcd_vlock_m_update_end;
}
vlock_m &= 0xff;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("[%d]: %s, vlcok_m: 0x%x,",
index, __func__, vlock_m);
}
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_M) {
lcd_ana_setb(table[i].reg, vlock_m, table[i].bit, table[i].len);
break;
}
i++;
}
lcd_vlock_m_update_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
}
void lcd_vlock_frac_update(int index, unsigned int vlock_frac)
{
struct aml_lcd_drv_s *pdrv;
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
int i = 0;
unsigned long flags = 0;
spin_lock_irqsave(&lcd_clk_lock, flags);
pdrv = aml_lcd_get_driver(index);
if (!pdrv) {
LCDERR("[%d]: %s: drv is null\n", index, __func__);
goto lcd_vlock_frac_update_end;
}
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
goto lcd_vlock_frac_update_end;
if (!cconf->data->pll_ctrl_table) {
LCDERR("[%d]: %s: pll_ctrl_table null\n",
index, __func__);
goto lcd_vlock_frac_update_end;
}
vlock_frac &= 0x1ffff;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
LCDPR("[%d]: %s, vlock_frac: 0x%x\n",
index, __func__, vlock_frac);
}
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_FRAC) {
lcd_ana_setb(table[i].reg, vlock_frac, table[i].bit, table[i].len);
break;
}
i++;
}
lcd_vlock_frac_update_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
}
/* for frame rate change */
void lcd_update_clk(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
struct lcd_clk_ctrl_s *table;
unsigned int offset;
int i = 0;
unsigned long flags = 0;
spin_lock_irqsave(&lcd_clk_lock, flags);
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
goto lcd_clk_update_end;
if (cconf->data->pll_frac_generate)
cconf->data->pll_frac_generate(pdrv);
offset = cconf->pll_offset;
if (!cconf->data->pll_ctrl_table)
goto lcd_clk_update_end;
table = cconf->data->pll_ctrl_table;
while (i < LCD_CLK_CTRL_CNT_MAX) {
if (table[i].flag == LCD_CLK_CTRL_END)
break;
if (table[i].flag == LCD_CLK_CTRL_FRAC) {
lcd_ana_setb(table[i].reg + offset, cconf->pll_frac,
table[i].bit, table[i].len);
}
i++;
}
lcd_clk_update_end:
spin_unlock_irqrestore(&lcd_clk_lock, flags);
LCDPR("[%d]: %s\n", pdrv->index, __func__);
}
/* for timing change */
void lcd_set_clk(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
unsigned long flags = 0;
int cnt = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (pdrv->lcd_pxp) {
if (cconf->data->vclk_crt_set)
cconf->data->vclk_crt_set(pdrv);
return;
}
lcd_set_clk_retry:
spin_lock_irqsave(&lcd_clk_lock, flags);
if (cconf->data->clk_set)
cconf->data->clk_set(pdrv);
if (cconf->data->vclk_crt_set)
cconf->data->vclk_crt_set(pdrv);
spin_unlock_irqrestore(&lcd_clk_lock, flags);
usleep_range(10000, 10001);
while (lcd_clk_msr_check(pdrv)) {
if (cnt++ >= 10) {
LCDERR("[%d]: %s timeout\n", pdrv->index, __func__);
break;
}
goto lcd_set_clk_retry;
}
if (cconf->data->clktree_set)
cconf->data->clktree_set(pdrv);
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
}
void lcd_disable_clk(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (cconf->data->clk_disable)
cconf->data->clk_disable(pdrv);
LCDPR("[%d]: %s\n", pdrv->index, __func__);
}
static void lcd_clk_gate_optional_switch(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (!cconf->data->clk_gate_optional_switch)
return;
if (status) {
if (cconf->clktree.clk_gate_optional_state) {
LCDPR("[%d]: clk_gate_optional is already on\n",
pdrv->index);
} else {
cconf->data->clk_gate_optional_switch(pdrv, 1);
}
} else {
if (cconf->clktree.clk_gate_optional_state == 0) {
LCDPR("[%d]: clk_gate_optional is already off\n",
pdrv->index);
} else {
cconf->data->clk_gate_optional_switch(pdrv, 0);
}
}
}
void lcd_clk_gate_switch(struct aml_lcd_drv_s *pdrv, int status)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return;
if (status) {
if (cconf->clktree.clk_gate_state) {
LCDPR("[%d]: clk_gate is already on\n", pdrv->index);
} else {
#ifdef CONFIG_AMLOGIC_VPU
vpu_dev_clk_gate_on(pdrv->lcd_vpu_dev);
#endif
if (cconf->data->clk_gate_switch)
cconf->data->clk_gate_switch(pdrv, 1);
cconf->clktree.clk_gate_state = 1;
}
lcd_clk_gate_optional_switch(pdrv, 1);
} else {
lcd_clk_gate_optional_switch(pdrv, 0);
if (cconf->clktree.clk_gate_state == 0) {
LCDPR("[%d]: clk_gate is already off\n", pdrv->index);
} else {
if (cconf->data->clk_gate_switch)
cconf->data->clk_gate_switch(pdrv, 0);
#ifdef CONFIG_AMLOGIC_VPU
vpu_dev_clk_gate_off(pdrv->lcd_vpu_dev);
#endif
cconf->clktree.clk_gate_state = 0;
}
}
}
int lcd_clk_clkmsr_print(struct aml_lcd_drv_s *pdrv, char *buf, int offset)
{
struct lcd_clk_config_s *cconf;
int clk;
int n, len = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n, "[%d]: %s: clk config is null\n",
pdrv->index, __func__);
return len;
}
if (cconf->data->enc_clk_msr_id == -1)
goto lcd_clk_clkmsr_print_step_1;
clk = meson_clk_measure(cconf->data->enc_clk_msr_id);
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n,
"encl_clk: %d\n", clk);
lcd_clk_clkmsr_print_step_1:
if (cconf->data->fifo_clk_msr_id == -1)
goto lcd_clk_clkmsr_print_step_2;
clk = meson_clk_measure(cconf->data->fifo_clk_msr_id);
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n,
"fifo_clk: %d\n", clk);
lcd_clk_clkmsr_print_step_2:
switch (pdrv->config.basic.lcd_type) {
case LCD_MLVDS:
case LCD_P2P:
if (cconf->data->tcon_clk_msr_id == -1)
break;
clk = meson_clk_measure(cconf->data->tcon_clk_msr_id);
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n,
"tcon_clk: %d\n", clk);
default:
break;
}
return len;
}
int lcd_clk_config_print(struct aml_lcd_drv_s *pdrv, char *buf, int offset)
{
struct lcd_clk_config_s *cconf;
int n, len = 0;
cconf = get_lcd_clk_config(pdrv);
if (!cconf) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf + len), n, "[%d]: %s: clk config is null\n",
pdrv->index, __func__);
return len;
}
if (cconf->data->clk_config_print)
len = cconf->data->clk_config_print(pdrv, buf, offset);
return len;
}
/* ****************************************************
* lcd clk config
* ****************************************************
*/
static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = {
.pll_od_fb = PLL_OD_FB_HPLL_G12A,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_HPLL_G12A,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_HPLL_G12A,
.pll_od_sel_max = PLL_OD_SEL_MAX_HPLL_G12A,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_HPLL_G12A,
.pll_vco_fmin = PLL_VCO_MIN_HPLL_G12A,
.pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.pll_out_fmin = PLL_VCO_MIN_HPLL_G12A / 16,
.div_in_fmax = 0,
.div_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.xd_out_fmax = ENCL_CLK_IN_MAX_G12A,
.clk_path_valid = 1,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = LCD_CLK_MSR_INVALID,
.pll_ctrl_table = pll_ctrl_table_g12a_path0,
.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_dft,
.set_ss_level = NULL,
.set_ss_advance = NULL,
.clk_ss_enable = NULL,
.clk_set = lcd_clk_set_g12a_path0,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_g12a,
.clk_gate_optional_switch = NULL,
.clktree_set = NULL,
.clktree_probe = lcd_clktree_probe_g12a,
.clktree_remove = lcd_clktree_remove_g12a,
.clk_config_init_print = lcd_clk_config_init_print_g12a,
.clk_config_print = lcd_clk_config_print_g12a,
.prbs_clk_config = NULL,
};
static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = {
.pll_od_fb = PLL_OD_FB_GP0_G12A,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_GP0_G12A,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_GP0_G12A,
.pll_od_sel_max = PLL_OD_SEL_MAX_GP0_G12A,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_GP0_G12A,
.pll_vco_fmin = PLL_VCO_MIN_GP0_G12A,
.pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.pll_out_fmin = PLL_VCO_MIN_GP0_G12A / 16,
.div_in_fmax = 0,
.div_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.xd_out_fmax = ENCL_CLK_IN_MAX_G12A,
.clk_path_valid = 1,
.vclk_sel = 1,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = LCD_CLK_MSR_INVALID,
.pll_ctrl_table = pll_ctrl_table_g12a_path1,
.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_g12a,
.pll_frac_generate = lcd_pll_frac_generate_g12a,
.set_ss_level = NULL,
.set_ss_advance = NULL,
.clk_ss_enable = NULL,
.clk_set = lcd_clk_set_g12a_path1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_g12a,
.clk_gate_optional_switch = NULL,
.clktree_set = NULL,
.clktree_probe = lcd_clktree_probe_g12a,
.clktree_remove = lcd_clktree_remove_g12a,
.clk_config_init_print = lcd_clk_config_init_print_g12a,
.clk_config_print = lcd_clk_config_print_g12a,
.prbs_clk_config = NULL,
};
static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = {
.pll_od_fb = PLL_OD_FB_HPLL_G12A,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_HPLL_G12A,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_HPLL_G12A,
.pll_od_sel_max = PLL_OD_SEL_MAX_HPLL_G12A,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_HPLL_G12A,
.pll_vco_fmin = PLL_VCO_MIN_HPLL_G12A,
.pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.pll_out_fmin = PLL_VCO_MIN_HPLL_G12A / 16,
.div_in_fmax = 0,
.div_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.xd_out_fmax = ENCL_CLK_IN_MAX_G12A,
.clk_path_valid = 1,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = LCD_CLK_MSR_INVALID,
.pll_ctrl_table = pll_ctrl_table_g12a_path0,
.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_dft,
.set_ss_level = NULL,
.set_ss_advance = NULL,
.clk_ss_enable = NULL,
.clk_set = lcd_clk_set_g12b_path0,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_g12a,
.clk_gate_optional_switch = NULL,
.clktree_set = NULL,
.clktree_probe = lcd_clktree_probe_g12a,
.clktree_remove = lcd_clktree_remove_g12a,
.clk_config_init_print = lcd_clk_config_init_print_g12a,
.clk_config_print = lcd_clk_config_print_g12a,
.prbs_clk_config = NULL,
};
static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = {
.pll_od_fb = PLL_OD_FB_GP0_G12A,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_GP0_G12A,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_GP0_G12A,
.pll_od_sel_max = PLL_OD_SEL_MAX_GP0_G12A,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_GP0_G12A,
.pll_vco_fmin = PLL_VCO_MIN_GP0_G12A,
.pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.pll_out_fmin = PLL_VCO_MIN_GP0_G12A / 16,
.div_in_fmax = 0,
.div_out_fmax = CRT_VID_CLK_IN_MAX_G12A,
.xd_out_fmax = ENCL_CLK_IN_MAX_G12A,
.clk_path_valid = 1,
.vclk_sel = 1,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = LCD_CLK_MSR_INVALID,
.pll_ctrl_table = pll_ctrl_table_g12a_path1,
.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_g12a,
.pll_frac_generate = lcd_pll_frac_generate_g12a,
.set_ss_level = NULL,
.set_ss_advance = NULL,
.clk_ss_enable = NULL,
.clk_set = lcd_clk_set_g12b_path1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_g12a,
.clk_gate_optional_switch = NULL,
.clktree_set = NULL,
.clktree_probe = lcd_clktree_probe_g12a,
.clktree_remove = lcd_clktree_remove_g12a,
.clk_config_init_print = lcd_clk_config_init_print_g12a,
.clk_config_print = lcd_clk_config_print_g12a,
.prbs_clk_config = NULL,
};
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
static struct lcd_clk_data_s lcd_clk_data_tl1 = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TL1,
.pll_vco_fmin = PLL_VCO_MIN_TL1,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = 129,
.tcon_clk_msr_id = 128,
.pll_ctrl_table = pll_ctrl_table_tl1,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_tl1,
.set_ss_advance = lcd_set_pll_ss_advance_tl1,
.clk_ss_enable = lcd_pll_ss_enable_tl1,
.clk_set = lcd_clk_set_tl1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_dft,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_tl1,
.clktree_probe = lcd_clktree_probe_tl1,
.clktree_remove = lcd_clktree_remove_tl1,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_tl1,
};
#endif
static struct lcd_clk_data_s lcd_clk_data_tm2 = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = 129,
.tcon_clk_msr_id = 128,
.pll_ctrl_table = pll_ctrl_table_tl1,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_tl1,
.set_ss_advance = lcd_set_pll_ss_advance_tl1,
.clk_ss_enable = lcd_pll_ss_enable_tl1,
.clk_set = lcd_clk_set_tl1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_dft,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_tl1,
.clktree_probe = lcd_clktree_probe_tl1,
.clktree_remove = lcd_clktree_remove_tl1,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_tl1,
};
static struct lcd_clk_data_s lcd_clk_data_t5 = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = 129,
.tcon_clk_msr_id = 128,
.pll_ctrl_table = pll_ctrl_table_tl1,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_tl1,
.set_ss_advance = lcd_set_pll_ss_advance_tl1,
.clk_ss_enable = lcd_pll_ss_enable_tl1,
.clk_set = lcd_clk_set_tl1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_dft,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_t5,
.clktree_probe = lcd_clktree_probe_tl1,
.clktree_remove = lcd_clktree_remove_tl1,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_tl1,
};
static struct lcd_clk_data_s lcd_clk_data_t5d = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_T5D,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.div_in_fmax = CLK_DIV_IN_MAX_T5D,
.div_out_fmax = CRT_VID_CLK_IN_MAX_T5D,
.xd_out_fmax = ENCL_CLK_IN_MAX_T5D,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 9,
.fifo_clk_msr_id = 129,
.tcon_clk_msr_id = 128,
.pll_ctrl_table = pll_ctrl_table_tl1,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_tl1,
.set_ss_advance = lcd_set_pll_ss_advance_tl1,
.clk_ss_enable = lcd_pll_ss_enable_tl1,
.clk_set = lcd_clk_set_tl1,
.vclk_crt_set = lcd_set_vclk_crt,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_dft,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_t5,
.clktree_probe = lcd_clktree_probe_tl1,
.clktree_remove = lcd_clktree_remove_tl1,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_tl1,
};
static struct lcd_clk_data_s lcd_clk_data_t7 = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 222,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = LCD_CLK_MSR_INVALID,
.pll_ctrl_table = pll_ctrl_table_t7,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_t7,
.set_ss_advance = lcd_set_pll_ss_advance_t7,
.clk_ss_enable = lcd_pll_ss_enable_t7,
.clk_set = lcd_clk_set_t7,
.vclk_crt_set = lcd_set_vclk_crt_t7,
.clk_disable = lcd_clk_disable_t7,
.clk_gate_switch = lcd_clk_gate_switch_t7,
.clk_gate_optional_switch = NULL,
.clktree_set = NULL,
.clktree_probe = lcd_clktree_probe_t7,
.clktree_remove = lcd_clktree_remove_t7,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_t7,
};
static struct lcd_clk_data_s lcd_clk_data_t3 = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 222,
.fifo_clk_msr_id = LCD_CLK_MSR_INVALID,
.tcon_clk_msr_id = 119,
.pll_ctrl_table = pll_ctrl_table_t7,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_t7,
.set_ss_advance = lcd_set_pll_ss_advance_t7,
.clk_ss_enable = lcd_pll_ss_enable_t7,
.clk_set = lcd_clk_set_t3,
.vclk_crt_set = lcd_set_vclk_crt_t7,
.clk_disable = lcd_clk_disable_t7,
.clk_gate_switch = lcd_clk_gate_switch_t7,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_t3,
.clktree_probe = lcd_clktree_probe_t3,
.clktree_remove = lcd_clktree_remove_t3,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_t3,
};
static struct lcd_clk_data_s lcd_clk_data_t5w = {
.pll_od_fb = PLL_OD_FB_TL1,
.pll_m_max = PLL_M_MAX,
.pll_m_min = PLL_M_MIN,
.pll_n_max = PLL_N_MAX,
.pll_n_min = PLL_N_MIN,
.pll_frac_range = PLL_FRAC_RANGE_TL1,
.pll_frac_sign_bit = PLL_FRAC_SIGN_BIT_TL1,
.pll_od_sel_max = PLL_OD_SEL_MAX_TL1,
.pll_ref_fmax = PLL_FREF_MAX,
.pll_ref_fmin = PLL_FREF_MIN,
.pll_vco_fmax = PLL_VCO_MAX_TM2,
.pll_vco_fmin = PLL_VCO_MIN_TM2,
.pll_out_fmax = CLK_DIV_IN_MAX_TL1,
.pll_out_fmin = PLL_VCO_MIN_TL1 / 16,
.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,
.clk_path_valid = 0,
.vclk_sel = 0,
.enc_clk_msr_id = 6,
.fifo_clk_msr_id = 129,
.tcon_clk_msr_id = 128,
.pll_ctrl_table = pll_ctrl_table_tl1,
.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_tl1,
.pll_frac_generate = lcd_pll_frac_generate_dft,
.set_ss_level = lcd_set_pll_ss_level_tl1,
.set_ss_advance = lcd_set_pll_ss_advance_tl1,
.clk_ss_enable = lcd_pll_ss_enable_tl1,
.clk_set = lcd_clk_set_tl1,
.vclk_crt_set = lcd_set_vclk_crt_t5w,
.clk_disable = lcd_clk_disable_dft,
.clk_gate_switch = lcd_clk_gate_switch_dft,
.clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1,
.clktree_set = lcd_set_tcon_clk_t5,
.clktree_probe = lcd_clktree_probe_tl1,
.clktree_remove = lcd_clktree_remove_tl1,
.clk_config_init_print = lcd_clk_config_init_print_dft,
.clk_config_print = lcd_clk_config_print_dft,
.prbs_clk_config = lcd_prbs_config_clk_tl1,
};
static void lcd_clk_config_chip_init(struct aml_lcd_drv_s *pdrv, struct lcd_clk_config_s *cconf)
{
cconf->pll_id = 0;
cconf->pll_offset = 0;
cconf->fin = FIN_FREQ;
switch (pdrv->data->chip_type) {
case LCD_CHIP_G12A:
case LCD_CHIP_SM1:
if (pdrv->clk_path)
cconf->data = &lcd_clk_data_g12a_path1;
else
cconf->data = &lcd_clk_data_g12a_path0;
break;
case LCD_CHIP_G12B:
if (pdrv->clk_path)
cconf->data = &lcd_clk_data_g12b_path1;
else
cconf->data = &lcd_clk_data_g12b_path0;
break;
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
case LCD_CHIP_TL1:
cconf->data = &lcd_clk_data_tl1;
break;
#endif
case LCD_CHIP_TM2:
cconf->data = &lcd_clk_data_tm2;
break;
case LCD_CHIP_T5:
cconf->data = &lcd_clk_data_t5;
break;
case LCD_CHIP_T5D:
cconf->data = &lcd_clk_data_t5d;
break;
case LCD_CHIP_T7:
cconf->data = &lcd_clk_data_t7;
switch (pdrv->index) {
case 1:
cconf->data->enc_clk_msr_id = 221;
cconf->pll_id = 1;
cconf->pll_offset = 0x5;
break;
case 2:
cconf->data->enc_clk_msr_id = 220;
cconf->pll_id = 2;
cconf->pll_offset = 0xa;
break;
case 0:
default:
cconf->data->enc_clk_msr_id = 222;
cconf->pll_id = 0;
cconf->pll_offset = 0;
break;
}
cconf->data->enc_clk_msr_id = -1;
break;
case LCD_CHIP_T3: /* only one pll */
cconf->data = &lcd_clk_data_t3;
switch (pdrv->index) {
case 1:
cconf->data->enc_clk_msr_id = 221;
cconf->pll_id = 1;
break;
case 0:
default:
cconf->data->enc_clk_msr_id = 222;
cconf->pll_id = 0;
break;
}
cconf->data->enc_clk_msr_id = -1;
break;
case LCD_CHIP_T5W:
cconf->data = &lcd_clk_data_t5w;
break;
default:
LCDPR("[%d]: %s: invalid chip type\n", pdrv->index, __func__);
return;
}
cconf->pll_od_fb = cconf->data->pll_od_fb;
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
if (cconf->data->clk_config_init_print)
cconf->data->clk_config_init_print(pdrv);
}
}
int lcd_clk_path_change(struct aml_lcd_drv_s *pdrv, int sel)
{
struct lcd_clk_config_s *cconf;
cconf = get_lcd_clk_config(pdrv);
if (!cconf)
return -1;
if (cconf->data->clk_path_valid == 0) {
LCDPR("[%d]: %s: current chip not support\n",
pdrv->index, __func__);
return -1;
}
switch (pdrv->data->chip_type) {
case LCD_CHIP_G12A:
case LCD_CHIP_G12B:
case LCD_CHIP_SM1:
if (sel)
cconf->data = &lcd_clk_data_g12a_path1;
else
cconf->data = &lcd_clk_data_g12a_path0;
cconf->pll_od_fb = cconf->data->pll_od_fb;
break;
default:
LCDERR("[%d]: %s: current chip not support\n",
pdrv->index, __func__);
return -1;
}
if (lcd_debug_print_flag & LCD_DBG_PR_CLK) {
if (cconf->data->clk_config_init_print)
cconf->data->clk_config_init_print(pdrv);
}
return 0;
}
void lcd_clk_config_probe(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
cconf = kzalloc(sizeof(*cconf), GFP_KERNEL);
if (!cconf)
return;
pdrv->clk_conf = (void *)cconf;
lcd_clk_config_chip_init(pdrv, cconf);
if (!cconf->data)
return;
if (cconf->data->clktree_probe)
cconf->data->clktree_probe(pdrv);
}
void lcd_clk_config_remove(struct aml_lcd_drv_s *pdrv)
{
struct lcd_clk_config_s *cconf;
if (!pdrv->clk_conf)
return;
cconf = (struct lcd_clk_config_s *)pdrv->clk_conf;
if (cconf->data && cconf->data->clktree_remove)
cconf->data->clktree_remove(pdrv);
kfree(cconf);
pdrv->clk_conf = NULL;
}