diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 147 |
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 | ||
490 | struct 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 | |||
507 | static int packed_depth_bytes(u32 format) | 490 | static 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 | ||
619 | static bool update_scaling_factors(struct intel_overlay *overlay, | 602 | static 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, ®s->DCLRKM); | 696 | iowrite32(flags, ®s->DCLRKM); |
714 | } | 697 | } |
715 | 698 | ||
716 | static u32 overlay_cmd_reg(struct put_image_params *params) | 699 | static 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 | ||
761 | static int intel_overlay_do_put_image(struct intel_overlay *overlay, | 744 | static 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, ®s->DWINPOS); | 792 | iowrite32(params->dst_y << 16 | params->dst_x, ®s->DWINPOS); |
810 | iowrite32((params->dst_h << 16) | params->dst_w, ®s->DWINSZ); | 793 | iowrite32(params->dst_height << 16 | params->dst_width, ®s->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, ®s->OBUF_0Y); | 804 | iowrite32(i915_ggtt_offset(vma) + params->offset_Y, ®s->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 | ®s->OBUF_0U); | 822 | ®s->OBUF_0U); |
836 | iowrite32(i915_ggtt_offset(vma) + params->offset_V, | 823 | iowrite32(i915_ggtt_offset(vma) + params->offset_V, |
837 | ®s->OBUF_0V); | 824 | ®s->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 | ||
941 | static int check_overlay_scaling(struct put_image_params *rec) | 929 | static 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, | |||
1067 | int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, | 1056 | int 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 | ||
1202 | out_unlock: | 1165 | out_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); |
1206 | out_free: | ||
1207 | kfree(params); | ||
1208 | 1169 | ||
1209 | return ret; | 1170 | return ret; |
1210 | } | 1171 | } |