Skip to content

Commit e780e44

Browse files
authored
Merge pull request #1596 from anholt/rpi-4.4.y-vc4-backports
Merge many vc4 changes from drm-vc4-next-2016-07-15
2 parents d31c6f2 + 73c3896 commit e780e44

File tree

11 files changed

+264
-51
lines changed

11 files changed

+264
-51
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 180 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,17 @@ struct vc4_crtc {
4747
const struct vc4_crtc_data *data;
4848
void __iomem *regs;
4949

50+
/* Timestamp at start of vblank irq - unaffected by lock delays. */
51+
ktime_t t_vblank;
52+
5053
/* Which HVS channel we're using for our CRTC. */
5154
int channel;
5255

5356
u8 lut_r[256];
5457
u8 lut_g[256];
5558
u8 lut_b[256];
59+
/* Size in pixels of the COB memory allocated to this CRTC. */
60+
u32 cob_size;
5661

5762
struct drm_pending_vblank_event *event;
5863
};
@@ -134,6 +139,144 @@ int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
134139
}
135140
#endif
136141

142+
int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
143+
unsigned int flags, int *vpos, int *hpos,
144+
ktime_t *stime, ktime_t *etime,
145+
const struct drm_display_mode *mode)
146+
{
147+
struct vc4_dev *vc4 = to_vc4_dev(dev);
148+
struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
149+
u32 val;
150+
int fifo_lines;
151+
int vblank_lines;
152+
int ret = 0;
153+
154+
/*
155+
* XXX Doesn't work well in interlaced mode yet, partially due
156+
* to problems in vc4 kms or drm core interlaced mode handling,
157+
* so disable for now in interlaced mode.
158+
*/
159+
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
160+
return ret;
161+
162+
/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
163+
164+
/* Get optional system timestamp before query. */
165+
if (stime)
166+
*stime = ktime_get();
167+
168+
/*
169+
* Read vertical scanline which is currently composed for our
170+
* pixelvalve by the HVS, and also the scaler status.
171+
*/
172+
val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
173+
174+
/* Get optional system timestamp after query. */
175+
if (etime)
176+
*etime = ktime_get();
177+
178+
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
179+
180+
/* Vertical position of hvs composed scanline. */
181+
*vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE);
182+
183+
/* No hpos info available. */
184+
if (hpos)
185+
*hpos = 0;
186+
187+
/* This is the offset we need for translating hvs -> pv scanout pos. */
188+
fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
189+
190+
if (fifo_lines > 0)
191+
ret |= DRM_SCANOUTPOS_VALID;
192+
193+
/* HVS more than fifo_lines into frame for compositing? */
194+
if (*vpos > fifo_lines) {
195+
/*
196+
* We are in active scanout and can get some meaningful results
197+
* from HVS. The actual PV scanout can not trail behind more
198+
* than fifo_lines as that is the fifo's capacity. Assume that
199+
* in active scanout the HVS and PV work in lockstep wrt. HVS
200+
* refilling the fifo and PV consuming from the fifo, ie.
201+
* whenever the PV consumes and frees up a scanline in the
202+
* fifo, the HVS will immediately refill it, therefore
203+
* incrementing vpos. Therefore we choose HVS read position -
204+
* fifo size in scanlines as a estimate of the real scanout
205+
* position of the PV.
206+
*/
207+
*vpos -= fifo_lines + 1;
208+
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
209+
*vpos /= 2;
210+
211+
ret |= DRM_SCANOUTPOS_ACCURATE;
212+
return ret;
213+
}
214+
215+
/*
216+
* Less: This happens when we are in vblank and the HVS, after getting
217+
* the VSTART restart signal from the PV, just started refilling its
218+
* fifo with new lines from the top-most lines of the new framebuffers.
219+
* The PV does not scan out in vblank, so does not remove lines from
220+
* the fifo, so the fifo will be full quickly and the HVS has to pause.
221+
* We can't get meaningful readings wrt. scanline position of the PV
222+
* and need to make things up in a approximative but consistent way.
223+
*/
224+
ret |= DRM_SCANOUTPOS_IN_VBLANK;
225+
vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay;
226+
227+
if (flags & DRM_CALLED_FROM_VBLIRQ) {
228+
/*
229+
* Assume the irq handler got called close to first
230+
* line of vblank, so PV has about a full vblank
231+
* scanlines to go, and as a base timestamp use the
232+
* one taken at entry into vblank irq handler, so it
233+
* is not affected by random delays due to lock
234+
* contention on event_lock or vblank_time lock in
235+
* the core.
236+
*/
237+
*vpos = -vblank_lines;
238+
239+
if (stime)
240+
*stime = vc4_crtc->t_vblank;
241+
if (etime)
242+
*etime = vc4_crtc->t_vblank;
243+
244+
/*
245+
* If the HVS fifo is not yet full then we know for certain
246+
* we are at the very beginning of vblank, as the hvs just
247+
* started refilling, and the stime and etime timestamps
248+
* truly correspond to start of vblank.
249+
*/
250+
if ((val & SCALER_DISPSTATX_FULL) != SCALER_DISPSTATX_FULL)
251+
ret |= DRM_SCANOUTPOS_ACCURATE;
252+
} else {
253+
/*
254+
* No clue where we are inside vblank. Return a vpos of zero,
255+
* which will cause calling code to just return the etime
256+
* timestamp uncorrected. At least this is no worse than the
257+
* standard fallback.
258+
*/
259+
*vpos = 0;
260+
}
261+
262+
return ret;
263+
}
264+
265+
int vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
266+
int *max_error, struct timeval *vblank_time,
267+
unsigned flags)
268+
{
269+
struct vc4_dev *vc4 = to_vc4_dev(dev);
270+
struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
271+
struct drm_crtc *crtc = &vc4_crtc->base;
272+
struct drm_crtc_state *state = crtc->state;
273+
274+
/* Helper routine in DRM core does all the work: */
275+
return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc_id, max_error,
276+
vblank_time, flags,
277+
&state->adjusted_mode);
278+
}
279+
137280
static void vc4_crtc_destroy(struct drm_crtc *crtc)
138281
{
139282
drm_crtc_cleanup(crtc);
@@ -465,14 +608,6 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
465608

466609
WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
467610

468-
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
469-
vc4_state->mm.start);
470-
471-
if (debug_dump_regs) {
472-
DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
473-
vc4_hvs_dump_state(dev);
474-
}
475-
476611
if (crtc->state->event) {
477612
unsigned long flags;
478613

@@ -482,8 +617,20 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
482617

483618
spin_lock_irqsave(&dev->event_lock, flags);
484619
vc4_crtc->event = crtc->state->event;
485-
spin_unlock_irqrestore(&dev->event_lock, flags);
486620
crtc->state->event = NULL;
621+
622+
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
623+
vc4_state->mm.start);
624+
625+
spin_unlock_irqrestore(&dev->event_lock, flags);
626+
} else {
627+
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
628+
vc4_state->mm.start);
629+
}
630+
631+
if (debug_dump_regs) {
632+
DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
633+
vc4_hvs_dump_state(dev);
487634
}
488635
}
489636

