@@ -368,6 +368,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
368368 h_size = window -> src .w * bpp ;
369369 v_size = window -> src .h ;
370370
371+ if (window -> reflect_x )
372+ h_offset += (window -> src .w - 1 ) * bpp ;
373+
374+ if (window -> reflect_y )
375+ v_offset += window -> src .h - 1 ;
376+
371377 value = V_PRESCALED_SIZE (v_size ) | H_PRESCALED_SIZE (h_size );
372378 tegra_plane_writel (plane , value , DC_WIN_PRESCALED_SIZE );
373379
@@ -404,9 +410,6 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
404410 tegra_plane_writel (plane , window -> stride [0 ], DC_WIN_LINE_STRIDE );
405411 }
406412
407- if (window -> bottom_up )
408- v_offset += window -> src .h - 1 ;
409-
410413 tegra_plane_writel (plane , h_offset , DC_WINBUF_ADDR_H_OFFSET );
411414 tegra_plane_writel (plane , v_offset , DC_WINBUF_ADDR_V_OFFSET );
412415
@@ -470,7 +473,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
470473 value |= COLOR_EXPAND ;
471474 }
472475
473- if (window -> bottom_up )
476+ if (window -> reflect_x )
477+ value |= H_DIRECTION ;
478+
479+ if (window -> reflect_y )
474480 value |= V_DIRECTION ;
475481
476482 if (tegra_plane_use_horizontal_filtering (plane , window )) {
@@ -601,7 +607,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
601607 struct drm_plane_state * state )
602608{
603609 struct tegra_plane_state * plane_state = to_tegra_plane_state (state );
604- unsigned int rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y ;
610+ unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
611+ DRM_MODE_REFLECT_X |
612+ DRM_MODE_REFLECT_Y ;
613+ unsigned int rotation = state -> rotation ;
605614 struct tegra_bo_tiling * tiling = & plane_state -> tiling ;
606615 struct tegra_plane * tegra = to_tegra_plane (plane );
607616 struct tegra_dc * dc = to_tegra_dc (state -> crtc );
@@ -639,12 +648,26 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
639648 return - EINVAL ;
640649 }
641650
642- rotation = drm_rotation_simplify (state -> rotation , rotation );
651+ /*
652+ * Older userspace used custom BO flag in order to specify the Y
653+ * reflection, while modern userspace uses the generic DRM rotation
654+ * property in order to achieve the same result. The legacy BO flag
655+ * duplicates the DRM rotation property when both are set.
656+ */
657+ if (tegra_fb_is_bottom_up (state -> fb ))
658+ rotation |= DRM_MODE_REFLECT_Y ;
659+
660+ rotation = drm_rotation_simplify (rotation , supported_rotation );
661+
662+ if (rotation & DRM_MODE_REFLECT_X )
663+ plane_state -> reflect_x = true;
664+ else
665+ plane_state -> reflect_x = false;
643666
644667 if (rotation & DRM_MODE_REFLECT_Y )
645- plane_state -> bottom_up = true;
668+ plane_state -> reflect_y = true;
646669 else
647- plane_state -> bottom_up = false;
670+ plane_state -> reflect_y = false;
648671
649672 /*
650673 * Tegra doesn't support different strides for U and V planes so we
@@ -706,7 +729,8 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
706729 window .dst .w = drm_rect_width (& plane -> state -> dst );
707730 window .dst .h = drm_rect_height (& plane -> state -> dst );
708731 window .bits_per_pixel = fb -> format -> cpp [0 ] * 8 ;
709- window .bottom_up = tegra_fb_is_bottom_up (fb ) || state -> bottom_up ;
732+ window .reflect_x = state -> reflect_x ;
733+ window .reflect_y = state -> reflect_y ;
710734
711735 /* copy from state */
712736 window .zpos = plane -> state -> normalized_zpos ;
@@ -792,6 +816,8 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
792816 err = drm_plane_create_rotation_property (& plane -> base ,
793817 DRM_MODE_ROTATE_0 ,
794818 DRM_MODE_ROTATE_0 |
819+ DRM_MODE_ROTATE_180 |
820+ DRM_MODE_REFLECT_X |
795821 DRM_MODE_REFLECT_Y );
796822 if (err < 0 )
797823 dev_err (dc -> dev , "failed to create rotation property: %d\n" ,
@@ -1080,6 +1106,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
10801106 err = drm_plane_create_rotation_property (& plane -> base ,
10811107 DRM_MODE_ROTATE_0 ,
10821108 DRM_MODE_ROTATE_0 |
1109+ DRM_MODE_ROTATE_180 |
1110+ DRM_MODE_REFLECT_X |
10831111 DRM_MODE_REFLECT_Y );
10841112 if (err < 0 )
10851113 dev_err (dc -> dev , "failed to create rotation property: %d\n" ,
@@ -2555,10 +2583,8 @@ static int tegra_dc_probe(struct platform_device *pdev)
25552583 return PTR_ERR (dc -> regs );
25562584
25572585 dc -> irq = platform_get_irq (pdev , 0 );
2558- if (dc -> irq < 0 ) {
2559- dev_err (& pdev -> dev , "failed to get IRQ\n" );
2586+ if (dc -> irq < 0 )
25602587 return - ENXIO ;
2561- }
25622588
25632589 err = tegra_dc_rgb_probe (dc );
25642590 if (err < 0 && err != - ENODEV ) {
0 commit comments