Lines Matching +full:exynos5420 +full:- +full:scaler
1 // SPDX-License-Identifier: GPL-2.0-or-later
25 #include "regs-gsc.h"
28 * GSC stands for General SCaler and
29 * supports image scaler/rotator and input/output DMA operations.
64 #define gsc_read(offset) readl(ctx->regs + (offset))
65 #define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
68 * A structure of scaler.
74 * @main_hratio: the main scaler's horizontal ratio.
75 * @main_vratio: the main scaler's vertical ratio.
91 * @sc: scaler infomations.
116 * struct gsc_driverdata - per device type driver data for init time.
130 /* 8-tap Filter Coefficient */
134 { -1, 2, -6, 127, 7, -2, 1, 0 },
135 { -1, 4, -12, 125, 16, -5, 1, 0 },
136 { -1, 5, -15, 120, 25, -8, 2, 0 },
137 { -1, 6, -18, 114, 35, -10, 3, -1 },
138 { -1, 6, -20, 107, 46, -13, 4, -1 },
139 { -2, 7, -21, 99, 57, -16, 5, -1 },
140 { -1, 6, -20, 89, 68, -18, 5, -1 },
141 { -1, 6, -20, 79, 79, -20, 6, -1 },
142 { -1, 5, -18, 68, 89, -20, 6, -1 },
143 { -1, 5, -16, 57, 99, -21, 7, -2 },
144 { -1, 4, -13, 46, 107, -20, 6, -1 },
145 { -1, 3, -10, 35, 114, -18, 6, -1 },
146 { 0, 2, -8, 25, 120, -15, 5, -1 },
147 { 0, 1, -5, 16, 125, -12, 4, -1 },
148 { 0, 1, -2, 7, 127, -6, 2, -1 }
150 { 3, -8, 14, 111, 13, -8, 3, 0 },
151 { 2, -6, 7, 112, 21, -10, 3, -1 },
152 { 2, -4, 1, 110, 28, -12, 4, -1 },
153 { 1, -2, -3, 106, 36, -13, 4, -1 },
154 { 1, -1, -7, 103, 44, -15, 4, -1 },
155 { 1, 1, -11, 97, 53, -16, 4, -1 },
156 { 0, 2, -13, 91, 61, -16, 4, -1 },
157 { 0, 3, -15, 85, 69, -17, 4, -1 },
158 { 0, 3, -16, 77, 77, -16, 3, 0 },
159 { -1, 4, -17, 69, 85, -15, 3, 0 },
160 { -1, 4, -16, 61, 91, -13, 2, 0 },
161 { -1, 4, -16, 53, 97, -11, 1, 1 },
162 { -1, 4, -15, 44, 103, -7, -1, 1 },
163 { -1, 4, -13, 36, 106, -3, -2, 1 },
164 { -1, 4, -12, 28, 110, 1, -4, 2 },
165 { -1, 3, -10, 21, 112, 7, -6, 2 }
167 { 2, -11, 25, 96, 25, -11, 2, 0 },
168 { 2, -10, 19, 96, 31, -12, 2, 0 },
169 { 2, -9, 14, 94, 37, -12, 2, 0 },
170 { 2, -8, 10, 92, 43, -12, 1, 0 },
171 { 2, -7, 5, 90, 49, -12, 1, 0 },
172 { 2, -5, 1, 86, 55, -12, 0, 1 },
173 { 2, -4, -2, 82, 61, -11, -1, 1 },
174 { 1, -3, -5, 77, 67, -9, -1, 1 },
175 { 1, -2, -7, 72, 72, -7, -2, 1 },
176 { 1, -1, -9, 67, 77, -5, -3, 1 },
177 { 1, -1, -11, 61, 82, -2, -4, 2 },
178 { 1, 0, -12, 55, 86, 1, -5, 2 },
179 { 0, 1, -12, 49, 90, 5, -7, 2 },
180 { 0, 1, -12, 43, 92, 10, -8, 2 },
181 { 0, 2, -12, 37, 94, 14, -9, 2 },
182 { 0, 2, -12, 31, 96, 19, -10, 2 }
184 { -1, -8, 33, 80, 33, -8, -1, 0 },
185 { -1, -8, 28, 80, 37, -7, -2, 1 },
186 { 0, -8, 24, 79, 41, -7, -2, 1 },
187 { 0, -8, 20, 78, 46, -6, -3, 1 },
188 { 0, -8, 16, 76, 50, -4, -3, 1 },
189 { 0, -7, 13, 74, 54, -3, -4, 1 },
190 { 1, -7, 10, 71, 58, -1, -5, 1 },
191 { 1, -6, 6, 68, 62, 1, -5, 1 },
192 { 1, -6, 4, 65, 65, 4, -6, 1 },
193 { 1, -5, 1, 62, 68, 6, -6, 1 },
194 { 1, -5, -1, 58, 71, 10, -7, 1 },
195 { 1, -4, -3, 54, 74, 13, -7, 0 },
196 { 1, -3, -4, 50, 76, 16, -8, 0 },
197 { 1, -3, -6, 46, 78, 20, -8, 0 },
198 { 1, -2, -7, 41, 79, 24, -8, 0 },
199 { 1, -2, -7, 37, 80, 28, -8, -1 }
201 { -3, 0, 35, 64, 35, 0, -3, 0 },
202 { -3, -1, 32, 64, 38, 1, -3, 0 },
203 { -2, -2, 29, 63, 41, 2, -3, 0 },
204 { -2, -3, 27, 63, 43, 4, -4, 0 },
205 { -2, -3, 24, 61, 46, 6, -4, 0 },
206 { -2, -3, 21, 60, 49, 7, -4, 0 },
207 { -1, -4, 19, 59, 51, 9, -4, -1 },
208 { -1, -4, 16, 57, 53, 12, -4, -1 },
209 { -1, -4, 14, 55, 55, 14, -4, -1 },
210 { -1, -4, 12, 53, 57, 16, -4, -1 },
211 { -1, -4, 9, 51, 59, 19, -4, -1 },
212 { 0, -4, 7, 49, 60, 21, -3, -2 },
213 { 0, -4, 6, 46, 61, 24, -3, -2 },
214 { 0, -4, 4, 43, 63, 27, -3, -2 },
215 { 0, -3, 2, 41, 63, 29, -2, -2 },
216 { 0, -3, 1, 38, 64, 32, -1, -3 }
218 { -1, 8, 33, 48, 33, 8, -1, 0 },
219 { -1, 7, 31, 49, 35, 9, -1, -1 },
220 { -1, 6, 30, 49, 36, 10, -1, -1 },
221 { -1, 5, 28, 48, 38, 12, -1, -1 },
222 { -1, 4, 26, 48, 39, 13, 0, -1 },
223 { -1, 3, 24, 47, 41, 15, 0, -1 },
224 { -1, 2, 23, 47, 42, 16, 0, -1 },
225 { -1, 2, 21, 45, 43, 18, 1, -1 },
226 { -1, 1, 19, 45, 45, 19, 1, -1 },
227 { -1, 1, 18, 43, 45, 21, 2, -1 },
228 { -1, 0, 16, 42, 47, 23, 2, -1 },
229 { -1, 0, 15, 41, 47, 24, 3, -1 },
230 { -1, 0, 13, 39, 48, 26, 4, -1 },
231 { -1, -1, 12, 38, 48, 28, 5, -1 },
232 { -1, -1, 10, 36, 49, 30, 6, -1 },
233 { -1, -1, 9, 35, 49, 31, 7, -1 }
254 /* 4-tap Filter Coefficient */
258 { -4, 127, 5, 0 },
259 { -6, 124, 11, -1 },
260 { -8, 118, 19, -1 },
261 { -8, 111, 27, -2 },
262 { -8, 102, 37, -3 },
263 { -8, 92, 48, -4 },
264 { -7, 81, 59, -5 },
265 { -6, 70, 70, -6 },
266 { -5, 59, 81, -7 },
267 { -4, 48, 92, -8 },
268 { -3, 37, 102, -8 },
269 { -2, 27, 111, -8 },
270 { -1, 19, 118, -8 },
271 { -1, 11, 124, -6 },
272 { 0, 5, 127, -4 }
275 { 4, 111, 14, -1 },
276 { 1, 109, 20, -2 },
277 { -2, 105, 27, -2 },
278 { -3, 100, 34, -3 },
279 { -5, 93, 43, -3 },
280 { -5, 86, 51, -4 },
281 { -5, 77, 60, -4 },
282 { -5, 69, 69, -5 },
283 { -4, 60, 77, -5 },
284 { -4, 51, 86, -5 },
285 { -3, 43, 93, -5 },
286 { -3, 34, 100, -3 },
287 { -2, 27, 105, -2 },
288 { -2, 20, 109, 1 },
289 { -1, 14, 111, 4 }
292 { 12, 97, 21, -2 },
293 { 8, 96, 26, -2 },
294 { 5, 93, 32, -2 },
295 { 2, 89, 39, -2 },
296 { 0, 84, 46, -2 },
297 { -1, 79, 53, -3 },
298 { -2, 73, 59, -2 },
299 { -2, 66, 66, -2 },
300 { -2, 59, 73, -2 },
301 { -3, 53, 79, -1 },
302 { -2, 46, 84, 0 },
303 { -2, 39, 89, 2 },
304 { -2, 32, 93, 5 },
305 { -2, 26, 96, 8 },
306 { -2, 21, 97, 12 }
309 { 18, 85, 26, -1 },
310 { 14, 84, 31, -1 },
311 { 11, 82, 36, -1 },
312 { 8, 79, 42, -1 },
313 { 6, 76, 47, -1 },
319 { -1, 47, 76, 6 },
320 { -1, 42, 79, 8 },
321 { -1, 36, 82, 11 },
322 { -1, 31, 84, 14 },
323 { -1, 26, 85, 18 }
388 while (count--) { in gsc_sw_reset()
396 DRM_DEV_ERROR(ctx->dev, "failed to reset gsc h/w.\n"); in gsc_sw_reset()
397 return -EBUSY; in gsc_sw_reset()
423 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]overflow[%d]level[%d]\n", in gsc_handle_irq()
452 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); in gsc_src_set_fmt()
560 ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0; in gsc_src_set_transf()
566 struct gsc_scaler *sc = &ctx->sc; in gsc_src_set_size()
570 cfg = (GSC_SRCIMG_OFFSET_X(buf->rect.x) | in gsc_src_set_size()
571 GSC_SRCIMG_OFFSET_Y(buf->rect.y)); in gsc_src_set_size()
575 cfg = (GSC_CROPPED_WIDTH(buf->rect.w) | in gsc_src_set_size()
576 GSC_CROPPED_HEIGHT(buf->rect.h)); in gsc_src_set_size()
584 cfg |= (GSC_SRCIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) | in gsc_src_set_size()
585 GSC_SRCIMG_HEIGHT(buf->buf.height)); in gsc_src_set_size()
592 if (buf->rect.w >= GSC_WIDTH_ITU_709) in gsc_src_set_size()
593 if (sc->range) in gsc_src_set_size()
598 if (sc->range) in gsc_src_set_size()
628 gsc_write(buf->dma_addr[0], GSC_IN_BASE_ADDR_Y(buf_id)); in gsc_src_set_addr()
629 gsc_write(buf->dma_addr[1], GSC_IN_BASE_ADDR_CB(buf_id)); in gsc_src_set_addr()
630 gsc_write(buf->dma_addr[2], GSC_IN_BASE_ADDR_CR(buf_id)); in gsc_src_set_addr()
639 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); in gsc_dst_set_fmt()
710 DRM_DEV_DEBUG_KMS(ctx->dev, "src[%d]dst[%d]\n", src, dst); in gsc_get_ratio_shift()
713 DRM_DEV_ERROR(ctx->dev, "failed to make ratio and shift.\n"); in gsc_get_ratio_shift()
714 return -EINVAL; in gsc_get_ratio_shift()
750 src_w = src->w; in gsc_set_prescaler()
751 src_h = src->h; in gsc_set_prescaler()
753 if (ctx->rotation) { in gsc_set_prescaler()
754 dst_w = dst->h; in gsc_set_prescaler()
755 dst_h = dst->w; in gsc_set_prescaler()
757 dst_w = dst->w; in gsc_set_prescaler()
758 dst_h = dst->h; in gsc_set_prescaler()
761 ret = gsc_get_ratio_shift(ctx, src_w, dst_w, &sc->pre_hratio); in gsc_set_prescaler()
763 DRM_DEV_ERROR(ctx->dev, "failed to get ratio horizontal.\n"); in gsc_set_prescaler()
767 ret = gsc_get_ratio_shift(ctx, src_h, dst_h, &sc->pre_vratio); in gsc_set_prescaler()
769 DRM_DEV_ERROR(ctx->dev, "failed to get ratio vertical.\n"); in gsc_set_prescaler()
773 DRM_DEV_DEBUG_KMS(ctx->dev, "pre_hratio[%d]pre_vratio[%d]\n", in gsc_set_prescaler()
774 sc->pre_hratio, sc->pre_vratio); in gsc_set_prescaler()
776 sc->main_hratio = (src_w << 16) / dst_w; in gsc_set_prescaler()
777 sc->main_vratio = (src_h << 16) / dst_h; in gsc_set_prescaler()
779 DRM_DEV_DEBUG_KMS(ctx->dev, "main_hratio[%ld]main_vratio[%ld]\n", in gsc_set_prescaler()
780 sc->main_hratio, sc->main_vratio); in gsc_set_prescaler()
782 gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio, in gsc_set_prescaler()
783 &sc->pre_shfactor); in gsc_set_prescaler()
785 DRM_DEV_DEBUG_KMS(ctx->dev, "pre_shfactor[%d]\n", sc->pre_shfactor); in gsc_set_prescaler()
787 cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) | in gsc_set_prescaler()
788 GSC_PRESC_H_RATIO(sc->pre_hratio) | in gsc_set_prescaler()
789 GSC_PRESC_V_RATIO(sc->pre_vratio)); in gsc_set_prescaler()
851 DRM_DEV_DEBUG_KMS(ctx->dev, "main_hratio[%ld]main_vratio[%ld]\n", in gsc_set_scaler()
852 sc->main_hratio, sc->main_vratio); in gsc_set_scaler()
854 gsc_set_h_coef(ctx, sc->main_hratio); in gsc_set_scaler()
855 cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio); in gsc_set_scaler()
858 gsc_set_v_coef(ctx, sc->main_vratio); in gsc_set_scaler()
859 cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio); in gsc_set_scaler()
866 struct gsc_scaler *sc = &ctx->sc; in gsc_dst_set_size()
870 cfg = (GSC_DSTIMG_OFFSET_X(buf->rect.x) | in gsc_dst_set_size()
871 GSC_DSTIMG_OFFSET_Y(buf->rect.y)); in gsc_dst_set_size()
875 if (ctx->rotation) in gsc_dst_set_size()
876 cfg = (GSC_SCALED_WIDTH(buf->rect.h) | in gsc_dst_set_size()
877 GSC_SCALED_HEIGHT(buf->rect.w)); in gsc_dst_set_size()
879 cfg = (GSC_SCALED_WIDTH(buf->rect.w) | in gsc_dst_set_size()
880 GSC_SCALED_HEIGHT(buf->rect.h)); in gsc_dst_set_size()
886 cfg |= GSC_DSTIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) | in gsc_dst_set_size()
887 GSC_DSTIMG_HEIGHT(buf->buf.height); in gsc_dst_set_size()
893 if (buf->rect.w >= GSC_WIDTH_ITU_709) in gsc_dst_set_size()
894 if (sc->range) in gsc_dst_set_size()
899 if (sc->range) in gsc_dst_set_size()
916 buf_num--; in gsc_dst_get_buf_seq()
918 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_num[%d]\n", buf_num); in gsc_dst_get_buf_seq()
953 gsc_write(buf->dma_addr[0], GSC_OUT_BASE_ADDR_Y(buf_id)); in gsc_dst_set_addr()
954 gsc_write(buf->dma_addr[1], GSC_OUT_BASE_ADDR_CB(buf_id)); in gsc_dst_set_addr()
955 gsc_write(buf->dma_addr[2], GSC_OUT_BASE_ADDR_CR(buf_id)); in gsc_dst_set_addr()
965 DRM_DEV_DEBUG_KMS(ctx->dev, "gsc id[%d]\n", ctx->id); in gsc_get_src_buf_index()
977 DRM_DEV_DEBUG_KMS(ctx->dev, "cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg, in gsc_get_src_buf_index()
981 DRM_DEV_ERROR(ctx->dev, "failed to get in buffer index.\n"); in gsc_get_src_buf_index()
982 return -EINVAL; in gsc_get_src_buf_index()
995 DRM_DEV_DEBUG_KMS(ctx->dev, "gsc id[%d]\n", ctx->id); in gsc_get_dst_buf_index()
1008 DRM_DEV_ERROR(ctx->dev, "failed to get out buffer index.\n"); in gsc_get_dst_buf_index()
1009 return -EINVAL; in gsc_get_dst_buf_index()
1014 DRM_DEV_DEBUG_KMS(ctx->dev, "cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg, in gsc_get_dst_buf_index()
1026 DRM_DEV_DEBUG_KMS(ctx->dev, "gsc id[%d]\n", ctx->id); in gsc_irq_handler()
1030 dev_err(ctx->dev, "occurred overflow at %d, status 0x%x.\n", in gsc_irq_handler()
1031 ctx->id, status); in gsc_irq_handler()
1032 err = -EINVAL; in gsc_irq_handler()
1038 dev_dbg(ctx->dev, "occurred frame done at %d, status 0x%x.\n", in gsc_irq_handler()
1039 ctx->id, status); in gsc_irq_handler()
1044 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id_src[%d]buf_id_dst[%d]\n", in gsc_irq_handler()
1048 err = -EINVAL; in gsc_irq_handler()
1051 if (ctx->task) { in gsc_irq_handler()
1052 struct exynos_drm_ipp_task *task = ctx->task; in gsc_irq_handler()
1054 ctx->task = NULL; in gsc_irq_handler()
1055 pm_runtime_mark_last_busy(ctx->dev); in gsc_irq_handler()
1056 pm_runtime_put_autosuspend(ctx->dev); in gsc_irq_handler()
1065 struct gsc_scaler *sc = &ctx->sc; in gsc_reset()
1071 dev_err(ctx->dev, "failed to reset hardware.\n"); in gsc_reset()
1075 /* scaler setting */ in gsc_reset()
1076 memset(&ctx->sc, 0x0, sizeof(ctx->sc)); in gsc_reset()
1077 sc->range = true; in gsc_reset()
1106 gsc_set_scaler(ctx, &ctx->sc); in gsc_start()
1119 ret = pm_runtime_resume_and_get(ctx->dev); in gsc_commit()
1121 dev_err(ctx->dev, "failed to enable GScaler device.\n"); in gsc_commit()
1125 ctx->task = task; in gsc_commit()
1129 pm_runtime_put_autosuspend(ctx->dev); in gsc_commit()
1130 ctx->task = NULL; in gsc_commit()
1134 gsc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier); in gsc_commit()
1135 gsc_src_set_transf(ctx, task->transform.rotation); in gsc_commit()
1136 gsc_src_set_size(ctx, &task->src); in gsc_commit()
1137 gsc_src_set_addr(ctx, 0, &task->src); in gsc_commit()
1138 gsc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier); in gsc_commit()
1139 gsc_dst_set_size(ctx, &task->dst); in gsc_commit()
1140 gsc_dst_set_addr(ctx, 0, &task->dst); in gsc_commit()
1141 gsc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect); in gsc_commit()
1154 if (ctx->task) { in gsc_abort()
1155 struct exynos_drm_ipp_task *task = ctx->task; in gsc_abort()
1157 ctx->task = NULL; in gsc_abort()
1158 pm_runtime_mark_last_busy(ctx->dev); in gsc_abort()
1159 pm_runtime_put_autosuspend(ctx->dev); in gsc_abort()
1160 exynos_drm_ipp_task_done(task, -EIO); in gsc_abort()
1173 struct exynos_drm_ipp *ipp = &ctx->ipp; in gsc_bind()
1175 ctx->drm_dev = drm_dev; in gsc_bind()
1176 ipp->drm_dev = drm_dev; in gsc_bind()
1177 exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); in gsc_bind()
1182 ctx->formats, ctx->num_formats, "gsc"); in gsc_bind()
1194 struct exynos_drm_ipp *ipp = &ctx->ipp; in gsc_unbind()
1197 exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv); in gsc_unbind()
1219 struct device *dev = &pdev->dev; in gsc_probe()
1227 return -ENOMEM; in gsc_probe()
1230 ctx->dev = dev; in gsc_probe()
1231 ctx->num_clocks = driver_data->num_clocks; in gsc_probe()
1232 ctx->clk_names = driver_data->clk_names; in gsc_probe()
1238 return -ENOMEM; in gsc_probe()
1245 formats[i].limits = driver_data->limits; in gsc_probe()
1246 formats[i].num_limits = driver_data->num_limits; in gsc_probe()
1255 formats[j].limits = driver_data->limits; in gsc_probe()
1256 formats[j].num_limits = driver_data->num_limits; in gsc_probe()
1259 ctx->formats = formats; in gsc_probe()
1260 ctx->num_formats = num_formats; in gsc_probe()
1263 for (i = 0; i < ctx->num_clocks; i++) { in gsc_probe()
1264 ctx->clocks[i] = devm_clk_get(dev, ctx->clk_names[i]); in gsc_probe()
1265 if (IS_ERR(ctx->clocks[i])) { in gsc_probe()
1267 ctx->clk_names[i]); in gsc_probe()
1268 return PTR_ERR(ctx->clocks[i]); in gsc_probe()
1272 ctx->regs = devm_platform_ioremap_resource(pdev, 0); in gsc_probe()
1273 if (IS_ERR(ctx->regs)) in gsc_probe()
1274 return PTR_ERR(ctx->regs); in gsc_probe()
1277 ctx->irq = platform_get_irq(pdev, 0); in gsc_probe()
1278 if (ctx->irq < 0) in gsc_probe()
1279 return ctx->irq; in gsc_probe()
1281 ret = devm_request_irq(dev, ctx->irq, gsc_irq_handler, 0, in gsc_probe()
1289 ctx->id = pdev->id; in gsc_probe()
1313 struct device *dev = &pdev->dev; in gsc_remove()
1327 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); in gsc_runtime_suspend()
1329 for (i = ctx->num_clocks - 1; i >= 0; i--) in gsc_runtime_suspend()
1330 clk_disable_unprepare(ctx->clocks[i]); in gsc_runtime_suspend()
1340 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); in gsc_runtime_resume()
1342 for (i = 0; i < ctx->num_clocks; i++) { in gsc_runtime_resume()
1343 ret = clk_prepare_enable(ctx->clocks[i]); in gsc_runtime_resume()
1345 while (--i >= 0) in gsc_runtime_resume()
1346 clk_disable_unprepare(ctx->clocks[i]); in gsc_runtime_resume()
1406 .compatible = "samsung,exynos5-gsc",
1409 .compatible = "samsung,exynos5250-gsc",
1412 .compatible = "samsung,exynos5420-gsc",
1415 .compatible = "samsung,exynos5433-gsc",
1426 .name = "exynos-drm-gsc",