Lines Matching +full:exynos5420 +full:- +full:scaler
1 // SPDX-License-Identifier: GPL-2.0-only
25 #include "regs-scaler.h"
27 #define scaler_read(offset) readl(scaler->regs + (offset))
28 #define scaler_write(cfg, offset) writel(cfg, scaler->regs + (offset))
93 static inline int scaler_reset(struct scaler_context *scaler) in scaler_reset() argument
100 } while (--retry > 1 && in scaler_reset()
105 } while (--retry > 0 && scaler_read(SCALER_INT_EN) != 1); in scaler_reset()
107 return retry ? 0 : -EIO; in scaler_reset()
110 static inline void scaler_enable_int(struct scaler_context *scaler) in scaler_enable_int() argument
143 static inline void scaler_set_src_fmt(struct scaler_context *scaler, in scaler_set_src_fmt() argument
152 static inline void scaler_set_src_base(struct scaler_context *scaler, in scaler_set_src_base() argument
162 for (i = 0; i < src_buf->format->num_planes; ++i) in scaler_set_src_base()
163 scaler_write(src_buf->dma_addr[i], bases[i]); in scaler_set_src_base()
166 static inline void scaler_set_src_span(struct scaler_context *scaler, in scaler_set_src_span() argument
171 val = SCALER_SRC_SPAN_SET_Y_SPAN(src_buf->buf.pitch[0] / in scaler_set_src_span()
172 src_buf->format->cpp[0]); in scaler_set_src_span()
174 if (src_buf->format->num_planes > 1) in scaler_set_src_span()
175 val |= SCALER_SRC_SPAN_SET_C_SPAN(src_buf->buf.pitch[1]); in scaler_set_src_span()
180 static inline void scaler_set_src_luma_chroma_pos(struct scaler_context *scaler, in scaler_set_src_luma_chroma_pos() argument
186 val = SCALER_SRC_Y_POS_SET_YH_POS(src_pos->x << 2); in scaler_set_src_luma_chroma_pos()
187 val |= SCALER_SRC_Y_POS_SET_YV_POS(src_pos->y << 2); in scaler_set_src_luma_chroma_pos()
190 (src_pos->x * fmt->chroma_tile_w / 16) << 2); in scaler_set_src_luma_chroma_pos()
192 (src_pos->y * fmt->chroma_tile_h / 16) << 2); in scaler_set_src_luma_chroma_pos()
196 static inline void scaler_set_src_wh(struct scaler_context *scaler, in scaler_set_src_wh() argument
201 val = SCALER_SRC_WH_SET_WIDTH(src_pos->w); in scaler_set_src_wh()
202 val |= SCALER_SRC_WH_SET_HEIGHT(src_pos->h); in scaler_set_src_wh()
206 static inline void scaler_set_dst_fmt(struct scaler_context *scaler, in scaler_set_dst_fmt() argument
215 static inline void scaler_set_dst_base(struct scaler_context *scaler, in scaler_set_dst_base() argument
225 for (i = 0; i < dst_buf->format->num_planes; ++i) in scaler_set_dst_base()
226 scaler_write(dst_buf->dma_addr[i], bases[i]); in scaler_set_dst_base()
229 static inline void scaler_set_dst_span(struct scaler_context *scaler, in scaler_set_dst_span() argument
234 val = SCALER_DST_SPAN_SET_Y_SPAN(dst_buf->buf.pitch[0] / in scaler_set_dst_span()
235 dst_buf->format->cpp[0]); in scaler_set_dst_span()
237 if (dst_buf->format->num_planes > 1) in scaler_set_dst_span()
238 val |= SCALER_DST_SPAN_SET_C_SPAN(dst_buf->buf.pitch[1]); in scaler_set_dst_span()
243 static inline void scaler_set_dst_luma_pos(struct scaler_context *scaler, in scaler_set_dst_luma_pos() argument
248 val = SCALER_DST_WH_SET_WIDTH(dst_pos->w); in scaler_set_dst_luma_pos()
249 val |= SCALER_DST_WH_SET_HEIGHT(dst_pos->h); in scaler_set_dst_luma_pos()
253 static inline void scaler_set_dst_wh(struct scaler_context *scaler, in scaler_set_dst_wh() argument
258 val = SCALER_DST_POS_SET_H_POS(dst_pos->x); in scaler_set_dst_wh()
259 val |= SCALER_DST_POS_SET_V_POS(dst_pos->y); in scaler_set_dst_wh()
263 static inline void scaler_set_hv_ratio(struct scaler_context *scaler, in scaler_set_hv_ratio() argument
271 h_ratio = (src_pos->h << 16) / dst_pos->w; in scaler_set_hv_ratio()
272 v_ratio = (src_pos->w << 16) / dst_pos->h; in scaler_set_hv_ratio()
274 h_ratio = (src_pos->w << 16) / dst_pos->w; in scaler_set_hv_ratio()
275 v_ratio = (src_pos->h << 16) / dst_pos->h; in scaler_set_hv_ratio()
285 static inline void scaler_set_rotation(struct scaler_context *scaler, in scaler_set_rotation() argument
303 static inline void scaler_set_csc(struct scaler_context *scaler, in scaler_set_csc() argument
320 switch (fmt->format) { in scaler_set_csc()
341 static inline void scaler_set_timer(struct scaler_context *scaler, in scaler_set_timer() argument
352 static inline void scaler_start_hw(struct scaler_context *scaler) in scaler_start_hw() argument
360 struct scaler_context *scaler = in scaler_commit() local
363 struct drm_exynos_ipp_task_rect *src_pos = &task->src.rect; in scaler_commit()
364 struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect; in scaler_commit()
368 src_fmt = scaler_get_format(task->src.buf.fourcc); in scaler_commit()
369 dst_fmt = scaler_get_format(task->dst.buf.fourcc); in scaler_commit()
371 ret = pm_runtime_resume_and_get(scaler->dev); in scaler_commit()
375 if (scaler_reset(scaler)) in scaler_commit()
376 return -EIO; in scaler_commit()
378 scaler->task = task; in scaler_commit()
381 scaler, src_fmt->internal_fmt, task->src.buf.modifier != 0); in scaler_commit()
382 scaler_set_src_base(scaler, &task->src); in scaler_commit()
383 scaler_set_src_span(scaler, &task->src); in scaler_commit()
384 scaler_set_src_luma_chroma_pos(scaler, src_pos, src_fmt); in scaler_commit()
385 scaler_set_src_wh(scaler, src_pos); in scaler_commit()
387 scaler_set_dst_fmt(scaler, dst_fmt->internal_fmt); in scaler_commit()
388 scaler_set_dst_base(scaler, &task->dst); in scaler_commit()
389 scaler_set_dst_span(scaler, &task->dst); in scaler_commit()
390 scaler_set_dst_luma_pos(scaler, dst_pos); in scaler_commit()
391 scaler_set_dst_wh(scaler, dst_pos); in scaler_commit()
393 scaler_set_hv_ratio(scaler, task->transform.rotation, src_pos, dst_pos); in scaler_commit()
394 scaler_set_rotation(scaler, task->transform.rotation); in scaler_commit()
396 scaler_set_csc(scaler, task->src.format); in scaler_commit()
398 scaler_set_timer(scaler, 0xffff, 0xf); in scaler_commit()
400 scaler_enable_int(scaler); in scaler_commit()
401 scaler_start_hw(scaler); in scaler_commit()
410 static inline void scaler_disable_int(struct scaler_context *scaler) in scaler_disable_int() argument
415 static inline u32 scaler_get_int_status(struct scaler_context *scaler) in scaler_get_int_status() argument
426 return val & SCALER_INT_STATUS_FRAME_END ? 0 : -EINVAL; in scaler_task_done()
431 struct scaler_context *scaler = arg; in scaler_irq_handler() local
433 u32 val = scaler_get_int_status(scaler); in scaler_irq_handler()
435 scaler_disable_int(scaler); in scaler_irq_handler()
437 if (scaler->task) { in scaler_irq_handler()
438 struct exynos_drm_ipp_task *task = scaler->task; in scaler_irq_handler()
440 scaler->task = NULL; in scaler_irq_handler()
441 pm_runtime_mark_last_busy(scaler->dev); in scaler_irq_handler()
442 pm_runtime_put_autosuspend(scaler->dev); in scaler_irq_handler()
451 struct scaler_context *scaler = dev_get_drvdata(dev); in scaler_bind() local
453 struct exynos_drm_ipp *ipp = &scaler->ipp; in scaler_bind()
455 scaler->drm_dev = drm_dev; in scaler_bind()
456 ipp->drm_dev = drm_dev; in scaler_bind()
457 exynos_drm_register_dma(drm_dev, dev, &scaler->dma_priv); in scaler_bind()
462 scaler->scaler_data->formats, in scaler_bind()
463 scaler->scaler_data->num_formats, "scaler"); in scaler_bind()
465 dev_info(dev, "The exynos scaler has been probed successfully\n"); in scaler_bind()
473 struct scaler_context *scaler = dev_get_drvdata(dev); in scaler_unbind() local
474 struct exynos_drm_ipp *ipp = &scaler->ipp; in scaler_unbind()
477 exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev, in scaler_unbind()
478 &scaler->dma_priv); in scaler_unbind()
488 struct device *dev = &pdev->dev; in scaler_probe()
489 struct scaler_context *scaler; in scaler_probe() local
493 scaler = devm_kzalloc(dev, sizeof(*scaler), GFP_KERNEL); in scaler_probe()
494 if (!scaler) in scaler_probe()
495 return -ENOMEM; in scaler_probe()
497 scaler->scaler_data = in scaler_probe()
500 scaler->dev = dev; in scaler_probe()
501 scaler->regs = devm_platform_ioremap_resource(pdev, 0); in scaler_probe()
502 if (IS_ERR(scaler->regs)) in scaler_probe()
503 return PTR_ERR(scaler->regs); in scaler_probe()
510 IRQF_ONESHOT, "drm_scaler", scaler); in scaler_probe()
516 for (i = 0; i < scaler->scaler_data->num_clk; ++i) { in scaler_probe()
517 scaler->clock[i] = devm_clk_get(dev, in scaler_probe()
518 scaler->scaler_data->clk_name[i]); in scaler_probe()
519 if (IS_ERR(scaler->clock[i])) { in scaler_probe()
521 return PTR_ERR(scaler->clock[i]); in scaler_probe()
528 platform_set_drvdata(pdev, scaler); in scaler_probe()
544 struct device *dev = &pdev->dev; in scaler_remove()
558 static int scaler_clk_ctrl(struct scaler_context *scaler, bool enable) in scaler_clk_ctrl() argument
564 for (i = 0; i < scaler->scaler_data->num_clk; ++i) in scaler_clk_ctrl()
565 clk_fun(scaler->clock[i]); in scaler_clk_ctrl()
572 struct scaler_context *scaler = dev_get_drvdata(dev); in scaler_runtime_suspend() local
574 return scaler_clk_ctrl(scaler, false); in scaler_runtime_suspend()
579 struct scaler_context *scaler = dev_get_drvdata(dev); in scaler_runtime_resume() local
581 return scaler_clk_ctrl(scaler, true); in scaler_runtime_resume()
710 .compatible = "samsung,exynos5420-scaler",
713 .compatible = "samsung,exynos5433-scaler",
724 .name = "exynos-scaler",