mirror of https://gitee.com/openkylin/linux.git
Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/media into drm-next
LVDS startup fixes, enable VSP compositor on GEN3 * 'drm/next/du' of git://linuxtv.org/pinchartl/media: drm: rcar-du: lvds: Refactor LVDS startup drm: rcar-du: lvds: Fix LVDS startup on R-Car Gen3 drm: rcar-du: lvds: Fix LVDS startup on R-Car Gen2 drm: rcar-du: lvds: Fix LVDS clock frequency range drm: rcar-du: lvds: Fix LVDCR1 for R-Car gen3 drm: rcar-du: Enable VSP compositor by default on Gen3 drm: rcar-du: Calculate DPLLCR to be more small jitter drm: rcar-du: Use 1000 to avoid misunderstanding in rcar_du_dpll_divider() drm: rcar-du: Remove zpos field from rcar_du_vsp_plane_state structure
This commit is contained in:
commit
e53a2079f4
|
@ -26,7 +26,8 @@ config DRM_RCAR_LVDS
|
|||
Enable support for the R-Car Display Unit embedded LVDS encoders.
|
||||
|
||||
config DRM_RCAR_VSP
|
||||
bool "R-Car DU VSP Compositor Support"
|
||||
bool "R-Car DU VSP Compositor Support" if ARM
|
||||
default y if ARM64
|
||||
depends on DRM_RCAR_DU
|
||||
depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m)
|
||||
help
|
||||
|
|
|
@ -125,14 +125,55 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
|
|||
unsigned int m;
|
||||
unsigned int n;
|
||||
|
||||
for (n = 39; n < 120; n++) {
|
||||
for (m = 0; m < 4; m++) {
|
||||
/*
|
||||
* fin fvco fout fclkout
|
||||
* in --> [1/M] --> |PD| -> [LPF] -> [VCO] -> [1/P] -+-> [1/FDPLL] -> out
|
||||
* +-> | | |
|
||||
* | |
|
||||
* +---------------- [1/N] <------------+
|
||||
*
|
||||
* fclkout = fvco / P / FDPLL -- (1)
|
||||
*
|
||||
* fin/M = fvco/P/N
|
||||
*
|
||||
* fvco = fin * P * N / M -- (2)
|
||||
*
|
||||
* (1) + (2) indicates
|
||||
*
|
||||
* fclkout = fin * N / M / FDPLL
|
||||
*
|
||||
* NOTES
|
||||
* N : (n + 1)
|
||||
* M : (m + 1)
|
||||
* FDPLL : (fdpll + 1)
|
||||
* P : 2
|
||||
* 2kHz < fvco < 4096MHz
|
||||
*
|
||||
* To minimize the jitter,
|
||||
* N : as large as possible
|
||||
* M : as small as possible
|
||||
*/
|
||||
for (m = 0; m < 4; m++) {
|
||||
for (n = 119; n > 38; n--) {
|
||||
/*
|
||||
* This code only runs on 64-bit architectures, the
|
||||
* unsigned long type can thus be used for 64-bit
|
||||
* computation. It will still compile without any
|
||||
* warning on 32-bit architectures.
|
||||
*
|
||||
* To optimize calculations, use fout instead of fvco
|
||||
* to verify the VCO frequency constraint.
|
||||
*/
|
||||
unsigned long fout = input * (n + 1) / (m + 1);
|
||||
|
||||
if (fout < 1000 || fout > 2048 * 1000 * 1000U)
|
||||
continue;
|
||||
|
||||
for (fdpll = 1; fdpll < 32; fdpll++) {
|
||||
unsigned long output;
|
||||
|
||||
output = input * (n + 1) / (m + 1)
|
||||
/ (fdpll + 1);
|
||||
if (output >= 400000000)
|
||||
output = fout / (fdpll + 1);
|
||||
if (output >= 400 * 1000 * 1000)
|
||||
continue;
|
||||
|
||||
diff = abs((long)output - (long)target);
|
||||
|
|
|
@ -39,100 +39,37 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
|
|||
iowrite32(data, lvds->mmio + reg);
|
||||
}
|
||||
|
||||
static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
|
||||
struct rcar_du_crtc *rcrtc)
|
||||
static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
|
||||
{
|
||||
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
|
||||
unsigned int freq = mode->clock;
|
||||
u32 lvdcr0;
|
||||
u32 pllcr;
|
||||
|
||||
/* PLL clock configuration */
|
||||
if (freq < 39000)
|
||||
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
|
||||
return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
|
||||
else if (freq < 61000)
|
||||
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
|
||||
return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
|
||||
else if (freq < 121000)
|
||||
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
|
||||
return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
|
||||
else
|
||||
pllcr = LVDPLLCR_PLLDLYCNT_150M;
|
||||
|
||||
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
|
||||
|
||||
/*
|
||||
* Select the input, hardcode mode 0, enable LVDS operation and turn
|
||||
* bias circuitry on.
|
||||
*/
|
||||
lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_BEN | LVDCR0_LVEN;
|
||||
if (rcrtc->index == 2)
|
||||
lvdcr0 |= LVDCR0_DUSEL;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
/* Turn all the channels on. */
|
||||
rcar_lvds_write(lvds, LVDCR1,
|
||||
LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
|
||||
LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
|
||||
LVDCR1_CLKSTBY_GEN2);
|
||||
|
||||
/*
|
||||
* Turn the PLL on, wait for the startup delay, and turn the output
|
||||
* on.
|
||||
*/
|
||||
lvdcr0 |= LVDCR0_PLLON;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
lvdcr0 |= LVDCR0_LVRES;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
return LVDPLLCR_PLLDLYCNT_150M;
|
||||
}
|
||||
|
||||
static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
|
||||
struct rcar_du_crtc *rcrtc)
|
||||
static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
|
||||
{
|
||||
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
|
||||
unsigned int freq = mode->clock;
|
||||
u32 lvdcr0;
|
||||
u32 pllcr;
|
||||
|
||||
/* PLL clock configuration */
|
||||
if (freq < 42000)
|
||||
pllcr = LVDPLLCR_PLLDIVCNT_42M;
|
||||
return LVDPLLCR_PLLDIVCNT_42M;
|
||||
else if (freq < 85000)
|
||||
pllcr = LVDPLLCR_PLLDIVCNT_85M;
|
||||
return LVDPLLCR_PLLDIVCNT_85M;
|
||||
else if (freq < 128000)
|
||||
pllcr = LVDPLLCR_PLLDIVCNT_128M;
|
||||
return LVDPLLCR_PLLDIVCNT_128M;
|
||||
else
|
||||
pllcr = LVDPLLCR_PLLDIVCNT_148M;
|
||||
|
||||
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
|
||||
|
||||
/* Turn all the channels on. */
|
||||
rcar_lvds_write(lvds, LVDCR1,
|
||||
LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
|
||||
LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
|
||||
LVDCR1_CLKSTBY_GEN3);
|
||||
|
||||
/*
|
||||
* Turn the PLL on, set it to LVDS normal mode, wait for the startup
|
||||
* delay and turn the output on.
|
||||
*/
|
||||
lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_PLLON;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
lvdcr0 |= LVDCR0_PWD;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
lvdcr0 |= LVDCR0_LVRES;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
return LVDPLLCR_PLLDIVCNT_148M;
|
||||
}
|
||||
|
||||
static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
|
||||
struct rcar_du_crtc *rcrtc)
|
||||
{
|
||||
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
|
||||
u32 lvdpllcr;
|
||||
u32 lvdhcr;
|
||||
u32 lvdcr0;
|
||||
int ret;
|
||||
|
||||
if (lvds->enabled)
|
||||
|
@ -163,11 +100,46 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
|
|||
|
||||
rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
|
||||
|
||||
/* Perform generation-specific initialization. */
|
||||
/* PLL clock configuration. */
|
||||
if (lvds->dev->info->gen < 3)
|
||||
rcar_du_lvdsenc_start_gen2(lvds, rcrtc);
|
||||
lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
|
||||
else
|
||||
rcar_du_lvdsenc_start_gen3(lvds, rcrtc);
|
||||
lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
|
||||
rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
|
||||
|
||||
/* Set the LVDS mode and select the input. */
|
||||
lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
|
||||
if (rcrtc->index == 2)
|
||||
lvdcr0 |= LVDCR0_DUSEL;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
/* Turn all the channels on. */
|
||||
rcar_lvds_write(lvds, LVDCR1,
|
||||
LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
|
||||
LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
|
||||
|
||||
if (lvds->dev->info->gen < 3) {
|
||||
/* Enable LVDS operation and turn the bias circuitry on. */
|
||||
lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
}
|
||||
|
||||
/* Turn the PLL on. */
|
||||
lvdcr0 |= LVDCR0_PLLON;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
if (lvds->dev->info->gen > 2) {
|
||||
/* Set LVDS normal mode. */
|
||||
lvdcr0 |= LVDCR0_PWD;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
}
|
||||
|
||||
/* Wait for the startup delay. */
|
||||
usleep_range(100, 150);
|
||||
|
||||
/* Turn the output on. */
|
||||
lvdcr0 |= LVDCR0_LVRES;
|
||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||
|
||||
lvds->enabled = true;
|
||||
|
||||
|
@ -203,17 +175,11 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
|
|||
void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct rcar_du_device *rcdu = lvds->dev;
|
||||
|
||||
/*
|
||||
* The internal LVDS encoder has a restricted clock frequency operating
|
||||
* range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp
|
||||
* the clock accordingly.
|
||||
* range (31MHz to 148.5MHz). Clamp the clock accordingly.
|
||||
*/
|
||||
if (rcdu->info->gen < 3)
|
||||
mode->clock = clamp(mode->clock, 30000, 150000);
|
||||
else
|
||||
mode->clock = clamp(mode->clock, 25175, 148500);
|
||||
mode->clock = clamp(mode->clock, 31000, 148500);
|
||||
}
|
||||
|
||||
void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
|
||||
|
|
|
@ -45,7 +45,6 @@ static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
|
|||
* @format: information about the pixel format used by the plane
|
||||
* @sg_tables: scatter-gather tables for the frame buffer memory
|
||||
* @alpha: value of the plane alpha property
|
||||
* @zpos: value of the plane zpos property
|
||||
*/
|
||||
struct rcar_du_vsp_plane_state {
|
||||
struct drm_plane_state state;
|
||||
|
@ -54,7 +53,6 @@ struct rcar_du_vsp_plane_state {
|
|||
struct sg_table sg_tables[3];
|
||||
|
||||
unsigned int alpha;
|
||||
unsigned int zpos;
|
||||
};
|
||||
|
||||
static inline struct rcar_du_vsp_plane_state *
|
||||
|
|
|
@ -26,10 +26,8 @@
|
|||
|
||||
#define LVDCR1 0x0004
|
||||
#define LVDCR1_CKSEL (1 << 15) /* Gen2 only */
|
||||
#define LVDCR1_CHSTBY_GEN2(n) (3 << (2 + (n) * 2)) /* Gen2 only */
|
||||
#define LVDCR1_CHSTBY_GEN3(n) (1 << (2 + (n) * 2)) /* Gen3 only */
|
||||
#define LVDCR1_CLKSTBY_GEN2 (3 << 0) /* Gen2 only */
|
||||
#define LVDCR1_CLKSTBY_GEN3 (1 << 0) /* Gen3 only */
|
||||
#define LVDCR1_CHSTBY(n) (3 << (2 + (n) * 2))
|
||||
#define LVDCR1_CLKSTBY (3 << 0)
|
||||
|
||||
#define LVDPLLCR 0x0008
|
||||
#define LVDPLLCR_CEEN (1 << 14)
|
||||
|
|
Loading…
Reference in New Issue