@@ -832,10 +832,14 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
832832 return & plane -> base ;
833833}
834834
835- static const u32 tegra_cursor_plane_formats [] = {
835+ static const u32 tegra_legacy_cursor_plane_formats [] = {
836836 DRM_FORMAT_RGBA8888 ,
837837};
838838
839+ static const u32 tegra_cursor_plane_formats [] = {
840+ DRM_FORMAT_ARGB8888 ,
841+ };
842+
839843static int tegra_cursor_atomic_check (struct drm_plane * plane ,
840844 struct drm_atomic_state * state )
841845{
@@ -875,12 +879,24 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
875879 plane );
876880 struct tegra_plane_state * tegra_plane_state = to_tegra_plane_state (new_state );
877881 struct tegra_dc * dc = to_tegra_dc (new_state -> crtc );
878- u32 value = CURSOR_CLIP_DISPLAY ;
882+ struct tegra_drm * tegra = plane -> dev -> dev_private ;
883+ #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
884+ u64 dma_mask = * dc -> dev -> dma_mask ;
885+ #endif
886+ unsigned int x , y ;
887+ u32 value = 0 ;
879888
880889 /* rien ne va plus */
881890 if (!new_state -> crtc || !new_state -> fb )
882891 return ;
883892
893+ /*
894+ * Legacy display supports hardware clipping of the cursor, but
895+ * nvdisplay relies on software to clip the cursor to the screen.
896+ */
897+ if (!dc -> soc -> has_nvdisplay )
898+ value |= CURSOR_CLIP_DISPLAY ;
899+
884900 switch (new_state -> crtc_w ) {
885901 case 32 :
886902 value |= CURSOR_SIZE_32x32 ;
@@ -908,7 +924,7 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
908924 tegra_dc_writel (dc , value , DC_DISP_CURSOR_START_ADDR );
909925
910926#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
911- value = (tegra_plane_state -> iova [0 ] >> 32 ) & 0x3 ;
927+ value = (tegra_plane_state -> iova [0 ] >> 32 ) & ( dma_mask >> 32 ) ;
912928 tegra_dc_writel (dc , value , DC_DISP_CURSOR_START_ADDR_HI );
913929#endif
914930
@@ -920,15 +936,39 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
920936 value = tegra_dc_readl (dc , DC_DISP_BLEND_CURSOR_CONTROL );
921937 value &= ~CURSOR_DST_BLEND_MASK ;
922938 value &= ~CURSOR_SRC_BLEND_MASK ;
923- value |= CURSOR_MODE_NORMAL ;
939+
940+ if (dc -> soc -> has_nvdisplay )
941+ value &= ~CURSOR_COMPOSITION_MODE_XOR ;
942+ else
943+ value |= CURSOR_MODE_NORMAL ;
944+
924945 value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC ;
925946 value |= CURSOR_SRC_BLEND_K1_TIMES_SRC ;
926947 value |= CURSOR_ALPHA ;
927948 tegra_dc_writel (dc , value , DC_DISP_BLEND_CURSOR_CONTROL );
928949
950+ /* nvdisplay relies on software for clipping */
951+ if (dc -> soc -> has_nvdisplay ) {
952+ struct drm_rect src ;
953+
954+ x = new_state -> dst .x1 ;
955+ y = new_state -> dst .y1 ;
956+
957+ drm_rect_fp_to_int (& src , & new_state -> src );
958+
959+ value = (src .y1 & tegra -> vmask ) << 16 | (src .x1 & tegra -> hmask );
960+ tegra_dc_writel (dc , value , DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR );
961+
962+ value = (drm_rect_height (& src ) & tegra -> vmask ) << 16 |
963+ (drm_rect_width (& src ) & tegra -> hmask );
964+ tegra_dc_writel (dc , value , DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR );
965+ } else {
966+ x = new_state -> crtc_x ;
967+ y = new_state -> crtc_y ;
968+ }
969+
929970 /* position the cursor */
930- value = (new_state -> crtc_y & 0x3fff ) << 16 |
931- (new_state -> crtc_x & 0x3fff );
971+ value = ((y & tegra -> vmask ) << 16 ) | (x & tegra -> hmask );
932972 tegra_dc_writel (dc , value , DC_DISP_CURSOR_POSITION );
933973}
934974
@@ -982,8 +1022,13 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
9821022 plane -> index = 6 ;
9831023 plane -> dc = dc ;
9841024
985- num_formats = ARRAY_SIZE (tegra_cursor_plane_formats );
986- formats = tegra_cursor_plane_formats ;
1025+ if (!dc -> soc -> has_nvdisplay ) {
1026+ num_formats = ARRAY_SIZE (tegra_legacy_cursor_plane_formats );
1027+ formats = tegra_legacy_cursor_plane_formats ;
1028+ } else {
1029+ num_formats = ARRAY_SIZE (tegra_cursor_plane_formats );
1030+ formats = tegra_cursor_plane_formats ;
1031+ }
9871032
9881033 err = drm_universal_plane_init (drm , & plane -> base , possible_crtcs ,
9891034 & tegra_plane_funcs , formats ,
@@ -2035,6 +2080,16 @@ static bool tegra_dc_has_window_groups(struct tegra_dc *dc)
20352080 return false;
20362081}
20372082
2083+ static int tegra_dc_early_init (struct host1x_client * client )
2084+ {
2085+ struct drm_device * drm = dev_get_drvdata (client -> host );
2086+ struct tegra_drm * tegra = drm -> dev_private ;
2087+
2088+ tegra -> num_crtcs ++ ;
2089+
2090+ return 0 ;
2091+ }
2092+
20382093static int tegra_dc_init (struct host1x_client * client )
20392094{
20402095 struct drm_device * drm = dev_get_drvdata (client -> host );
@@ -2045,6 +2100,12 @@ static int tegra_dc_init(struct host1x_client *client)
20452100 struct drm_plane * cursor = NULL ;
20462101 int err ;
20472102
2103+ /*
2104+ * DC has been reset by now, so VBLANK syncpoint can be released
2105+ * for general use.
2106+ */
2107+ host1x_syncpt_release_vblank_reservation (client , 26 + dc -> pipe );
2108+
20482109 /*
20492110 * XXX do not register DCs with no window groups because we cannot
20502111 * assign a primary plane to them, which in turn will cause KMS to
@@ -2111,6 +2172,12 @@ static int tegra_dc_init(struct host1x_client *client)
21112172 if (dc -> soc -> pitch_align > tegra -> pitch_align )
21122173 tegra -> pitch_align = dc -> soc -> pitch_align ;
21132174
2175+ /* track maximum resolution */
2176+ if (dc -> soc -> has_nvdisplay )
2177+ drm -> mode_config .max_width = drm -> mode_config .max_height = 16384 ;
2178+ else
2179+ drm -> mode_config .max_width = drm -> mode_config .max_height = 4096 ;
2180+
21142181 err = tegra_dc_rgb_init (drm , dc );
21152182 if (err < 0 && err != - ENODEV ) {
21162183 dev_err (dc -> dev , "failed to initialize RGB output: %d\n" , err );
@@ -2141,7 +2208,7 @@ static int tegra_dc_init(struct host1x_client *client)
21412208 drm_plane_cleanup (primary );
21422209
21432210 host1x_client_iommu_detach (client );
2144- host1x_syncpt_free (dc -> syncpt );
2211+ host1x_syncpt_put (dc -> syncpt );
21452212
21462213 return err ;
21472214}
@@ -2166,7 +2233,17 @@ static int tegra_dc_exit(struct host1x_client *client)
21662233 }
21672234
21682235 host1x_client_iommu_detach (client );
2169- host1x_syncpt_free (dc -> syncpt );
2236+ host1x_syncpt_put (dc -> syncpt );
2237+
2238+ return 0 ;
2239+ }
2240+
2241+ static int tegra_dc_late_exit (struct host1x_client * client )
2242+ {
2243+ struct drm_device * drm = dev_get_drvdata (client -> host );
2244+ struct tegra_drm * tegra = drm -> dev_private ;
2245+
2246+ tegra -> num_crtcs -- ;
21702247
21712248 return 0 ;
21722249}
@@ -2235,8 +2312,10 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
22352312}
22362313
22372314static const struct host1x_client_ops dc_client_ops = {
2315+ .early_init = tegra_dc_early_init ,
22382316 .init = tegra_dc_init ,
22392317 .exit = tegra_dc_exit ,
2318+ .late_exit = tegra_dc_late_exit ,
22402319 .suspend = tegra_dc_runtime_suspend ,
22412320 .resume = tegra_dc_runtime_resume ,
22422321};
@@ -2246,6 +2325,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
22462325 .supports_interlacing = false,
22472326 .supports_cursor = false,
22482327 .supports_block_linear = false,
2328+ .supports_sector_layout = false,
22492329 .has_legacy_blending = true,
22502330 .pitch_align = 8 ,
22512331 .has_powergate = false,
@@ -2265,6 +2345,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
22652345 .supports_interlacing = false,
22662346 .supports_cursor = false,
22672347 .supports_block_linear = false,
2348+ .supports_sector_layout = false,
22682349 .has_legacy_blending = true,
22692350 .pitch_align = 8 ,
22702351 .has_powergate = false,
@@ -2284,6 +2365,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
22842365 .supports_interlacing = false,
22852366 .supports_cursor = false,
22862367 .supports_block_linear = false,
2368+ .supports_sector_layout = false,
22872369 .has_legacy_blending = true,
22882370 .pitch_align = 64 ,
22892371 .has_powergate = true,
@@ -2303,6 +2385,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
23032385 .supports_interlacing = true,
23042386 .supports_cursor = true,
23052387 .supports_block_linear = true,
2388+ .supports_sector_layout = false,
23062389 .has_legacy_blending = false,
23072390 .pitch_align = 64 ,
23082391 .has_powergate = true,
@@ -2322,6 +2405,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
23222405 .supports_interlacing = true,
23232406 .supports_cursor = true,
23242407 .supports_block_linear = true,
2408+ .supports_sector_layout = false,
23252409 .has_legacy_blending = false,
23262410 .pitch_align = 64 ,
23272411 .has_powergate = true,
@@ -2375,6 +2459,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
23752459 .supports_interlacing = true,
23762460 .supports_cursor = true,
23772461 .supports_block_linear = true,
2462+ .supports_sector_layout = false,
23782463 .has_legacy_blending = false,
23792464 .pitch_align = 64 ,
23802465 .has_powergate = false,
@@ -2423,6 +2508,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
24232508 .supports_interlacing = true,
24242509 .supports_cursor = true,
24252510 .supports_block_linear = true,
2511+ .supports_sector_layout = true,
24262512 .has_legacy_blending = false,
24272513 .pitch_align = 64 ,
24282514 .has_powergate = false,
@@ -2532,9 +2618,16 @@ static int tegra_dc_couple(struct tegra_dc *dc)
25322618
25332619static int tegra_dc_probe (struct platform_device * pdev )
25342620{
2621+ u64 dma_mask = dma_get_mask (pdev -> dev .parent );
25352622 struct tegra_dc * dc ;
25362623 int err ;
25372624
2625+ err = dma_coerce_mask_and_coherent (& pdev -> dev , dma_mask );
2626+ if (err < 0 ) {
2627+ dev_err (& pdev -> dev , "failed to set DMA mask: %d\n" , err );
2628+ return err ;
2629+ }
2630+
25382631 dc = devm_kzalloc (& pdev -> dev , sizeof (* dc ), GFP_KERNEL );
25392632 if (!dc )
25402633 return - ENOMEM ;
0 commit comments