video: ssd2828: Allow using 'pclk' as the PLL clock source
Instead of using the internal 'tx_clk' clock source, it is also possible to use the pixel clock signal from the parallel LCD interface ('pclk') as the reference clock for PLL. The 'tx_clk' clock speed may be different on different boards/devices (the allowed range is 8MHz - 30MHz). Which is not very convenient, especially considering the need to know the exact 'tx_clk' clock speed. This clock speed may be difficult to identify without having device schematics and/or accurate documentation/sources every time. Using 'pclk' is free from all these problems. Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com> Acked-by: Anatolij Gustschin <agust@denx.de> Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
aaa6ac5eab
commit
dddccd6913
@ -19,12 +19,14 @@ config VIDEO_LCD_SSD2828
|
||||
config VIDEO_LCD_SSD2828_TX_CLK
|
||||
int "SSD2828 TX_CLK frequency (in MHz)"
|
||||
depends on VIDEO_LCD_SSD2828
|
||||
default 0
|
||||
---help---
|
||||
The frequency of the crystal, which is clocking SSD2828. It may be
|
||||
anything in the 8MHz-30MHz range and the exact value should be
|
||||
retrieved from the board schematics. Or in the case of Allwinner
|
||||
hardware, it can be usually found as 'lcd_xtal_freq' variable in
|
||||
FEX files.
|
||||
FEX files. It can be also set to 0 for selecting PCLK from the
|
||||
parallel LCD interface instead of TX_CLK as the PLL clock source.
|
||||
|
||||
config VIDEO_LCD_SSD2828_RESET
|
||||
string "RESET pin of SSD2828"
|
||||
|
@ -340,7 +340,7 @@ static int ssd2828_configure_video_interface(const struct ssd2828_config *cfg,
|
||||
int ssd2828_init(const struct ssd2828_config *cfg,
|
||||
const struct ctfb_res_modes *mode)
|
||||
{
|
||||
u32 lp_div, pll_freq_kbps, pll_config;
|
||||
u32 lp_div, pll_freq_kbps, reference_freq_khz, pll_config;
|
||||
/* The LP clock speed is limited by 10MHz */
|
||||
const u32 mipi_dsi_low_power_clk_khz = 10000;
|
||||
/*
|
||||
@ -373,6 +373,20 @@ int ssd2828_init(const struct ssd2828_config *cfg,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick the reference clock for PLL. If we know the exact 'tx_clk'
|
||||
* clock speed, then everything is good. If not, then we can fallback
|
||||
* to 'pclk' (pixel clock from the parallel LCD interface). In the
|
||||
* case of using this fallback, it is necessary to have parallel LCD
|
||||
* already initialized and running at this point.
|
||||
*/
|
||||
reference_freq_khz = cfg->ssd2828_tx_clk_khz;
|
||||
if (reference_freq_khz == 0) {
|
||||
reference_freq_khz = mode->pixclock_khz;
|
||||
/* Use 'pclk' as the reference clock for PLL */
|
||||
cfgr_reg |= SSD2828_CFGR_CSS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the parallel LCD timings in the appropriate registers.
|
||||
*/
|
||||
@ -390,10 +404,10 @@ int ssd2828_init(const struct ssd2828_config *cfg,
|
||||
/* PLL Configuration Register */
|
||||
pll_config = construct_pll_config(
|
||||
cfg->mipi_dsi_bitrate_per_data_lane_mbps * 1000,
|
||||
cfg->ssd2828_tx_clk_khz);
|
||||
reference_freq_khz);
|
||||
write_hw_register(cfg, SSD2828_PLCR, pll_config);
|
||||
|
||||
pll_freq_kbps = decode_pll_config(pll_config, cfg->ssd2828_tx_clk_khz);
|
||||
pll_freq_kbps = decode_pll_config(pll_config, reference_freq_khz);
|
||||
lp_div = DIV_ROUND_UP(pll_freq_kbps, mipi_dsi_low_power_clk_khz * 8);
|
||||
|
||||
/* VC Control Register */
|
||||
|
@ -47,8 +47,12 @@ struct ssd2828_config {
|
||||
* to TX_CLK_XIO/TX_CLK_XIN pins), which is necessary at least for
|
||||
* clocking SPI after reset. The exact clock speed is not strictly,
|
||||
* defined, but the datasheet says that it must be somewhere in the
|
||||
* 8MHz - 30MHz range (see "TX_CLK Timing" section). It is used as
|
||||
* a reference clock for PLL and must be set correctly.
|
||||
* 8MHz - 30MHz range (see "TX_CLK Timing" section). It can be also
|
||||
* used as a reference clock for PLL. If the exact clock frequency
|
||||
* is known, then it can be specified here. If it is unknown, or the
|
||||
* information is not trustworthy, then it can be set to 0.
|
||||
*
|
||||
* If unsure, set to 0.
|
||||
*/
|
||||
int ssd2828_tx_clk_khz;
|
||||
|
||||
@ -115,7 +119,8 @@ struct ssd2828_config {
|
||||
* The right place to insert this function call is after the parallel LCD
|
||||
* interface is initialized and before turning on the backlight. This is
|
||||
* advised in the "Example for system sleep in and out" section of the
|
||||
* SSD2828 datasheet.
|
||||
* SSD2828 datasheet. And also SS2828 may use 'pclk' as the clock source
|
||||
* for PLL, which means that the input signal must be already there.
|
||||
*/
|
||||
int ssd2828_init(const struct ssd2828_config *cfg,
|
||||
const struct ctfb_res_modes *mode);
|
||||
|
Loading…
Reference in New Issue
Block a user