aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c147
1 files changed, 54 insertions, 93 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 443dfaefd7a6..72eb7e48e8bc 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -487,23 +487,6 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv)
487 overlay->active = false; 487 overlay->active = false;
488} 488}
489 489
490struct put_image_params {
491 int format;
492 short dst_x;
493 short dst_y;
494 short dst_w;
495 short dst_h;
496 short src_w;
497 short src_scan_h;
498 short src_scan_w;
499 short src_h;
500 short stride_Y;
501 short stride_UV;
502 int offset_Y;
503 int offset_U;
504 int offset_V;
505};
506
507static int packed_depth_bytes(u32 format) 490static int packed_depth_bytes(u32 format)
508{ 491{
509 switch (format & I915_OVERLAY_DEPTH_MASK) { 492 switch (format & I915_OVERLAY_DEPTH_MASK) {
@@ -618,25 +601,25 @@ static void update_polyphase_filter(struct overlay_registers __iomem *regs)
618 601
619static bool update_scaling_factors(struct intel_overlay *overlay, 602static bool update_scaling_factors(struct intel_overlay *overlay,
620 struct overlay_registers __iomem *regs, 603 struct overlay_registers __iomem *regs,
621 struct put_image_params *params) 604 struct drm_intel_overlay_put_image *params)
622{ 605{
623 /* fixed point with a 12 bit shift */ 606 /* fixed point with a 12 bit shift */
624 u32 xscale, yscale, xscale_UV, yscale_UV; 607 u32 xscale, yscale, xscale_UV, yscale_UV;
625#define FP_SHIFT 12 608#define FP_SHIFT 12
626#define FRACT_MASK 0xfff 609#define FRACT_MASK 0xfff
627 bool scale_changed = false; 610 bool scale_changed = false;
628 int uv_hscale = uv_hsubsampling(params->format); 611 int uv_hscale = uv_hsubsampling(params->flags);
629 int uv_vscale = uv_vsubsampling(params->format); 612 int uv_vscale = uv_vsubsampling(params->flags);
630 613
631 if (params->dst_w > 1) 614 if (params->dst_width > 1)
632 xscale = ((params->src_scan_w - 1) << FP_SHIFT) 615 xscale = ((params->src_scan_width - 1) << FP_SHIFT) /
633 /(params->dst_w); 616 params->dst_width;
634 else 617 else
635 xscale = 1 << FP_SHIFT; 618 xscale = 1 << FP_SHIFT;
636 619
637 if (params->dst_h > 1) 620 if (params->dst_height > 1)
638 yscale = ((params->src_scan_h - 1) << FP_SHIFT) 621 yscale = ((params->src_scan_height - 1) << FP_SHIFT) /
639 /(params->dst_h); 622 params->dst_height;
640 else 623 else
641 yscale = 1 << FP_SHIFT; 624 yscale = 1 << FP_SHIFT;
642 625
@@ -713,12 +696,12 @@ static void update_colorkey(struct intel_overlay *overlay,
713 iowrite32(flags, &regs->DCLRKM); 696 iowrite32(flags, &regs->DCLRKM);
714} 697}
715 698
716static u32 overlay_cmd_reg(struct put_image_params *params) 699static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params)
717{ 700{
718 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; 701 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
719 702
720 if (params->format & I915_OVERLAY_YUV_PLANAR) { 703 if (params->flags & I915_OVERLAY_YUV_PLANAR) {
721 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 704 switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
722 case I915_OVERLAY_YUV422: 705 case I915_OVERLAY_YUV422:
723 cmd |= OCMD_YUV_422_PLANAR; 706 cmd |= OCMD_YUV_422_PLANAR;
724 break; 707 break;
@@ -731,7 +714,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
731 break; 714 break;
732 } 715 }
733 } else { /* YUV packed */ 716 } else { /* YUV packed */
734 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 717 switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
735 case I915_OVERLAY_YUV422: 718 case I915_OVERLAY_YUV422:
736 cmd |= OCMD_YUV_422_PACKED; 719 cmd |= OCMD_YUV_422_PACKED;
737 break; 720 break;
@@ -740,7 +723,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
740 break; 723 break;
741 } 724 }
742 725
743 switch (params->format & I915_OVERLAY_SWAP_MASK) { 726 switch (params->flags & I915_OVERLAY_SWAP_MASK) {
744 case I915_OVERLAY_NO_SWAP: 727 case I915_OVERLAY_NO_SWAP:
745 break; 728 break;
746 case I915_OVERLAY_UV_SWAP: 729 case I915_OVERLAY_UV_SWAP:
@@ -760,7 +743,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
760 743
761static int intel_overlay_do_put_image(struct intel_overlay *overlay, 744static int intel_overlay_do_put_image(struct intel_overlay *overlay,
762 struct drm_i915_gem_object *new_bo, 745 struct drm_i915_gem_object *new_bo,
763 struct put_image_params *params) 746 struct drm_intel_overlay_put_image *params)
764{ 747{
765 struct overlay_registers __iomem *regs = overlay->regs; 748 struct overlay_registers __iomem *regs = overlay->regs;
766 struct drm_i915_private *dev_priv = overlay->i915; 749 struct drm_i915_private *dev_priv = overlay->i915;
@@ -806,35 +789,40 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
806 goto out_unpin; 789 goto out_unpin;
807 } 790 }
808 791
809 iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS); 792 iowrite32(params->dst_y << 16 | params->dst_x, &regs->DWINPOS);
810 iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ); 793 iowrite32(params->dst_height << 16 | params->dst_width, &regs->DWINSZ);
811 794
812 if (params->format & I915_OVERLAY_YUV_PACKED) 795 if (params->flags & I915_OVERLAY_YUV_PACKED)
813 tmp_width = packed_width_bytes(params->format, params->src_w); 796 tmp_width = packed_width_bytes(params->flags,
797 params->src_width);
814 else 798 else
815 tmp_width = params->src_w; 799 tmp_width = params->src_width;
816 800
817 swidth = params->src_w; 801 swidth = params->src_width;
818 swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width); 802 swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
819 sheight = params->src_h; 803 sheight = params->src_height;
820 iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y); 804 iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
821 ostride = params->stride_Y; 805 ostride = params->stride_Y;
822 806
823 if (params->format & I915_OVERLAY_YUV_PLANAR) { 807 if (params->flags & I915_OVERLAY_YUV_PLANAR) {
824 int uv_hscale = uv_hsubsampling(params->format); 808 int uv_hscale = uv_hsubsampling(params->flags);
825 int uv_vscale = uv_vsubsampling(params->format); 809 int uv_vscale = uv_vsubsampling(params->flags);
826 u32 tmp_U, tmp_V; 810 u32 tmp_U, tmp_V;
827 swidth |= (params->src_w/uv_hscale) << 16; 811
812 swidth |= (params->src_width / uv_hscale) << 16;
813 sheight |= (params->src_height / uv_vscale) << 16;
814
828 tmp_U = calc_swidthsw(dev_priv, params->offset_U, 815 tmp_U = calc_swidthsw(dev_priv, params->offset_U,
829 params->src_w/uv_hscale); 816 params->src_width / uv_hscale);
830 tmp_V = calc_swidthsw(dev_priv, params->offset_V, 817 tmp_V = calc_swidthsw(dev_priv, params->offset_V,
831 params->src_w/uv_hscale); 818 params->src_width / uv_hscale);
832 swidthsw |= max_t(u32, tmp_U, tmp_V) << 16; 819 swidthsw |= max(tmp_U, tmp_V) << 16;
833 sheight |= (params->src_h/uv_vscale) << 16; 820
834 iowrite32(i915_ggtt_offset(vma) + params->offset_U, 821 iowrite32(i915_ggtt_offset(vma) + params->offset_U,
835 &regs->OBUF_0U); 822 &regs->OBUF_0U);
836 iowrite32(i915_ggtt_offset(vma) + params->offset_V, 823 iowrite32(i915_ggtt_offset(vma) + params->offset_V,
837 &regs->OBUF_0V); 824 &regs->OBUF_0V);
825
838 ostride |= params->stride_UV << 16; 826 ostride |= params->stride_UV << 16;
839 } 827 }
840 828
@@ -938,15 +926,16 @@ static int check_overlay_dst(struct intel_overlay *overlay,
938 return -EINVAL; 926 return -EINVAL;
939} 927}
940 928
941static int check_overlay_scaling(struct put_image_params *rec) 929static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
942{ 930{
943 u32 tmp; 931 u32 tmp;
944 932
945 /* downscaling limit is 8.0 */ 933 /* downscaling limit is 8.0 */
946 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; 934 tmp = ((rec->src_scan_height << 16) / rec->dst_height) >> 16;
947 if (tmp > 7) 935 if (tmp > 7)
948 return -EINVAL; 936 return -EINVAL;
949 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16; 937
938 tmp = ((rec->src_scan_width << 16) / rec->dst_width) >> 16;
950 if (tmp > 7) 939 if (tmp > 7)
951 return -EINVAL; 940 return -EINVAL;
952 941
@@ -1067,13 +1056,12 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
1067int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, 1056int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
1068 struct drm_file *file_priv) 1057 struct drm_file *file_priv)
1069{ 1058{
1070 struct drm_intel_overlay_put_image *put_image_rec = data; 1059 struct drm_intel_overlay_put_image *params = data;
1071 struct drm_i915_private *dev_priv = to_i915(dev); 1060 struct drm_i915_private *dev_priv = to_i915(dev);
1072 struct intel_overlay *overlay; 1061 struct intel_overlay *overlay;
1073 struct drm_crtc *drmmode_crtc; 1062 struct drm_crtc *drmmode_crtc;
1074 struct intel_crtc *crtc; 1063 struct intel_crtc *crtc;
1075 struct drm_i915_gem_object *new_bo; 1064 struct drm_i915_gem_object *new_bo;
1076 struct put_image_params *params;
1077 int ret; 1065 int ret;
1078 1066
1079 overlay = dev_priv->overlay; 1067 overlay = dev_priv->overlay;
@@ -1082,7 +1070,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
1082 return -ENODEV; 1070 return -ENODEV;
1083 } 1071 }
1084 1072
1085 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { 1073 if (!(params->flags & I915_OVERLAY_ENABLE)) {
1086 drm_modeset_lock_all(dev); 1074 drm_modeset_lock_all(dev);
1087 mutex_lock(&dev->struct_mutex); 1075 mutex_lock(&dev->struct_mutex);
1088 1076
@@ -1094,22 +1082,14 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
1094 return ret; 1082 return ret;
1095 } 1083 }
1096 1084
1097 params = kmalloc(sizeof(*params), GFP_KERNEL); 1085 drmmode_crtc = drm_crtc_find(dev, file_priv, params->crtc_id);
1098 if (!params) 1086 if (!drmmode_crtc)
1099 return -ENOMEM; 1087 return -ENOENT;
1100
1101 drmmode_crtc = drm_crtc_find(dev, file_priv, put_image_rec->crtc_id);
1102 if (!drmmode_crtc) {
1103 ret = -ENOENT;
1104 goto out_free;
1105 }
1106 crtc = to_intel_crtc(drmmode_crtc); 1088 crtc = to_intel_crtc(drmmode_crtc);
1107 1089
1108 new_bo = i915_gem_object_lookup(file_priv, put_image_rec->bo_handle); 1090 new_bo = i915_gem_object_lookup(file_priv, params->bo_handle);
1109 if (!new_bo) { 1091 if (!new_bo)
1110 ret = -ENOENT; 1092 return -ENOENT;
1111 goto out_free;
1112 }
1113 1093
1114 drm_modeset_lock_all(dev); 1094 drm_modeset_lock_all(dev);
1115 mutex_lock(&dev->struct_mutex); 1095 mutex_lock(&dev->struct_mutex);
@@ -1145,42 +1125,27 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
1145 overlay->pfit_active = false; 1125 overlay->pfit_active = false;
1146 } 1126 }
1147 1127
1148 ret = check_overlay_dst(overlay, put_image_rec); 1128 ret = check_overlay_dst(overlay, params);
1149 if (ret != 0) 1129 if (ret != 0)
1150 goto out_unlock; 1130 goto out_unlock;
1151 1131
1152 if (overlay->pfit_active) { 1132 if (overlay->pfit_active) {
1153 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / 1133 params->dst_y = (((u32)params->dst_y << 12) /
1154 overlay->pfit_vscale_ratio); 1134 overlay->pfit_vscale_ratio);
1155 /* shifting right rounds downwards, so add 1 */ 1135 /* shifting right rounds downwards, so add 1 */
1156 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / 1136 params->dst_height = (((u32)params->dst_height << 12) /
1157 overlay->pfit_vscale_ratio) + 1; 1137 overlay->pfit_vscale_ratio) + 1;
1158 } else {
1159 params->dst_y = put_image_rec->dst_y;
1160 params->dst_h = put_image_rec->dst_height;
1161 } 1138 }
1162 params->dst_x = put_image_rec->dst_x; 1139
1163 params->dst_w = put_image_rec->dst_width; 1140 if (params->src_scan_height > params->src_height ||
1164 1141 params->src_scan_width > params->src_width) {
1165 params->src_w = put_image_rec->src_width;
1166 params->src_h = put_image_rec->src_height;
1167 params->src_scan_w = put_image_rec->src_scan_width;
1168 params->src_scan_h = put_image_rec->src_scan_height;
1169 if (params->src_scan_h > params->src_h ||
1170 params->src_scan_w > params->src_w) {
1171 ret = -EINVAL; 1142 ret = -EINVAL;
1172 goto out_unlock; 1143 goto out_unlock;
1173 } 1144 }
1174 1145
1175 ret = check_overlay_src(dev_priv, put_image_rec, new_bo); 1146 ret = check_overlay_src(dev_priv, params, new_bo);
1176 if (ret != 0) 1147 if (ret != 0)
1177 goto out_unlock; 1148 goto out_unlock;
1178 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1179 params->stride_Y = put_image_rec->stride_Y;
1180 params->stride_UV = put_image_rec->stride_UV;
1181 params->offset_Y = put_image_rec->offset_Y;
1182 params->offset_U = put_image_rec->offset_U;
1183 params->offset_V = put_image_rec->offset_V;
1184 1149
1185 /* Check scaling after src size to prevent a divide-by-zero. */ 1150 /* Check scaling after src size to prevent a divide-by-zero. */
1186 ret = check_overlay_scaling(params); 1151 ret = check_overlay_scaling(params);
@@ -1195,16 +1160,12 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
1195 drm_modeset_unlock_all(dev); 1160 drm_modeset_unlock_all(dev);
1196 i915_gem_object_put(new_bo); 1161 i915_gem_object_put(new_bo);
1197 1162
1198 kfree(params);
1199
1200 return 0; 1163 return 0;
1201 1164
1202out_unlock: 1165out_unlock:
1203 mutex_unlock(&dev->struct_mutex); 1166 mutex_unlock(&dev->struct_mutex);
1204 drm_modeset_unlock_all(dev); 1167 drm_modeset_unlock_all(dev);
1205 i915_gem_object_put(new_bo); 1168 i915_gem_object_put(new_bo);
1206out_free:
1207 kfree(params);
1208 1169
1209 return ret; 1170 return ret;
1210} 1171}