4141#include "intel_global_state.h"
4242#include "intel_hdcp.h"
4343#include "intel_psr.h"
44+ #include "intel_fb.h"
4445#include "skl_universal_plane.h"
4546
4647/**
@@ -310,11 +311,11 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
310311 kfree (crtc_state );
311312}
312313
313- static void intel_atomic_setup_scaler (struct intel_crtc_scaler_state * scaler_state ,
314- int num_scalers_need , struct intel_crtc * intel_crtc ,
315- const char * name , int idx ,
316- struct intel_plane_state * plane_state ,
317- int * scaler_id )
314+ static int intel_atomic_setup_scaler (struct intel_crtc_scaler_state * scaler_state ,
315+ int num_scalers_need , struct intel_crtc * intel_crtc ,
316+ const char * name , int idx ,
317+ struct intel_plane_state * plane_state ,
318+ int * scaler_id )
318319{
319320 struct drm_i915_private * dev_priv = to_i915 (intel_crtc -> base .dev );
320321 int j ;
@@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
334335
335336 if (drm_WARN (& dev_priv -> drm , * scaler_id < 0 ,
336337 "Cannot find scaler for %s:%d\n" , name , idx ))
337- return ;
338+ return - EINVAL ;
338339
339340 /* set scaler mode */
340341 if (plane_state && plane_state -> hw .fb &&
@@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
375376 mode = SKL_PS_SCALER_MODE_DYN ;
376377 }
377378
379+ /*
380+ * FIXME: we should also check the scaler factors for pfit, so
381+ * this shouldn't be tied directly to planes.
382+ */
383+ if (plane_state && plane_state -> hw .fb ) {
384+ const struct drm_framebuffer * fb = plane_state -> hw .fb ;
385+ const struct drm_rect * src = & plane_state -> uapi .src ;
386+ const struct drm_rect * dst = & plane_state -> uapi .dst ;
387+ int hscale , vscale , max_vscale , max_hscale ;
388+
389+ /*
390+ * FIXME: When two scalers are needed, but only one of
391+ * them needs to downscale, we should make sure that
392+ * the one that needs downscaling support is assigned
393+ * as the first scaler, so we don't reject downscaling
394+ * unnecessarily.
395+ */
396+
397+ if (DISPLAY_VER (dev_priv ) >= 14 ) {
398+ /*
399+ * On versions 14 and up, only the first
400+ * scaler supports a vertical scaling factor
401+ * of more than 1.0, while a horizontal
402+ * scaling factor of 3.0 is supported.
403+ */
404+ max_hscale = 0x30000 - 1 ;
405+ if (* scaler_id == 0 )
406+ max_vscale = 0x30000 - 1 ;
407+ else
408+ max_vscale = 0x10000 ;
409+
410+ } else if (DISPLAY_VER (dev_priv ) >= 10 ||
411+ !intel_format_info_is_yuv_semiplanar (fb -> format , fb -> modifier )) {
412+ max_hscale = 0x30000 - 1 ;
413+ max_vscale = 0x30000 - 1 ;
414+ } else {
415+ max_hscale = 0x20000 - 1 ;
416+ max_vscale = 0x20000 - 1 ;
417+ }
418+
419+ /*
420+ * FIXME: We should change the if-else block above to
421+ * support HQ vs dynamic scaler properly.
422+ */
423+
424+ /* Check if required scaling is within limits */
425+ hscale = drm_rect_calc_hscale (src , dst , 1 , max_hscale );
426+ vscale = drm_rect_calc_vscale (src , dst , 1 , max_vscale );
427+
428+ if (hscale < 0 || vscale < 0 ) {
429+ drm_dbg_kms (& dev_priv -> drm ,
430+ "Scaler %d doesn't support required plane scaling\n" ,
431+ * scaler_id );
432+ drm_rect_debug_print ("src: " , src , true);
433+ drm_rect_debug_print ("dst: " , dst , false);
434+
435+ return - EINVAL ;
436+ }
437+ }
438+
378439 drm_dbg_kms (& dev_priv -> drm , "Attached scaler id %u.%u to %s:%d\n" ,
379440 intel_crtc -> pipe , * scaler_id , name , idx );
380441 scaler_state -> scalers [* scaler_id ].mode = mode ;
442+
443+ return 0 ;
381444}
382445
383446/**
@@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
437500 for (i = 0 ; i < sizeof (scaler_state -> scaler_users ) * 8 ; i ++ ) {
438501 int * scaler_id ;
439502 const char * name ;
440- int idx ;
503+ int idx , ret ;
441504
442505 /* skip if scaler not required */
443506 if (!(scaler_state -> scaler_users & (1 << i )))
@@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
494557 scaler_id = & plane_state -> scaler_id ;
495558 }
496559
497- intel_atomic_setup_scaler (scaler_state , num_scalers_need ,
498- intel_crtc , name , idx ,
499- plane_state , scaler_id );
560+ ret = intel_atomic_setup_scaler (scaler_state , num_scalers_need ,
561+ intel_crtc , name , idx ,
562+ plane_state , scaler_id );
563+ if (ret < 0 )
564+ return ret ;
500565 }
501566
502567 return 0 ;
0 commit comments