@@ -509,10 +656,14 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
509656
{
510657
struct drm_crtc *crtc = &vc4_crtc->base;
511658
struct drm_device *dev = crtc->dev;
659+
struct vc4_dev *vc4 = to_vc4_dev(dev);
660+
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
661+
u32 chan = vc4_crtc->channel;
512662
unsigned long flags;
513663

514664
spin_lock_irqsave(&dev->event_lock, flags);
515-
if (vc4_crtc->event) {
665+
if (vc4_crtc->event &&
666+
(vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)))) {
516667
drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
517668
vc4_crtc->event = NULL;
518669
drm_crtc_vblank_put(crtc);
@@ -527,6 +678,7 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
527678
irqreturn_t ret = IRQ_NONE;
528679

529680
if (stat & PV_INT_VFP_START) {
681+
vc4_crtc->t_vblank = ktime_get();
530682
CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
531683
drm_crtc_handle_vblank(&vc4_crtc->base);
532684
vc4_crtc_handle_page_flip(vc4_crtc);
@@ -751,6 +903,22 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
751903
}
752904
}
753905

906+
static void
907+
vc4_crtc_get_cob_allocation(struct vc4_crtc *vc4_crtc)
908+
{
909+
struct drm_device *drm = vc4_crtc->base.dev;
910+
struct vc4_dev *vc4 = to_vc4_dev(drm);
911+
u32 dispbase = HVS_READ(SCALER_DISPBASEX(vc4_crtc->channel));
912+
/* Top/base are supposed to be 4-pixel aligned, but the
913+
* Raspberry Pi firmware fills the low bits (which are
914+
* presumably ignored).
915+
*/
916+
u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
917+
u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
918+
919+
vc4_crtc->cob_size = top - base + 4;
920+
}
921+
754922
static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
755923
{
756924
struct platform_device *pdev = to_platform_device(dev);
@@ -827,6 +995,8 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
827995
crtc->cursor = cursor_plane;
828996
}
829997

998+
vc4_crtc_get_cob_allocation(vc4_crtc);
999+
8301000
CRTC_WRITE(PV_INTEN, 0);
8311001
CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
8321002
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),

