[Intel-gfx] [PATCH 10/11] drm/i915: Add NV12 to primary plane programming.

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Mon May 11 03:24:54 PDT 2015


Hi,

On 05/08/2015 09:40 PM, Chandra Konduru wrote:
> This patch is adding NV12 support to skylake primary plane
> programming. It is covering linear/X/Y/Yf tiling formats
> for 0 and 180 rotations.
> 
> For 90/270 rotation, Y and UV subplanes should be treated
> as separate surfaces and GTT remapping for rotation should
> be done separately for each subplane. Once GEM adds support
> for seperate remappings for two subplanes, 90/270 support
> to be added to plane programming.
> 
> v2:
> -Use regular int instead of 16.16 in aux_offset calculations (me)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru at intel.com>
> Testcase: igt/kms_nv12
> ---
>   drivers/gpu/drm/i915/intel_atomic_plane.c |    2 ++
>   drivers/gpu/drm/i915/intel_display.c      |   38 +++++++++++++++++++++++++++++
>   2 files changed, 40 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
> index 86ba4b2..119439d 100644
> --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
> +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
> @@ -185,10 +185,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
>   		 * 90/270 is not allowed with RGB64 16:16:16:16,
>   		 * RGB 16-bit 5:6:5, and Indexed 8-bit.
>   		 * TBD: Add RGB64 case once its added in supported format list.
> +		 * TBD: Remove NV12, once its 90/270 remapping is supported
>   		 */
>   		switch (state->fb->pixel_format) {
>   		case DRM_FORMAT_C8:
>   		case DRM_FORMAT_RGB565:
> +		case DRM_FORMAT_NV12:
>   			DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
>   					drm_get_format_name(state->fb->pixel_format));
>   			return -EINVAL;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3ae646e..943a835 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3015,6 +3015,9 @@ u32 skl_plane_ctl_format(uint32_t pixel_format)
>   	case DRM_FORMAT_VYUY:
>   		plane_ctl_format = PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
>   		break;
> +	case DRM_FORMAT_NV12:
> +		plane_ctl_format = PLANE_CTL_FORMAT_NV12;
> +		break;
>   	default:
>   		BUG();
>   	}
> @@ -3085,6 +3088,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>   	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
>   	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
>   	int scaler_id = -1;
> +	u32 aux_dist = 0, aux_x_offset = 0, aux_y_offset = 0, aux_stride = 0;
> +	u32 tile_row_adjustment = 0;
>   
>   	plane_state = to_intel_plane_state(plane->state);
>   
> @@ -3141,11 +3146,34 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>   		x_offset = stride * tile_height - y - src_h;
>   		y_offset = x;
>   		plane_size = (src_w - 1) << 16 | (src_h - 1);
> +		/*
> +		 * TBD: For NV12 90/270 rotation, Y and UV subplanes should
> +		 * be treated as separate surfaces and GTT remapping for
> +		 * rotation should be done separately for each subplane.
> +		 * Enable support once seperate remappings are available.
> +		 */
>   	} else {
>   		stride = fb->pitches[0] / stride_div;
>   		x_offset = x;
>   		y_offset = y;
>   		plane_size = (src_h - 1) << 16 | (src_w - 1);
> +		tile_height = PAGE_SIZE / stride_div;
> +
> +		if (fb->pixel_format == DRM_FORMAT_NV12) {
> +			int height_in_mem = (fb->offsets[1]/fb->pitches[0]);
> +			/*
> +			 * If UV starts from middle of a page, then UV start should
> +			 * be programmed to beginning of that page. And offset into that
> +			 * page to be programmed into y-offset
> +			 */
> +			tile_row_adjustment = height_in_mem % tile_height;
> +			aux_dist = fb->pitches[0] * (height_in_mem - tile_row_adjustment);
> +			aux_x_offset = DIV_ROUND_UP(x, 2);
> +			aux_y_offset = DIV_ROUND_UP(y, 2) + tile_row_adjustment;
> +			/* For tile-Yf, uv-subplane tile width is 2x of Y-subplane */
> +			aux_stride = fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED ?
> +				stride / 2 : stride;
> +		}
>   	}
>   	plane_offset = y_offset << 16 | x_offset;
>   
> @@ -3153,11 +3181,14 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>   	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
>   	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
>   	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
> +	I915_WRITE(PLANE_AUX_DIST(pipe, 0), aux_dist | aux_stride);
> +	I915_WRITE(PLANE_AUX_OFFSET(pipe, 0), aux_y_offset << 16 | aux_x_offset);
>   
>   	if (scaler_id >= 0) {
>   		uint32_t ps_ctrl = 0;
>   
>   		WARN_ON(!dst_w || !dst_h);
> +
>   		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(0) |
>   			crtc_state->scaler_state.scalers[scaler_id].mode;
>   		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
> @@ -3166,6 +3197,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>   		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), (dst_w << 16) | dst_h);
>   		I915_WRITE(PLANE_POS(pipe, 0), 0);
>   	} else {
> +		WARN_ON(fb->pixel_format == DRM_FORMAT_NV12);
>   		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);

