aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-02-20 16:03:35 -0500
committerDave Airlie <airlied@redhat.com>2018-02-20 16:03:35 -0500
commite53a2079f46aadb4c3d86ba2528e2b5b7eae49dc (patch)
tree6b51a69993df06abb40a61d0bd3a8c4e1ac8ef2b
parent933519a5a269d8460450545adefcb5caec622cac (diff)
parent871dfe7b48bdc56877826d6cf669e9eef0cf671b (diff)
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
-rw-r--r--drivers/gpu/drm/rcar-du/Kconfig3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c51
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c140
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds_regs.h6
5 files changed, 103 insertions, 99 deletions
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 8a50dab19e5c..5d0b4b7119af 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -26,7 +26,8 @@ config DRM_RCAR_LVDS
26 Enable support for the R-Car Display Unit embedded LVDS encoders. 26 Enable support for the R-Car Display Unit embedded LVDS encoders.
27 27
28config DRM_RCAR_VSP 28config DRM_RCAR_VSP
29 bool "R-Car DU VSP Compositor Support" 29 bool "R-Car DU VSP Compositor Support" if ARM
30 default y if ARM64
30 depends on DRM_RCAR_DU 31 depends on DRM_RCAR_DU
31 depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m) 32 depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m)
32 help 33 help
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 5685d5af6998..c4420538ec85 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -125,14 +125,55 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
125 unsigned int m; 125 unsigned int m;
126 unsigned int n; 126 unsigned int n;
127 127
128 for (n = 39; n < 120; n++) { 128 /*
129 for (m = 0; m < 4; m++) { 129 * fin fvco fout fclkout
130 * in --> [1/M] --> |PD| -> [LPF] -> [VCO] -> [1/P] -+-> [1/FDPLL] -> out
131 * +-> | | |
132 * | |
133 * +---------------- [1/N] <------------+
134 *
135 * fclkout = fvco / P / FDPLL -- (1)
136 *
137 * fin/M = fvco/P/N
138 *
139 * fvco = fin * P * N / M -- (2)
140 *
141 * (1) + (2) indicates
142 *
143 * fclkout = fin * N / M / FDPLL
144 *
145 * NOTES
146 * N : (n + 1)
147 * M : (m + 1)
148 * FDPLL : (fdpll + 1)
149 * P : 2
150 * 2kHz < fvco < 4096MHz
151 *
152 * To minimize the jitter,
153 * N : as large as possible
154 * M : as small as possible
155 */
156 for (m = 0; m < 4; m++) {
157 for (n = 119; n > 38; n--) {
158 /*
159 * This code only runs on 64-bit architectures, the
160 * unsigned long type can thus be used for 64-bit
161 * computation. It will still compile without any
162 * warning on 32-bit architectures.
163 *
164 * To optimize calculations, use fout instead of fvco
165 * to verify the VCO frequency constraint.
166 */
167 unsigned long fout = input * (n + 1) / (m + 1);
168
169 if (fout < 1000 || fout > 2048 * 1000 * 1000U)
170 continue;
171
130 for (fdpll = 1; fdpll < 32; fdpll++) { 172 for (fdpll = 1; fdpll < 32; fdpll++) {
131 unsigned long output; 173 unsigned long output;
132 174
133 output = input * (n + 1) / (m + 1) 175 output = fout / (fdpll + 1);
134 / (fdpll + 1); 176 if (output >= 400 * 1000 * 1000)
135 if (output >= 400000000)
136 continue; 177 continue;
137 178
138 diff = abs((long)output - (long)target); 179 diff = abs((long)output - (long)target);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 12d22f3db1af..4defa8123eb2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -39,100 +39,37 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
39 iowrite32(data, lvds->mmio + reg); 39 iowrite32(data, lvds->mmio + reg);
40} 40}
41 41
42static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds, 42static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
43 struct rcar_du_crtc *rcrtc)
44{ 43{
45 const struct drm_display_mode *mode = &rcrtc->crtc.mode;
46 unsigned int freq = mode->clock;
47 u32 lvdcr0;
48 u32 pllcr;
49
50 /* PLL clock configuration */
51 if (freq < 39000) 44 if (freq < 39000)
52 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; 45 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
53 else if (freq < 61000) 46 else if (freq < 61000)
54 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; 47 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
55 else if (freq < 121000) 48 else if (freq < 121000)
56 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; 49 return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
57 else 50 else
58 pllcr = LVDPLLCR_PLLDLYCNT_150M; 51 return LVDPLLCR_PLLDLYCNT_150M;
59
60 rcar_lvds_write(lvds, LVDPLLCR, pllcr);
61
62 /*
63 * Select the input, hardcode mode 0, enable LVDS operation and turn
64 * bias circuitry on.
65 */
66 lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_BEN | LVDCR0_LVEN;
67 if (rcrtc->index == 2)
68 lvdcr0 |= LVDCR0_DUSEL;
69 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
70
71 /* Turn all the channels on. */
72 rcar_lvds_write(lvds, LVDCR1,
73 LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
74 LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
75 LVDCR1_CLKSTBY_GEN2);
76
77 /*
78 * Turn the PLL on, wait for the startup delay, and turn the output
79 * on.
80 */
81 lvdcr0 |= LVDCR0_PLLON;
82 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
83
84 usleep_range(100, 150);
85
86 lvdcr0 |= LVDCR0_LVRES;
87 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
88} 52}
89 53
90static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, 54static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
91 struct rcar_du_crtc *rcrtc)
92{ 55{
93 const struct drm_display_mode *mode = &rcrtc->crtc.mode;
94 unsigned int freq = mode->clock;
95 u32 lvdcr0;
96 u32 pllcr;
97
98 /* PLL clock configuration */
99 if (freq < 42000) 56 if (freq < 42000)
100 pllcr = LVDPLLCR_PLLDIVCNT_42M; 57 return LVDPLLCR_PLLDIVCNT_42M;
101 else if (freq < 85000) 58 else if (freq < 85000)
102 pllcr = LVDPLLCR_PLLDIVCNT_85M; 59 return LVDPLLCR_PLLDIVCNT_85M;
103 else if (freq < 128000) 60 else if (freq < 128000)
104 pllcr = LVDPLLCR_PLLDIVCNT_128M; 61 return LVDPLLCR_PLLDIVCNT_128M;
105 else 62 else
106 pllcr = LVDPLLCR_PLLDIVCNT_148M; 63 return LVDPLLCR_PLLDIVCNT_148M;
107
108 rcar_lvds_write(lvds, LVDPLLCR, pllcr);
109
110 /* Turn all the channels on. */
111 rcar_lvds_write(lvds, LVDCR1,
112 LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
113 LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
114 LVDCR1_CLKSTBY_GEN3);
115
116 /*
117 * Turn the PLL on, set it to LVDS normal mode, wait for the startup
118 * delay and turn the output on.
119 */
120 lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_PLLON;
121 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
122
123 lvdcr0 |= LVDCR0_PWD;
124 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
125
126 usleep_range(100, 150);
127
128 lvdcr0 |= LVDCR0_LVRES;
129 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
130} 64}
131 65
132static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, 66static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
133 struct rcar_du_crtc *rcrtc) 67 struct rcar_du_crtc *rcrtc)
134{ 68{
69 const struct drm_display_mode *mode = &rcrtc->crtc.mode;
70 u32 lvdpllcr;
135 u32 lvdhcr; 71 u32 lvdhcr;
72 u32 lvdcr0;
136 int ret; 73 int ret;
137 74
138 if (lvds->enabled) 75 if (lvds->enabled)
@@ -163,11 +100,46 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
163 100
164 rcar_lvds_write(lvds, LVDCHCR, lvdhcr); 101 rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
165 102
166 /* Perform generation-specific initialization. */ 103 /* PLL clock configuration. */
167 if (lvds->dev->info->gen < 3) 104 if (lvds->dev->info->gen < 3)
168 rcar_du_lvdsenc_start_gen2(lvds, rcrtc); 105 lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
169 else 106 else
170 rcar_du_lvdsenc_start_gen3(lvds, rcrtc); 107 lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
108 rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
109
110 /* Set the LVDS mode and select the input. */
111 lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
112 if (rcrtc->index == 2)
113 lvdcr0 |= LVDCR0_DUSEL;
114 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
115
116 /* Turn all the channels on. */
117 rcar_lvds_write(lvds, LVDCR1,
118 LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
119 LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
120
121 if (lvds->dev->info->gen < 3) {
122 /* Enable LVDS operation and turn the bias circuitry on. */
123 lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN;
124 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
125 }
126
127 /* Turn the PLL on. */
128 lvdcr0 |= LVDCR0_PLLON;
129 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
130
131 if (lvds->dev->info->gen > 2) {
132 /* Set LVDS normal mode. */
133 lvdcr0 |= LVDCR0_PWD;
134 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
135 }
136
137 /* Wait for the startup delay. */
138 usleep_range(100, 150);
139
140 /* Turn the output on. */
141 lvdcr0 |= LVDCR0_LVRES;
142 rcar_lvds_write(lvds, LVDCR0, lvdcr0);
171 143
172 lvds->enabled = true; 144 lvds->enabled = true;
173 145
@@ -203,17 +175,11 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
203void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds, 175void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
204 struct drm_display_mode *mode) 176 struct drm_display_mode *mode)
205{ 177{
206 struct rcar_du_device *rcdu = lvds->dev;
207
208 /* 178 /*
209 * The internal LVDS encoder has a restricted clock frequency operating 179 * The internal LVDS encoder has a restricted clock frequency operating
210 * range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp 180 * range (31MHz to 148.5MHz). Clamp the clock accordingly.
211 * the clock accordingly.
212 */ 181 */
213 if (rcdu->info->gen < 3) 182 mode->clock = clamp(mode->clock, 31000, 148500);
214 mode->clock = clamp(mode->clock, 30000, 150000);
215 else
216 mode->clock = clamp(mode->clock, 25175, 148500);
217} 183}
218 184
219void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, 185void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
index f876c512163c..4c5d7bbce6aa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -45,7 +45,6 @@ static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
45 * @format: information about the pixel format used by the plane 45 * @format: information about the pixel format used by the plane
46 * @sg_tables: scatter-gather tables for the frame buffer memory 46 * @sg_tables: scatter-gather tables for the frame buffer memory
47 * @alpha: value of the plane alpha property 47 * @alpha: value of the plane alpha property
48 * @zpos: value of the plane zpos property
49 */ 48 */
50struct rcar_du_vsp_plane_state { 49struct rcar_du_vsp_plane_state {
51 struct drm_plane_state state; 50 struct drm_plane_state state;
@@ -54,7 +53,6 @@ struct rcar_du_vsp_plane_state {
54 struct sg_table sg_tables[3]; 53 struct sg_table sg_tables[3];
55 54
56 unsigned int alpha; 55 unsigned int alpha;
57 unsigned int zpos;
58}; 56};
59 57
60static inline struct rcar_du_vsp_plane_state * 58static inline struct rcar_du_vsp_plane_state *
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index d7d294ba2dbe..2896835ca7e9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -26,10 +26,8 @@
26 26
27#define LVDCR1 0x0004 27#define LVDCR1 0x0004
28#define LVDCR1_CKSEL (1 << 15) /* Gen2 only */ 28#define LVDCR1_CKSEL (1 << 15) /* Gen2 only */
29#define LVDCR1_CHSTBY_GEN2(n) (3 << (2 + (n) * 2)) /* Gen2 only */ 29#define LVDCR1_CHSTBY(n) (3 << (2 + (n) * 2))
30#define LVDCR1_CHSTBY_GEN3(n) (1 << (2 + (n) * 2)) /* Gen3 only */ 30#define LVDCR1_CLKSTBY (3 << 0)
31#define LVDCR1_CLKSTBY_GEN2 (3 << 0) /* Gen2 only */
32#define LVDCR1_CLKSTBY_GEN3 (1 << 0) /* Gen3 only */
33 31
34#define LVDPLLCR 0x0008 32#define LVDPLLCR 0x0008
35#define LVDPLLCR_CEEN (1 << 14) 33#define LVDPLLCR_CEEN (1 << 14)