drivers/gpu/drm/vc4/vc4_dpi.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,12 @@ static struct drm_connector *vc4_dpi_connector_init(struct drm_device *dev,
236236
{
237237
struct drm_connector *connector = NULL;
238238
struct vc4_dpi_connector *dpi_connector;
239-
int ret = 0;
240239

241240
dpi_connector = devm_kzalloc(dev->dev, sizeof(*dpi_connector),
242241
GFP_KERNEL);
243-
if (!dpi_connector) {
244-
ret = -ENOMEM;
245-
goto fail;
246-
}
242+
if (!dpi_connector)
243+
return ERR_PTR(-ENOMEM);
244+
247245
connector = &dpi_connector->base;
248246

249247
dpi_connector->encoder = dpi->encoder;
@@ -260,12 +258,6 @@ static struct drm_connector *vc4_dpi_connector_init(struct drm_device *dev,
260258
drm_mode_connector_attach_encoder(connector, dpi->encoder);
261259

262260
return connector;
263-
264-
fail:
265-
if (connector)
266-
vc4_dpi_connector_destroy(connector);
267-
268-
return ERR_PTR(ret);
269261
}
270262

271263
static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {

drivers/gpu/drm/vc4/vc4_drv.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ static const struct file_operations vc4_drm_fops = {
8888
};
8989

9090
static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
91-
DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
92-
DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
93-
DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
94-
DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
95-
DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
96-
DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
91+
DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, DRM_RENDER_ALLOW),
92+
DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, DRM_RENDER_ALLOW),
93+
DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, DRM_RENDER_ALLOW),
94+
DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, DRM_RENDER_ALLOW),
95+
DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, DRM_RENDER_ALLOW),
96+
DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, DRM_RENDER_ALLOW),
9797
DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
9898
DRM_ROOT_ONLY),
9999
};
@@ -116,6 +116,8 @@ static struct drm_driver vc4_drm_driver = {
116116
.enable_vblank = vc4_enable_vblank,
117117
.disable_vblank = vc4_disable_vblank,
118118
.get_vblank_counter = drm_vblank_no_hw_counter,
119+
.get_scanout_position = vc4_crtc_get_scanoutpos,
120+
.get_vblank_timestamp = vc4_crtc_get_vblank_timestamp,
119121

120122
#if defined(CONFIG_DEBUG_FS)
121123
.debugfs_init = vc4_debugfs_init,
@@ -231,8 +233,6 @@ static int vc4_drm_bind(struct device *dev)
231233
vc4_bo_cache_init(drm);
232234

233235
drm_mode_config_init(drm);
234-
if (ret)
235-
goto unref;
236236

237237
vc4_gem_init(drm);
238238

@@ -266,7 +266,6 @@ static int vc4_drm_bind(struct device *dev)
266266
component_unbind_all(dev, drm);
267267
gem_destroy:
268268
vc4_gem_destroy(drm);
269-
unref:
270269
drm_dev_unref(drm);
271270
vc4_bo_cache_destroy(drm);
272271
return ret;
@@ -295,8 +294,8 @@ static struct platform_driver *const component_drivers[] = {
295294
&vc4_hdmi_driver,
296295
&vc4_dpi_driver,
297296
&vc4_dsi_driver,
298-
&vc4_crtc_driver,
299297
&vc4_hvs_driver,
298+
&vc4_crtc_driver,
300299
&vc4_v3d_driver,
301300
};
302301

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,13 @@ int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
419419
void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
420420
void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
421421
int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
422+
int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
423+
unsigned int flags, int *vpos, int *hpos,
424+
ktime_t *stime, ktime_t *etime,
425+
const struct drm_display_mode *mode);
426+
int vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
427+
int *max_error, struct timeval *vblank_time,
428+
unsigned flags);
422429

423430
/* vc4_debugfs.c */
424431
int vc4_debugfs_init(struct drm_minor *minor);

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -467,12 +467,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
467467
if (IS_ERR(hdmi->hd_regs))
468468
return PTR_ERR(hdmi->hd_regs);
469469

470-
ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
471-
if (!ddc_node) {
472-
DRM_ERROR("Failed to find ddc node in device tree\n");
473-
return -ENODEV;
474-
}
475-
476470
hdmi->pixel_clock = devm_clk_get(dev, "pixel");
477471
if (IS_ERR(hdmi->pixel_clock)) {
478472
DRM_ERROR("Failed to get pixel clock\n");
@@ -484,7 +478,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
484478
return PTR_ERR(hdmi->hsm_clock);
485479
}
486480

481+
ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
482+
if (!ddc_node) {
483+
DRM_ERROR("Failed to find ddc node in device tree\n");
484+
return -ENODEV;
485+
}
486+
487487
hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
488+
of_node_put(ddc_node);
488489
if (!hdmi->ddc) {
489490
DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
490491
return -EPROBE_DEFER;

0 commit comments

Comments
 (0)