I've hit this WARN_ON with kms_rotation_crc by just changing the format of frame buffers
it creates to NV12 (so even before any rotation happens). Small snippet:

[  906.408194] [drm:skl_update_scaler_users] PLANE:17 staged scaling request for 3200x1800->3200x1800 crtc_state = ffff880037348800 scaler_users = 0x1
[  906.436759] ------------[ cut here ]------------
[  906.442107] WARNING: CPU: 0 PID: 1709 at drivers/gpu/drm/i915/intel_display.c:3225 skylake_update_primary_plane+0x678/0x6e0 [i915]()
[  906.455620] WARN_ON(fb->pixel_format == DRM_FORMAT_NV12)
[  906.461451] Modules linked in: coretemp i915 drm_kms_helper drm i2c_algo_bit i2c_hid video pinctrl_sunrisepoint pinctrl_intel acpi_pad nls_iso8859_1 hid_generic usbhid hid e1000e ptp psmouse ahci pps_core libahci
[  906.483472] CPU: 0 PID: 1709 Comm: kms_rotation_cr Tainted: G     U  W       4.1.0-rc3-150511+ #12
[  906.493638] Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2R1.86C.X070.R01.1501282110 01/28/2015
[  906.507938]  0000000000000c99 ffff88009bc979a8 ffffffff8161283d 0000000000000007
[  906.516410]  ffff88009bc979f8 ffff88009bc979e8 ffffffff81050062 ffff88009acd0000
[  906.524874]  ffff88009acd0000 ffff8800372356c0 0000000000000000 00000000c1802000
[  906.533341] Call Trace:
[  906.536135]  [<ffffffff8161283d>] dump_stack+0x4c/0x6e
[  906.541979]  [<ffffffff81050062>] warn_slowpath_common+0xb2/0xe0
[  906.548802]  [<ffffffff81050146>] warn_slowpath_fmt+0x46/0x50
[  906.555408]  [<ffffffffa0242cf8>] skylake_update_primary_plane+0x678/0x6e0 [i915]
[  906.563980]  [<ffffffffa023cca3>] intel_commit_primary_plane+0x93/0xb0 [i915]
[  906.572158]  [<ffffffffa025fa49>] intel_plane_atomic_update+0x19/0x20 [i915]
[  906.580180]  [<ffffffffa01b026a>] drm_atomic_helper_commit_planes+0x17a/0x210 [drm_kms_helper]
[  906.590029]  [<ffffffffa0245de3>] __intel_set_mode+0xbf3/0xcd0 [i915]
[  906.597418]  [<ffffffffa024bdae>] intel_crtc_set_config+0x4ee/0x650 [i915]
[  906.605277]  [<ffffffffa014b549>] drm_mode_set_config_internal+0x69/0x120 [drm]
[  906.613618]  [<ffffffffa0150b48>] drm_mode_setcrtc+0x558/0x650 [drm]
[  906.620856]  [<ffffffffa0140f19>] drm_ioctl+0x3f9/0x650 [drm]
[  906.627419]  [<ffffffffa01505f0>] ? drm_mode_setplane+0x200/0x200 [drm]
[  906.634939]  [<ffffffff8116a1f3>] do_vfs_ioctl+0x543/0x5a0
[  906.641170]  [<ffffffff810a8576>] ? rcu_eqs_exit+0x96/0xb0
[  906.647408]  [<ffffffff81095f2d>] ? trace_hardirqs_on+0xd/0x10
[  906.654038]  [<ffffffff81175cd7>] ? __fget_light+0x57/0xa0
[  906.660271]  [<ffffffff8116a29c>] SyS_ioctl+0x4c/0x90
[  906.666031]  [<ffffffff8161aed7>] system_call_fastpath+0x12/0x6f
[  906.672854] ---[ end trace 599568c0e80eee2a ]---
[  906.678235] [drm:intel_pipe_update_end [i915]] *ERROR* Atomic update failure on pipe A (start=10907 end=10921)
[  906.679305] [drm:intel_cpu_fifo_underrun_irq_handler [i915]] *ERROR* CPU pipe A FIFO underrun

Machine even hard hangs in the process. Either way, it is probably bad that userspace can hit
this WARN_ON just by trying to display a NV12 frame buffer.

Regards,

Tvrtko


More information about the Intel-gfx mailing list