123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
- */
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/platform_device.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/file.h>
- #include <linux/delay.h>
- #include <linux/debugfs.h>
- #include <linux/interrupt.h>
- #include "sde_rotator_r1_hwio.h"
- #include "sde_rotator_core.h"
- #include "sde_rotator_util.h"
- #include "sde_rotator_r1_internal.h"
- #include "sde_rotator_r1.h"
- #include "sde_rotator_r1_debug.h"
- struct sde_mdp_hw_resource {
- struct sde_rot_hw_resource hw;
- struct sde_mdp_ctl *ctl;
- struct sde_mdp_mixer *mixer;
- struct sde_mdp_pipe *pipe;
- struct sde_mdp_writeback *wb;
- };
- struct sde_rotator_r1_data {
- struct sde_rot_mgr *mgr;
- int wb_id;
- int ctl_id;
- int irq_num;
- struct sde_mdp_hw_resource *mdp_hw;
- };
- static u32 sde_hw_rotator_input_pixfmts[] = {
- SDE_PIX_FMT_XRGB_8888,
- SDE_PIX_FMT_ARGB_8888,
- SDE_PIX_FMT_ABGR_8888,
- SDE_PIX_FMT_RGBA_8888,
- SDE_PIX_FMT_BGRA_8888,
- SDE_PIX_FMT_RGBX_8888,
- SDE_PIX_FMT_BGRX_8888,
- SDE_PIX_FMT_XBGR_8888,
- SDE_PIX_FMT_RGBA_5551,
- SDE_PIX_FMT_ARGB_1555,
- SDE_PIX_FMT_ABGR_1555,
- SDE_PIX_FMT_BGRA_5551,
- SDE_PIX_FMT_BGRX_5551,
- SDE_PIX_FMT_RGBX_5551,
- SDE_PIX_FMT_XBGR_1555,
- SDE_PIX_FMT_XRGB_1555,
- SDE_PIX_FMT_ARGB_4444,
- SDE_PIX_FMT_RGBA_4444,
- SDE_PIX_FMT_BGRA_4444,
- SDE_PIX_FMT_ABGR_4444,
- SDE_PIX_FMT_RGBX_4444,
- SDE_PIX_FMT_XRGB_4444,
- SDE_PIX_FMT_BGRX_4444,
- SDE_PIX_FMT_XBGR_4444,
- SDE_PIX_FMT_RGB_888,
- SDE_PIX_FMT_BGR_888,
- SDE_PIX_FMT_RGB_565,
- SDE_PIX_FMT_BGR_565,
- SDE_PIX_FMT_Y_CB_CR_H2V2,
- SDE_PIX_FMT_Y_CR_CB_H2V2,
- SDE_PIX_FMT_Y_CR_CB_GH2V2,
- SDE_PIX_FMT_Y_CBCR_H2V2,
- SDE_PIX_FMT_Y_CRCB_H2V2,
- SDE_PIX_FMT_Y_CBCR_H1V2,
- SDE_PIX_FMT_Y_CRCB_H1V2,
- SDE_PIX_FMT_Y_CBCR_H2V1,
- SDE_PIX_FMT_Y_CRCB_H2V1,
- SDE_PIX_FMT_YCBYCR_H2V1,
- SDE_PIX_FMT_Y_CBCR_H2V2_VENUS,
- SDE_PIX_FMT_Y_CRCB_H2V2_VENUS,
- SDE_PIX_FMT_RGBA_8888_UBWC,
- SDE_PIX_FMT_RGBX_8888_UBWC,
- SDE_PIX_FMT_RGB_565_UBWC,
- SDE_PIX_FMT_Y_CBCR_H2V2_UBWC,
- };
- static u32 sde_hw_rotator_output_pixfmts[] = {
- SDE_PIX_FMT_XRGB_8888,
- SDE_PIX_FMT_ARGB_8888,
- SDE_PIX_FMT_ABGR_8888,
- SDE_PIX_FMT_RGBA_8888,
- SDE_PIX_FMT_BGRA_8888,
- SDE_PIX_FMT_RGBX_8888,
- SDE_PIX_FMT_BGRX_8888,
- SDE_PIX_FMT_XBGR_8888,
- SDE_PIX_FMT_RGBA_5551,
- SDE_PIX_FMT_ARGB_1555,
- SDE_PIX_FMT_ABGR_1555,
- SDE_PIX_FMT_BGRA_5551,
- SDE_PIX_FMT_BGRX_5551,
- SDE_PIX_FMT_RGBX_5551,
- SDE_PIX_FMT_XBGR_1555,
- SDE_PIX_FMT_XRGB_1555,
- SDE_PIX_FMT_ARGB_4444,
- SDE_PIX_FMT_RGBA_4444,
- SDE_PIX_FMT_BGRA_4444,
- SDE_PIX_FMT_ABGR_4444,
- SDE_PIX_FMT_RGBX_4444,
- SDE_PIX_FMT_XRGB_4444,
- SDE_PIX_FMT_BGRX_4444,
- SDE_PIX_FMT_XBGR_4444,
- SDE_PIX_FMT_RGB_888,
- SDE_PIX_FMT_BGR_888,
- SDE_PIX_FMT_RGB_565,
- SDE_PIX_FMT_BGR_565,
- SDE_PIX_FMT_Y_CB_CR_H2V2,
- SDE_PIX_FMT_Y_CR_CB_H2V2,
- SDE_PIX_FMT_Y_CR_CB_GH2V2,
- SDE_PIX_FMT_Y_CBCR_H2V2,
- SDE_PIX_FMT_Y_CRCB_H2V2,
- SDE_PIX_FMT_Y_CBCR_H1V2,
- SDE_PIX_FMT_Y_CRCB_H1V2,
- SDE_PIX_FMT_Y_CBCR_H2V1,
- SDE_PIX_FMT_Y_CRCB_H2V1,
- SDE_PIX_FMT_YCBYCR_H2V1,
- SDE_PIX_FMT_Y_CBCR_H2V2_VENUS,
- SDE_PIX_FMT_Y_CRCB_H2V2_VENUS,
- SDE_PIX_FMT_RGBA_8888_UBWC,
- SDE_PIX_FMT_RGBX_8888_UBWC,
- SDE_PIX_FMT_RGB_565_UBWC,
- SDE_PIX_FMT_Y_CBCR_H2V2_UBWC,
- };
- static struct sde_mdp_hw_resource *sde_rotator_hw_alloc(
- struct sde_rot_mgr *mgr, u32 ctl_id, u32 wb_id, int irq_num)
- {
- struct sde_mdp_hw_resource *mdp_hw;
- struct sde_rot_data_type *mdata = sde_rot_get_mdata();
- int pipe_ndx, offset = ctl_id;
- int ret = 0;
- mdp_hw = devm_kzalloc(&mgr->pdev->dev,
- sizeof(struct sde_mdp_hw_resource), GFP_KERNEL);
- if (!mdp_hw)
- return ERR_PTR(-ENOMEM);
- mdp_hw->ctl = sde_mdp_ctl_alloc(mdata, offset);
- if (IS_ERR_OR_NULL(mdp_hw->ctl)) {
- SDEROT_ERR("unable to allocate ctl\n");
- ret = -ENODEV;
- goto error;
- }
- mdp_hw->ctl->irq_num = irq_num;
- mdp_hw->wb = sde_mdp_wb_assign(wb_id, mdp_hw->ctl->num);
- if (IS_ERR_OR_NULL(mdp_hw->wb)) {
- SDEROT_ERR("unable to allocate wb\n");
- ret = -ENODEV;
- goto error;
- }
- mdp_hw->ctl->wb = mdp_hw->wb;
- mdp_hw->mixer = sde_mdp_mixer_assign(mdp_hw->wb->num, true);
- if (IS_ERR_OR_NULL(mdp_hw->mixer)) {
- SDEROT_ERR("unable to allocate wb mixer\n");
- ret = -ENODEV;
- goto error;
- }
- mdp_hw->ctl->mixer_left = mdp_hw->mixer;
- mdp_hw->mixer->ctl = mdp_hw->ctl;
- mdp_hw->mixer->rotator_mode = true;
- switch (mdp_hw->mixer->num) {
- case SDE_MDP_WB_LAYERMIXER0:
- mdp_hw->ctl->opmode = SDE_MDP_CTL_OP_ROT0_MODE;
- break;
- case SDE_MDP_WB_LAYERMIXER1:
- mdp_hw->ctl->opmode = SDE_MDP_CTL_OP_ROT1_MODE;
- break;
- default:
- SDEROT_ERR("invalid layer mixer=%d\n", mdp_hw->mixer->num);
- ret = -EINVAL;
- goto error;
- }
- mdp_hw->ctl->ops.start_fnc = sde_mdp_writeback_start;
- mdp_hw->ctl->wb_type = SDE_MDP_WB_CTL_TYPE_BLOCK;
- if (mdp_hw->ctl->ops.start_fnc)
- ret = mdp_hw->ctl->ops.start_fnc(mdp_hw->ctl);
- if (ret)
- goto error;
- /* override from dt */
- pipe_ndx = wb_id;
- mdp_hw->pipe = sde_mdp_pipe_assign(mdata, mdp_hw->mixer, pipe_ndx);
- if (IS_ERR_OR_NULL(mdp_hw->pipe)) {
- SDEROT_ERR("dma pipe allocation failed\n");
- ret = -ENODEV;
- goto error;
- }
- mdp_hw->pipe->mixer_left = mdp_hw->mixer;
- mdp_hw->hw.wb_id = mdp_hw->wb->num;
- mdp_hw->hw.pending_count = 0;
- atomic_set(&mdp_hw->hw.num_active, 0);
- mdp_hw->hw.max_active = 1;
- init_waitqueue_head(&mdp_hw->hw.wait_queue);
- return mdp_hw;
- error:
- if (!IS_ERR_OR_NULL(mdp_hw->pipe))
- sde_mdp_pipe_destroy(mdp_hw->pipe);
- if (!IS_ERR_OR_NULL(mdp_hw->ctl)) {
- if (mdp_hw->ctl->ops.stop_fnc)
- mdp_hw->ctl->ops.stop_fnc(mdp_hw->ctl, 0);
- sde_mdp_ctl_free(mdp_hw->ctl);
- }
- devm_kfree(&mgr->pdev->dev, mdp_hw);
- return ERR_PTR(ret);
- }
- static void sde_rotator_hw_free(struct sde_rot_mgr *mgr,
- struct sde_mdp_hw_resource *mdp_hw)
- {
- struct sde_mdp_mixer *mixer;
- struct sde_mdp_ctl *ctl;
- if (!mgr || !mdp_hw)
- return;
- mixer = mdp_hw->pipe->mixer_left;
- sde_mdp_pipe_destroy(mdp_hw->pipe);
- ctl = sde_mdp_ctl_mixer_switch(mixer->ctl,
- SDE_MDP_WB_CTL_TYPE_BLOCK);
- if (ctl) {
- if (ctl->ops.stop_fnc)
- ctl->ops.stop_fnc(ctl, 0);
- sde_mdp_ctl_free(ctl);
- }
- devm_kfree(&mgr->pdev->dev, mdp_hw);
- }
- static struct sde_rot_hw_resource *sde_rotator_hw_alloc_ext(
- struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id)
- {
- struct sde_mdp_hw_resource *mdp_hw;
- struct sde_rotator_r1_data *hw_data;
- if (!mgr || !mgr->hw_data)
- return NULL;
- hw_data = mgr->hw_data;
- mdp_hw = hw_data->mdp_hw;
- return &mdp_hw->hw;
- }
- static void sde_rotator_hw_free_ext(struct sde_rot_mgr *mgr,
- struct sde_rot_hw_resource *hw)
- {
- /* currently nothing specific for this device */
- }
- static void sde_rotator_translate_rect(struct sde_rect *dst,
- struct sde_rect *src)
- {
- dst->x = src->x;
- dst->y = src->y;
- dst->w = src->w;
- dst->h = src->h;
- }
- static u32 sde_rotator_translate_flags(u32 input)
- {
- u32 output = 0;
- if (input & SDE_ROTATION_NOP)
- output |= SDE_ROT_NOP;
- if (input & SDE_ROTATION_FLIP_LR)
- output |= SDE_FLIP_LR;
- if (input & SDE_ROTATION_FLIP_UD)
- output |= SDE_FLIP_UD;
- if (input & SDE_ROTATION_90)
- output |= SDE_ROT_90;
- if (input & SDE_ROTATION_DEINTERLACE)
- output |= SDE_DEINTERLACE;
- if (input & SDE_ROTATION_SECURE)
- output |= SDE_SECURE_OVERLAY_SESSION;
- return output;
- }
- static int sde_rotator_config_hw(struct sde_rot_hw_resource *hw,
- struct sde_rot_entry *entry)
- {
- struct sde_mdp_hw_resource *mdp_hw;
- struct sde_mdp_pipe *pipe;
- struct sde_rotation_item *item;
- int ret;
- if (!hw || !entry) {
- SDEROT_ERR("null hw resource/entry");
- return -EINVAL;
- }
- mdp_hw = container_of(hw, struct sde_mdp_hw_resource, hw);
- pipe = mdp_hw->pipe;
- item = &entry->item;
- pipe->flags = sde_rotator_translate_flags(item->flags);
- pipe->src_fmt = sde_get_format_params(item->input.format);
- pipe->img_width = item->input.width;
- pipe->img_height = item->input.height;
- sde_rotator_translate_rect(&pipe->src, &item->src_rect);
- sde_rotator_translate_rect(&pipe->dst, &item->src_rect);
- pipe->params_changed++;
- ret = sde_mdp_pipe_queue_data(pipe, &entry->src_buf);
- SDEROT_DBG("Config pipe. src{%u,%u,%u,%u}f=%u\n"
- "dst{%u,%u,%u,%u}f=%u session_id=%u\n",
- item->src_rect.x, item->src_rect.y,
- item->src_rect.w, item->src_rect.h, item->input.format,
- item->dst_rect.x, item->dst_rect.y,
- item->dst_rect.w, item->dst_rect.h, item->output.format,
- item->session_id);
- return ret;
- }
- static int sde_rotator_cancel_hw(struct sde_rot_hw_resource *hw,
- struct sde_rot_entry *entry)
- {
- return 0;
- }
- static int sde_rotator_abort_hw(struct sde_rot_hw_resource *hw,
- struct sde_rot_entry *entry)
- {
- return 0;
- }
- static int sde_rotator_kickoff_entry(struct sde_rot_hw_resource *hw,
- struct sde_rot_entry *entry)
- {
- struct sde_mdp_hw_resource *mdp_hw;
- int ret;
- struct sde_mdp_writeback_arg wb_args;
- if (!hw || !entry) {
- SDEROT_ERR("null hw resource/entry");
- return -EINVAL;
- }
- wb_args.data = &entry->dst_buf;
- wb_args.priv_data = entry;
- mdp_hw = container_of(hw, struct sde_mdp_hw_resource, hw);
- ret = sde_mdp_writeback_display_commit(mdp_hw->ctl, &wb_args);
- return ret;
- }
- static int sde_rotator_wait_for_entry(struct sde_rot_hw_resource *hw,
- struct sde_rot_entry *entry)
- {
- struct sde_mdp_hw_resource *mdp_hw;
- int ret;
- struct sde_mdp_ctl *ctl;
- if (!hw || !entry) {
- SDEROT_ERR("null hw resource/entry");
- return -EINVAL;
- }
- mdp_hw = container_of(hw, struct sde_mdp_hw_resource, hw);
- ctl = mdp_hw->ctl;
- ret = sde_mdp_display_wait4comp(ctl);
- return ret;
- }
- static int sde_rotator_hw_validate_entry(struct sde_rot_mgr *mgr,
- struct sde_rot_entry *entry)
- {
- int ret = 0;
- u16 src_w, src_h, dst_w, dst_h, bit;
- struct sde_rotation_item *item = &entry->item;
- struct sde_mdp_format_params *fmt;
- src_w = item->src_rect.w;
- src_h = item->src_rect.h;
- if (item->flags & SDE_ROTATION_90) {
- dst_w = item->dst_rect.h;
- dst_h = item->dst_rect.w;
- } else {
- dst_w = item->dst_rect.w;
- dst_h = item->dst_rect.h;
- }
- entry->dnsc_factor_w = 0;
- entry->dnsc_factor_h = 0;
- if ((src_w != dst_w) || (src_h != dst_h)) {
- if ((src_w % dst_w) || (src_h % dst_h)) {
- SDEROT_DBG("non integral scale not support\n");
- ret = -EINVAL;
- goto dnsc_err;
- }
- entry->dnsc_factor_w = src_w / dst_w;
- bit = fls(entry->dnsc_factor_w);
- if ((entry->dnsc_factor_w & ~BIT(bit - 1)) || (bit > 5)) {
- SDEROT_DBG("non power-of-2 scale not support\n");
- ret = -EINVAL;
- goto dnsc_err;
- }
- entry->dnsc_factor_h = src_h / dst_h;
- bit = fls(entry->dnsc_factor_h);
- if ((entry->dnsc_factor_h & ~BIT(bit - 1)) || (bit > 5)) {
- SDEROT_DBG("non power-of-2 dscale not support\n");
- ret = -EINVAL;
- goto dnsc_err;
- }
- }
- fmt = sde_get_format_params(item->output.format);
- if (sde_mdp_is_ubwc_format(fmt) &&
- (entry->dnsc_factor_h || entry->dnsc_factor_w)) {
- SDEROT_DBG("downscale with ubwc not support\n");
- ret = -EINVAL;
- }
- dnsc_err:
- /* Downscaler does not support asymmetrical dnsc */
- if (entry->dnsc_factor_w != entry->dnsc_factor_h) {
- SDEROT_DBG("asymmetric downscale not support\n");
- ret = -EINVAL;
- }
- if (ret) {
- entry->dnsc_factor_w = 0;
- entry->dnsc_factor_h = 0;
- }
- return ret;
- }
- static ssize_t sde_rotator_hw_show_caps(struct sde_rot_mgr *mgr,
- struct device_attribute *attr, char *buf, ssize_t len)
- {
- struct sde_rotator_r1_data *hw_data;
- int cnt = 0;
- if (!mgr || !buf)
- return 0;
- hw_data = mgr->hw_data;
- #define SPRINT(fmt, ...) \
- (cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))
- SPRINT("wb_id=%d\n", hw_data->wb_id);
- SPRINT("ctl_id=%d\n", hw_data->ctl_id);
- return cnt;
- }
- static ssize_t sde_rotator_hw_show_state(struct sde_rot_mgr *mgr,
- struct device_attribute *attr, char *buf, ssize_t len)
- {
- struct sde_rotator_r1_data *hw_data;
- int cnt = 0;
- if (!mgr || !buf)
- return 0;
- hw_data = mgr->hw_data;
- #define SPRINT(fmt, ...) \
- (cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))
- if (hw_data && hw_data->mdp_hw) {
- struct sde_rot_hw_resource *hw = &hw_data->mdp_hw->hw;
- SPRINT("irq_num=%d\n", hw_data->irq_num);
- SPRINT("max_active=%d\n", hw->max_active);
- SPRINT("num_active=%d\n", atomic_read(&hw->num_active));
- SPRINT("pending_cnt=%u\n", hw->pending_count);
- }
- return cnt;
- }
- /*
- * sde_hw_rotator_get_pixfmt - get the indexed pixel format
- * @mgr: Pointer to rotator manager
- * @index: index of pixel format
- * @input: true for input port; false for output port
- * @mode: operating mode
- */
- static u32 sde_hw_rotator_get_pixfmt(struct sde_rot_mgr *mgr,
- int index, bool input, u32 mode)
- {
- if (input) {
- if (index < ARRAY_SIZE(sde_hw_rotator_input_pixfmts))
- return sde_hw_rotator_input_pixfmts[index];
- else
- return 0;
- } else {
- if (index < ARRAY_SIZE(sde_hw_rotator_output_pixfmts))
- return sde_hw_rotator_output_pixfmts[index];
- else
- return 0;
- }
- }
- /*
- * sde_hw_rotator_is_valid_pixfmt - verify if the given pixel format is valid
- * @mgr: Pointer to rotator manager
- * @pixfmt: pixel format to be verified
- * @input: true for input port; false for output port
- * @mode: operating mode
- */
- static int sde_hw_rotator_is_valid_pixfmt(struct sde_rot_mgr *mgr, u32 pixfmt,
- bool input, u32 mode)
- {
- int i;
- if (input) {
- for (i = 0; i < ARRAY_SIZE(sde_hw_rotator_input_pixfmts); i++)
- if (sde_hw_rotator_input_pixfmts[i] == pixfmt)
- return true;
- } else {
- for (i = 0; i < ARRAY_SIZE(sde_hw_rotator_output_pixfmts); i++)
- if (sde_hw_rotator_output_pixfmts[i] == pixfmt)
- return true;
- }
- return false;
- }
- static int sde_rotator_hw_parse_dt(struct sde_rotator_r1_data *hw_data,
- struct platform_device *dev)
- {
- int ret = 0;
- u32 data;
- if (!hw_data || !dev)
- return -EINVAL;
- ret = of_property_read_u32(dev->dev.of_node,
- "qcom,mdss-wb-id", &data);
- if (ret)
- hw_data->wb_id = -1;
- else
- hw_data->wb_id = (int) data;
- ret = of_property_read_u32(dev->dev.of_node,
- "qcom,mdss-ctl-id", &data);
- if (ret)
- hw_data->ctl_id = -1;
- else
- hw_data->ctl_id = (int) data;
- return ret;
- }
- static int sde_rotator_hw_rev_init(struct sde_rot_data_type *mdata)
- {
- if (!mdata) {
- SDEROT_ERR("null rotator data\n");
- return -EINVAL;
- }
- clear_bit(SDE_QOS_PER_PIPE_IB, mdata->sde_qos_map);
- set_bit(SDE_QOS_OVERHEAD_FACTOR, mdata->sde_qos_map);
- clear_bit(SDE_QOS_CDP, mdata->sde_qos_map);
- set_bit(SDE_QOS_OTLIM, mdata->sde_qos_map);
- set_bit(SDE_QOS_PER_PIPE_LUT, mdata->sde_qos_map);
- clear_bit(SDE_QOS_SIMPLIFIED_PREFILL, mdata->sde_qos_map);
- set_bit(SDE_CAPS_R1_WB, mdata->sde_caps_map);
- return 0;
- }
- enum {
- SDE_ROTATOR_INTR_WB_0,
- SDE_ROTATOR_INTR_WB_1,
- SDE_ROTATOR_INTR_MAX,
- };
- struct intr_callback {
- void (*func)(void *data);
- void *arg;
- };
- struct intr_callback sde_intr_cb[SDE_ROTATOR_INTR_MAX];
- int sde_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
- void (*fnc_ptr)(void *), void *arg)
- {
- if (intf_num >= SDE_ROTATOR_INTR_MAX) {
- SDEROT_WARN("invalid intr type=%u intf_num=%u\n",
- intr_type, intf_num);
- return -EINVAL;
- }
- sde_intr_cb[intf_num].func = fnc_ptr;
- sde_intr_cb[intf_num].arg = arg;
- return 0;
- }
- static irqreturn_t sde_irq_handler(int irq, void *ptr)
- {
- struct sde_rot_data_type *mdata = ptr;
- irqreturn_t ret = IRQ_NONE;
- u32 isr;
- isr = readl_relaxed(mdata->mdp_base + SDE_MDP_REG_INTR_STATUS);
- SDEROT_DBG("intr_status = %8.8x\n", isr);
- if (isr & SDE_MDP_INTR_WB_0_DONE) {
- struct intr_callback *cb = &sde_intr_cb[SDE_ROTATOR_INTR_WB_0];
- if (cb->func) {
- writel_relaxed(SDE_MDP_INTR_WB_0_DONE,
- mdata->mdp_base + SDE_MDP_REG_INTR_CLEAR);
- cb->func(cb->arg);
- ret = IRQ_HANDLED;
- }
- }
- if (isr & SDE_MDP_INTR_WB_1_DONE) {
- struct intr_callback *cb = &sde_intr_cb[SDE_ROTATOR_INTR_WB_1];
- if (cb->func) {
- writel_relaxed(SDE_MDP_INTR_WB_1_DONE,
- mdata->mdp_base + SDE_MDP_REG_INTR_CLEAR);
- cb->func(cb->arg);
- ret = IRQ_HANDLED;
- }
- }
- return ret;
- }
- static void sde_rotator_hw_destroy(struct sde_rot_mgr *mgr)
- {
- struct sde_rot_data_type *mdata = sde_rot_get_mdata();
- struct sde_rotator_r1_data *hw_data;
- if (!mgr || !mgr->pdev || !mgr->hw_data)
- return;
- hw_data = mgr->hw_data;
- if (hw_data->irq_num >= 0)
- devm_free_irq(&mgr->pdev->dev, hw_data->irq_num, mdata);
- sde_rotator_hw_free(mgr, hw_data->mdp_hw);
- devm_kfree(&mgr->pdev->dev, mgr->hw_data);
- mgr->hw_data = NULL;
- }
- int sde_rotator_r1_init(struct sde_rot_mgr *mgr)
- {
- struct sde_rot_data_type *mdata = sde_rot_get_mdata();
- struct sde_rotator_r1_data *hw_data;
- int ret;
- if (!mgr || !mgr->pdev) {
- SDEROT_ERR("null rotator manager/platform device");
- return -EINVAL;
- }
- hw_data = devm_kzalloc(&mgr->pdev->dev,
- sizeof(struct sde_rotator_r1_data), GFP_KERNEL);
- if (hw_data == NULL)
- return -ENOMEM;
- mgr->hw_data = hw_data;
- mgr->ops_config_hw = sde_rotator_config_hw;
- mgr->ops_cancel_hw = sde_rotator_cancel_hw;
- mgr->ops_abort_hw = sde_rotator_abort_hw;
- mgr->ops_kickoff_entry = sde_rotator_kickoff_entry;
- mgr->ops_wait_for_entry = sde_rotator_wait_for_entry;
- mgr->ops_hw_alloc = sde_rotator_hw_alloc_ext;
- mgr->ops_hw_free = sde_rotator_hw_free_ext;
- mgr->ops_hw_destroy = sde_rotator_hw_destroy;
- mgr->ops_hw_validate_entry = sde_rotator_hw_validate_entry;
- mgr->ops_hw_show_caps = sde_rotator_hw_show_caps;
- mgr->ops_hw_show_state = sde_rotator_hw_show_state;
- mgr->ops_hw_create_debugfs = sde_rotator_r1_create_debugfs;
- mgr->ops_hw_get_pixfmt = sde_hw_rotator_get_pixfmt;
- mgr->ops_hw_is_valid_pixfmt = sde_hw_rotator_is_valid_pixfmt;
- ret = sde_rotator_hw_parse_dt(mgr->hw_data, mgr->pdev);
- if (ret)
- goto error_parse_dt;
- hw_data->irq_num = platform_get_irq(mgr->pdev, 0);
- if (hw_data->irq_num < 0) {
- SDEROT_ERR("fail to get rotator irq\n");
- } else {
- ret = devm_request_threaded_irq(&mgr->pdev->dev,
- hw_data->irq_num,
- sde_irq_handler, NULL,
- 0, "sde_rotator_r1", mdata);
- if (ret) {
- SDEROT_ERR("fail to request irq r:%d\n", ret);
- hw_data->irq_num = -1;
- } else {
- disable_irq(hw_data->irq_num);
- }
- }
- hw_data->mdp_hw = sde_rotator_hw_alloc(mgr, hw_data->ctl_id,
- hw_data->wb_id, hw_data->irq_num);
- if (IS_ERR_OR_NULL(hw_data->mdp_hw))
- goto error_hw_alloc;
- ret = sde_rotator_hw_rev_init(sde_rot_get_mdata());
- if (ret)
- goto error_hw_rev_init;
- hw_data->mgr = mgr;
- return 0;
- error_hw_rev_init:
- if (hw_data->irq_num >= 0)
- devm_free_irq(&mgr->pdev->dev, hw_data->irq_num, mdata);
- sde_rotator_hw_free(mgr, hw_data->mdp_hw);
- error_hw_alloc:
- devm_kfree(&mgr->pdev->dev, mgr->hw_data);
- error_parse_dt:
- return ret;
- }
|