drm/i915: implement drmmode overlay support v4
This implements intel overlay support for kms via a device-specific ioctl. Thomas Hellstrom brought up the idea of a general ioctl (on dri-devel). We've reached the conclusion that such an infrastructure only makes sense when multiple kms overlay implementations exists, which atm don't (and it doesn't look like this is gonna change). Open issues: - Runs in sync with the gpu, i.e. unnecessary waiting. I've decided to wait on this because the hw tends to hang when changing something in this area. I left some dummy functions as infrastructure. - polyphase filtering uses a static table. - uses uninterruptible sleeps. Unfortunately the alternatives may unnecessarily wedged the hw if/when we timeout too early (and userspace only overloaded the batch buffers with stuff worth a few secs of gpu time). Changes since v1: - fix off-by-one misconception on my side. This fixes fullscreen playback. Changes since v2: - add underrun detection as spec'ed for i965. - flush caches properly, fixing visual corruptions. Changes since v4: - fix up cache flushing of overlay memory regs. - killed require_pipe_a logic - it hangs the chip. Tested-By: diego.abelenda@gmail.com (on a 865G) Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> [anholt: Resolved against the MADVISE ioctl going in before this one] Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
f0f8a9cece
commit
02e792fbaa
|
@ -23,6 +23,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
|
|||
intel_fb.o \
|
||||
intel_tv.o \
|
||||
intel_dvo.o \
|
||||
intel_overlay.o \
|
||||
dvo_ch7xxx.o \
|
||||
dvo_ch7017.o \
|
||||
dvo_ivch.o \
|
||||
|
|
|
@ -807,6 +807,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
|||
case I915_PARAM_NUM_FENCES_AVAIL:
|
||||
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
|
||||
break;
|
||||
case I915_PARAM_HAS_OVERLAY:
|
||||
value = dev_priv->overlay ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
||||
param->param);
|
||||
|
@ -1548,6 +1551,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_mm_takedown(&dev_priv->vram);
|
||||
i915_gem_lastclose(dev);
|
||||
|
||||
intel_cleanup_overlay(dev);
|
||||
}
|
||||
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
|
@ -1656,6 +1661,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
|
||||
DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
|
||||
DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
|
||||
DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
};
|
||||
|
||||
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
|
||||
|
|
|
@ -170,6 +170,8 @@ struct drm_i915_display_funcs {
|
|||
/* clock gating init */
|
||||
};
|
||||
|
||||
struct intel_overlay;
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
|
||||
|
@ -241,6 +243,9 @@ typedef struct drm_i915_private {
|
|||
|
||||
struct intel_opregion opregion;
|
||||
|
||||
/* overlay */
|
||||
struct intel_overlay *overlay;
|
||||
|
||||
/* LVDS info */
|
||||
int backlight_duty_cycle; /* restore backlight to this value */
|
||||
bool panel_wants_dither;
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define MI_NOOP MI_INSTR(0, 0)
|
||||
#define MI_USER_INTERRUPT MI_INSTR(0x02, 0)
|
||||
#define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0)
|
||||
#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16)
|
||||
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
|
@ -151,6 +152,10 @@
|
|||
#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
|
||||
#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
|
||||
#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
|
||||
#define MI_OVERLAY_FLIP MI_INSTR(0x11,0)
|
||||
#define MI_OVERLAY_CONTINUE (0x0<<21)
|
||||
#define MI_OVERLAY_ON (0x1<<21)
|
||||
#define MI_OVERLAY_OFF (0x2<<21)
|
||||
#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
|
||||
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
|
||||
#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
|
||||
|
|
|
@ -1781,6 +1781,22 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
|
||||
{
|
||||
struct intel_overlay *overlay;
|
||||
|
||||
if (!enable && intel_crtc->overlay) {
|
||||
overlay = intel_crtc->overlay;
|
||||
mutex_lock(&overlay->dev->struct_mutex);
|
||||
intel_overlay_switch_off(overlay);
|
||||
mutex_unlock(&overlay->dev->struct_mutex);
|
||||
}
|
||||
/* Let userspace switch the overlay on again. In most cases userspace
|
||||
* has to recompute where to put it anyway. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -1839,12 +1855,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
intel_update_fbc(crtc, &crtc->mode);
|
||||
|
||||
/* Give the overlay scaler a chance to enable if it's on this pipe */
|
||||
//intel_crtc_dpms_video(crtc, true); TODO
|
||||
intel_crtc_dpms_overlay(intel_crtc, true);
|
||||
break;
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
intel_update_watermarks(dev);
|
||||
|
||||
/* Give the overlay scaler a chance to disable if it's on this pipe */
|
||||
//intel_crtc_dpms_video(crtc, FALSE); TODO
|
||||
intel_crtc_dpms_overlay(intel_crtc, false);
|
||||
|
||||
if (dev_priv->cfb_plane == plane &&
|
||||
dev_priv->display.disable_fbc)
|
||||
|
@ -2039,7 +2056,7 @@ static int i830_get_display_clock_speed(struct drm_device *dev)
|
|||
* Return the pipe currently connected to the panel fitter,
|
||||
* or -1 if the panel fitter is not present or not in use
|
||||
*/
|
||||
static int intel_panel_fitter_pipe (struct drm_device *dev)
|
||||
int intel_panel_fitter_pipe (struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pfit_control;
|
||||
|
@ -4458,6 +4475,8 @@ void intel_modeset_init(struct drm_device *dev)
|
|||
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
|
||||
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
|
||||
(unsigned long)dev);
|
||||
|
||||
intel_setup_overlay(dev);
|
||||
}
|
||||
|
||||
void intel_modeset_cleanup(struct drm_device *dev)
|
||||
|
|
|
@ -110,6 +110,25 @@ struct intel_output {
|
|||
int clone_mask;
|
||||
};
|
||||
|
||||
struct intel_crtc;
|
||||
struct intel_overlay {
|
||||
struct drm_device *dev;
|
||||
struct intel_crtc *crtc;
|
||||
struct drm_i915_gem_object *vid_bo;
|
||||
struct drm_i915_gem_object *old_vid_bo;
|
||||
int active;
|
||||
int pfit_active;
|
||||
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
|
||||
u32 color_key;
|
||||
u32 brightness, contrast, saturation;
|
||||
u32 old_xscale, old_yscale;
|
||||
/* register access */
|
||||
u32 flip_addr;
|
||||
struct drm_i915_gem_object *reg_bo;
|
||||
void *virt_addr;
|
||||
int hw_wedged;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
struct drm_crtc base;
|
||||
enum pipe pipe;
|
||||
|
@ -121,6 +140,7 @@ struct intel_crtc {
|
|||
bool busy; /* is scanout buffer being updated frequently? */
|
||||
struct timer_list idle_timer;
|
||||
bool lowfreq_avail;
|
||||
struct intel_overlay *overlay;
|
||||
};
|
||||
|
||||
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
|
||||
|
@ -148,6 +168,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||
extern void intel_edp_link_config (struct intel_output *, int *, int *);
|
||||
|
||||
|
||||
extern int intel_panel_fitter_pipe (struct drm_device *dev);
|
||||
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
|
||||
extern void intel_encoder_prepare (struct drm_encoder *encoder);
|
||||
extern void intel_encoder_commit (struct drm_encoder *encoder);
|
||||
|
@ -183,4 +204,11 @@ extern int intel_framebuffer_create(struct drm_device *dev,
|
|||
struct drm_framebuffer **fb,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
extern void intel_setup_overlay(struct drm_device *dev);
|
||||
extern void intel_cleanup_overlay(struct drm_device *dev);
|
||||
extern int intel_overlay_switch_off(struct intel_overlay *overlay);
|
||||
extern int intel_overlay_put_image(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int intel_overlay_attrs(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
|
|
1293
drivers/gpu/drm/i915/intel_overlay.c
Normal file
1293
drivers/gpu/drm/i915/intel_overlay.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -186,6 +186,8 @@ typedef struct _drm_i915_sarea {
|
|||
#define DRM_I915_GEM_MMAP_GTT 0x24
|
||||
#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25
|
||||
#define DRM_I915_GEM_MADVISE 0x26
|
||||
#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
|
||||
#define DRM_I915_OVERLAY_ATTRS 0x28
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
|
@ -223,6 +225,8 @@ typedef struct _drm_i915_sarea {
|
|||
#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
|
||||
#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id)
|
||||
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
|
||||
#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
|
||||
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
|
@ -266,6 +270,7 @@ typedef struct drm_i915_irq_wait {
|
|||
#define I915_PARAM_CHIPSET_ID 4
|
||||
#define I915_PARAM_HAS_GEM 5
|
||||
#define I915_PARAM_NUM_FENCES_AVAIL 6
|
||||
#define I915_PARAM_HAS_OVERLAY 7
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
int param;
|
||||
|
@ -686,4 +691,70 @@ struct drm_i915_gem_madvise {
|
|||
__u32 retained;
|
||||
};
|
||||
|
||||
/* flags */
|
||||
#define I915_OVERLAY_TYPE_MASK 0xff
|
||||
#define I915_OVERLAY_YUV_PLANAR 0x01
|
||||
#define I915_OVERLAY_YUV_PACKED 0x02
|
||||
#define I915_OVERLAY_RGB 0x03
|
||||
|
||||
#define I915_OVERLAY_DEPTH_MASK 0xff00
|
||||
#define I915_OVERLAY_RGB24 0x1000
|
||||
#define I915_OVERLAY_RGB16 0x2000
|
||||
#define I915_OVERLAY_RGB15 0x3000
|
||||
#define I915_OVERLAY_YUV422 0x0100
|
||||
#define I915_OVERLAY_YUV411 0x0200
|
||||
#define I915_OVERLAY_YUV420 0x0300
|
||||
#define I915_OVERLAY_YUV410 0x0400
|
||||
|
||||
#define I915_OVERLAY_SWAP_MASK 0xff0000
|
||||
#define I915_OVERLAY_NO_SWAP 0x000000
|
||||
#define I915_OVERLAY_UV_SWAP 0x010000
|
||||
#define I915_OVERLAY_Y_SWAP 0x020000
|
||||
#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000
|
||||
|
||||
#define I915_OVERLAY_FLAGS_MASK 0xff000000
|
||||
#define I915_OVERLAY_ENABLE 0x01000000
|
||||
|
||||
struct drm_intel_overlay_put_image {
|
||||
/* various flags and src format description */
|
||||
__u32 flags;
|
||||
/* source picture description */
|
||||
__u32 bo_handle;
|
||||
/* stride values and offsets are in bytes, buffer relative */
|
||||
__u16 stride_Y; /* stride for packed formats */
|
||||
__u16 stride_UV;
|
||||
__u32 offset_Y; /* offset for packet formats */
|
||||
__u32 offset_U;
|
||||
__u32 offset_V;
|
||||
/* in pixels */
|
||||
__u16 src_width;
|
||||
__u16 src_height;
|
||||
/* to compensate the scaling factors for partially covered surfaces */
|
||||
__u16 src_scan_width;
|
||||
__u16 src_scan_height;
|
||||
/* output crtc description */
|
||||
__u32 crtc_id;
|
||||
__u16 dst_x;
|
||||
__u16 dst_y;
|
||||
__u16 dst_width;
|
||||
__u16 dst_height;
|
||||
};
|
||||
|
||||
/* flags */
|
||||
#define I915_OVERLAY_UPDATE_ATTRS (1<<0)
|
||||
#define I915_OVERLAY_UPDATE_GAMMA (1<<1)
|
||||
struct drm_intel_overlay_attrs {
|
||||
__u32 flags;
|
||||
__u32 color_key;
|
||||
__s32 brightness;
|
||||
__u32 contrast;
|
||||
__u32 saturation;
|
||||
__u32 gamma0;
|
||||
__u32 gamma1;
|
||||
__u32 gamma2;
|
||||
__u32 gamma3;
|
||||
__u32 gamma4;
|
||||
__u32 gamma5;
|
||||
};
|
||||
|
||||
#endif /* _I915_DRM_H_ */
|
||||
|
|
Loading…
Reference in a new issue