/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" #include "mtk_dump.h" #include "mtk_rect.h" #include "mtk_drm_drv.h" #define DISP_REG_RSZ_ENABLE (0x000) #define FLD_RSZ_RST REG_FLD_MSB_LSB(16, 16) #define FLD_RSZ_EN REG_FLD_MSB_LSB(0, 0) #define DISP_REG_RSZ_CONTROL_1 (0x004) #define FLD_RSZ_INT_WCLR_EN REG_FLD_MSB_LSB(31, 31) #define FLD_RSZ_INTEN REG_FLD_MSB_LSB(30, 28) #define FLD_RSZ_DCM_DIS REG_FLD_MSB_LSB(27, 27) #define FLD_RSZ_VERTICAL_TABLE_SELECT REG_FLD_MSB_LSB(25, 21) #define FLD_RSZ_HORIZONTAL_TABLE_SELECT REG_FLD_MSB_LSB(20, 16) #define FLD_RSZ_VERTICAL_EN REG_FLD_MSB_LSB(1, 1) #define FLD_RSZ_HORIZONTAL_EN REG_FLD_MSB_LSB(0, 0) #define DISP_REG_RSZ_CONTROL_2 (0x008) #define FLD_RSZ_RGB_BIT_MODE REG_FLD_MSB_LSB(28, 28) #define FLD_RSZ_POWER_SAVING REG_FLD_MSB_LSB(9, 9) #define DISP_REG_RSZ_INT_FLAG (0x00c) #define FLD_RSZ_SOF_RESET REG_FLD_MSB_LSB(5, 5) #define FLD_RSZ_SIZE_ERR REG_FLD_MSB_LSB(4, 4) #define FLD_RSZ_FRAME_END REG_FLD_MSB_LSB(1, 1) #define FLD_RSZ_FRAME_START REG_FLD_MSB_LSB(0, 0) #define DISP_REG_RSZ_INPUT_IMAGE (0x010) #define FLD_RSZ_INPUT_IMAGE_H REG_FLD_MSB_LSB(31, 16) #define FLD_RSZ_INPUT_IMAGE_W REG_FLD_MSB_LSB(15, 0) #define DISP_REG_RSZ_OUTPUT_IMAGE (0x014) #define FLD_RSZ_OUTPUT_IMAGE_H REG_FLD_MSB_LSB(31, 16) #define FLD_RSZ_OUTPUT_IMAGE_W REG_FLD_MSB_LSB(15, 0) #define DISP_REG_RSZ_HORIZONTAL_COEFF_STEP (0x018) #define DISP_REG_RSZ_VERTICAL_COEFF_STEP (0x01c) #define DISP_REG_RSZ_LUMA_HORIZONTAL_INTEGER_OFFSET (0x020) #define DISP_REG_RSZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET (0x024) #define DISP_REG_RSZ_LUMA_VERTICAL_INTEGER_OFFSET (0x028) #define DISP_REG_RSZ_LUMA_VERTICAL_SUBPIXEL_OFFSET (0x02c) #define DISP_REG_RSZ_DEBUG_SEL (0x044) #define DISP_REG_RSZ_DEBUG (0x048) #define DISP_REG_RSZ_SHADOW_CTRL (0x0f0) #define FLD_RSZ_READ_WRK_REG REG_FLD_MSB_LSB(2, 2) #define FLD_RSZ_FORCE_COMMIT REG_FLD_MSB_LSB(1, 1) #define FLD_RSZ_BYPASS_SHADOW REG_FLD_MSB_LSB(0, 0) #define RSZ_READ_WRK_REG BIT(2) #define RSZ_FORCE_COMMIT BIT(1) #define RSZ_BYPASS_SHADOW BIT(0) #define UNIT 32768 #define TILE_LOSS 4 #define TILE_LOSS_LEFT 4 #define TILE_LOSS_RIGHT 4 struct mtk_disp_rsz_data { unsigned int tile_length; unsigned int in_max_height; bool support_shadow; }; enum mtk_rsz_color_format { ARGB8101010, RGB999, RGB888, UNKNOWN_RSZ_CFMT, }; struct rsz_tile_params { u32 step; u32 int_offset; u32 sub_offset; u32 in_len; u32 out_len; }; struct mtk_rsz_config_struct { struct rsz_tile_params tw[2]; struct rsz_tile_params th[1]; enum mtk_rsz_color_format fmt; u32 frm_in_w; u32 frm_in_h; u32 frm_out_w; u32 frm_out_h; }; /** * struct mtk_disp_rsz - DISP_RSZ driver structure * @ddp_comp - structure containing type enum and hardware resources * @crtc - associated crtc to report irq events to */ struct mtk_disp_rsz { struct mtk_ddp_comp ddp_comp; struct drm_crtc *crtc; const struct mtk_disp_rsz_data *data; }; static inline struct mtk_disp_rsz *comp_to_rsz(struct mtk_ddp_comp *comp) { return container_of(comp, struct mtk_disp_rsz, ddp_comp); } static void mtk_rsz_start(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle) { int ret; ret = pm_runtime_get_sync(comp->dev); if (ret < 0) DRM_ERROR("Failed to enable power domain: %d\n", ret); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_ENABLE, 0x1, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_DEBUG_SEL, 0x3, ~0); } static void mtk_rsz_stop(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle) { int ret; ret = pm_runtime_put(comp->dev); if (ret < 0) DRM_ERROR("Failed to disable power domain: %d\n", ret); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_ENABLE, 0x0, ~0); } int mtk_rsz_calc_tile_params(u32 frm_in_len, u32 frm_out_len, bool tile_mode, struct rsz_tile_params t[]) { u32 tile_loss = 0; u32 step = 0; s32 init_phase = 0; s32 offset[2] = {0}; s32 int_offset[2] = {0}; s32 sub_offset[2] = {0}; u32 tile_in_len[2] = {0}; u32 tile_out_len = 0; if (tile_mode) tile_loss = TILE_LOSS; if (frm_out_len > 1) step = (UNIT * (frm_in_len - 1) + (frm_out_len - 2)) / (frm_out_len - 1); else { DRM_ERROR("%s:%d Division by zero\n", __func__, __LINE__); return -1; } /* left half */ offset[0] = (step * (frm_out_len - 1) - UNIT * (frm_in_len - 1)) / 2; init_phase = UNIT - offset[0]; sub_offset[0] = -offset[0]; if (sub_offset[0] < 0) { int_offset[0]--; sub_offset[0] = UNIT + sub_offset[0]; } if (sub_offset[0] >= UNIT) { int_offset[0]++; sub_offset[0] = sub_offset[0] - UNIT; } if (tile_mode) { tile_in_len[0] = frm_in_len / 2 + tile_loss; tile_out_len = frm_out_len / 2; } else { tile_in_len[0] = frm_in_len; tile_out_len = frm_out_len; } t[0].step = step; t[0].int_offset = (u32)(int_offset[0] & 0xffff); t[0].sub_offset = (u32)(sub_offset[0] & 0x1fffff); t[0].in_len = tile_in_len[0]; t[0].out_len = tile_out_len; DDPDBG("%s:%s:step:%u,offset:%u.%u,len:%u->%u\n", __func__, tile_mode ? "dual" : "single", t[0].step, t[0].int_offset, t[0].sub_offset, t[0].in_len, t[0].out_len); if (!tile_mode) return 0; /* right half */ offset[1] = (init_phase + frm_out_len / 2 * step) - (frm_in_len / 2 - tile_loss - (offset[0] ? 1 : 0) + 1) * UNIT + UNIT; int_offset[1] = offset[1] / UNIT; sub_offset[1] = offset[1] - UNIT * int_offset[1]; tile_in_len[1] = frm_in_len / 2 + tile_loss + (offset[0] ? 1 : 0); if (int_offset[1] & 0x1) { int_offset[1]++; tile_in_len[1]++; DDPMSG("right tile int_offset: make odd to even\n"); } t[1].step = step; t[1].int_offset = (u32)(int_offset[1] & 0xffff); t[1].sub_offset = (u32)(sub_offset[1] & 0x1fffff); t[1].in_len = tile_in_len[1]; t[1].out_len = tile_out_len; DDPDBG("%s:%s:step:%u,offset:%u.%u,len:%u->%u\n", __func__, tile_mode ? "dual" : "single", t[1].step, t[1].int_offset, t[1].sub_offset, t[1].in_len, t[1].out_len); return 0; } static int mtk_rsz_set_color_format(enum mtk_rsz_color_format fmt) { u32 reg_val = 0; switch (fmt) { case ARGB8101010: reg_val = REG_FLD_VAL(FLD_RSZ_POWER_SAVING, 0x0); reg_val |= REG_FLD_VAL(FLD_RSZ_RGB_BIT_MODE, 0x0); break; case RGB999: reg_val = REG_FLD_VAL(FLD_RSZ_POWER_SAVING, 0x1); reg_val |= REG_FLD_VAL(FLD_RSZ_RGB_BIT_MODE, 0x0); break; case RGB888: reg_val = REG_FLD_VAL(FLD_RSZ_POWER_SAVING, 0x1); reg_val |= REG_FLD_VAL(FLD_RSZ_RGB_BIT_MODE, 0x1); break; default: DDPMSG("unknown resize color format\n"); break; } return reg_val; } static int mtk_rsz_check_params(struct mtk_rsz_config_struct *rsz_config, unsigned int tile_length) { if ((rsz_config->frm_in_w != rsz_config->frm_out_w || rsz_config->frm_in_h != rsz_config->frm_out_h) && rsz_config->frm_in_w > tile_length) { DDPPR_ERR("%s:need rsz but input width(%u) > limit(%u)\n", __func__, rsz_config->frm_in_w, tile_length); return -EINVAL; } return 0; } static void mtk_rsz_addon_config(struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id prev, enum mtk_ddp_comp_id next, union mtk_addon_config *addon_config, struct cmdq_pkt *handle) { struct mtk_addon_rsz_config config = addon_config->addon_rsz_config; struct mtk_rsz_config_struct *rsz_config = NULL; struct mtk_disp_rsz *rsz = comp_to_rsz(comp); enum mtk_rsz_color_format fmt = RGB888; bool tile_mode = false; u32 reg_val = 0; u32 tile_idx = 0; u32 in_w = 0, in_h = 0, out_w = 0, out_h = 0; rsz_config = kzalloc(sizeof(struct mtk_rsz_config_struct), GFP_KERNEL); if (!rsz_config) { DDPPR_ERR("fail to create rsz_config!\n"); return; } rsz_config->frm_in_w = config.rsz_src_roi.width; rsz_config->frm_in_h = config.rsz_src_roi.height; rsz_config->frm_out_w = config.rsz_dst_roi.width; rsz_config->frm_out_h = config.rsz_dst_roi.height; if (mtk_rsz_check_params(rsz_config, rsz->data->tile_length)) { kfree(rsz_config); return; } if (comp->mtk_crtc->is_dual_pipe) { rsz_config->tw[tile_idx].in_len = addon_config->addon_rsz_config.rsz_param.in_len; rsz_config->tw[tile_idx].out_len = addon_config->addon_rsz_config.rsz_param.out_len; rsz_config->tw[tile_idx].step = addon_config->addon_rsz_config.rsz_param.step; rsz_config->tw[tile_idx].int_offset = addon_config->addon_rsz_config.rsz_param.int_offset; rsz_config->tw[tile_idx].sub_offset = addon_config->addon_rsz_config.rsz_param.sub_offset; } else { mtk_rsz_calc_tile_params(rsz_config->frm_in_w, rsz_config->frm_out_w, tile_mode, rsz_config->tw); } mtk_rsz_calc_tile_params(rsz_config->frm_in_h, rsz_config->frm_out_h, tile_mode, rsz_config->th); in_w = rsz_config->tw[tile_idx].in_len; in_h = rsz_config->th[0].in_len; out_w = rsz_config->tw[tile_idx].out_len; out_h = rsz_config->th[0].out_len; if (in_w > out_w || in_h > out_h) { DDPPR_ERR("DISP_RSZ only supports scale-up,(%ux%u)->(%ux%u)\n", in_w, in_h, out_w, out_h); kfree(rsz_config); return; } reg_val = 0; reg_val |= REG_FLD_VAL(FLD_RSZ_HORIZONTAL_EN, (in_w != out_w)); reg_val |= REG_FLD_VAL(FLD_RSZ_VERTICAL_EN, (in_h != out_h)); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_CONTROL_1, reg_val, ~0); DDPDBG("%s:CONTROL_1:0x%x\n", __func__, reg_val); reg_val = mtk_rsz_set_color_format(fmt); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_CONTROL_2, reg_val, ~0); DDPDBG("%s:CONTROL_2:0x%x\n", __func__, reg_val); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_INPUT_IMAGE, in_h << 16 | in_w, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_OUTPUT_IMAGE, out_h << 16 | out_w, ~0); DDPDBG("%s:%s:(%ux%u)->(%ux%u)\n", __func__, mtk_dump_comp_str(comp), in_w, in_h, out_w, out_h); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_HORIZONTAL_COEFF_STEP, rsz_config->tw[tile_idx].step, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_VERTICAL_COEFF_STEP, rsz_config->th[0].step, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_LUMA_HORIZONTAL_INTEGER_OFFSET, rsz_config->tw[tile_idx].int_offset, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET, rsz_config->tw[tile_idx].sub_offset, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_LUMA_VERTICAL_INTEGER_OFFSET, rsz_config->th[0].int_offset, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_REG_RSZ_LUMA_VERTICAL_SUBPIXEL_OFFSET, rsz_config->th[0].sub_offset, ~0); kfree(rsz_config); } int mtk_rsz_dump(struct mtk_ddp_comp *comp) { void __iomem *baddr = comp->regs; int i = 0; DDPDUMP("== DISP %s REGS ==\n", mtk_dump_comp_str(comp)); for (i = 0; i < 3; i++) { DDPDUMP("0x%03X: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 0x10, readl(baddr + i * 0x10), readl(baddr + i * 0x10 + 0x4), readl(baddr + i * 0x10 + 0x8), readl(baddr + i * 0x10 + 0xC)); } DDPDUMP("0x044: 0x%08x 0x%08x; 0x0F0: 0x%08x\n", readl(baddr + 0x44), readl(baddr + 0x48), readl(baddr + 0xF0)); return 0; } int mtk_rsz_analysis(struct mtk_ddp_comp *comp) { void __iomem *baddr = comp->regs; u32 enable = 0; u32 con1 = 0; u32 con2 = 0; u32 int_flag = 0; u32 in_size = 0; u32 out_size = 0; u32 in_pos = 0; u32 shadow = 0; const int len = 100; char msg[len]; int n = 0; enable = readl(baddr + DISP_REG_RSZ_ENABLE); con1 = readl(baddr + DISP_REG_RSZ_CONTROL_1); con2 = readl(baddr + DISP_REG_RSZ_CONTROL_2); int_flag = readl(baddr + DISP_REG_RSZ_INT_FLAG); in_size = readl(baddr + DISP_REG_RSZ_INPUT_IMAGE); out_size = readl(baddr + DISP_REG_RSZ_OUTPUT_IMAGE); in_pos = readl(baddr + DISP_REG_RSZ_DEBUG); shadow = readl(baddr + DISP_REG_RSZ_SHADOW_CTRL); DDPDUMP("== DISP %s ANALYSIS ==\n", mtk_dump_comp_str(comp)); writel(0x3, baddr + DISP_REG_RSZ_DEBUG_SEL); n = snprintf(msg, len, "en:%d,rst:%d,h_en:%d,v_en:%d,h_table:%d,v_table:%d,", REG_FLD_VAL_GET(FLD_RSZ_EN, enable), REG_FLD_VAL_GET(FLD_RSZ_RST, enable), REG_FLD_VAL_GET(FLD_RSZ_HORIZONTAL_EN, con1), REG_FLD_VAL_GET(FLD_RSZ_VERTICAL_EN, con1), REG_FLD_VAL_GET(FLD_RSZ_HORIZONTAL_TABLE_SELECT, con1), REG_FLD_VAL_GET(FLD_RSZ_VERTICAL_TABLE_SELECT, con1)); n += snprintf(msg + n, len - n, "dcm_dis:%d,int_en:%d,wclr_en:%d\n", REG_FLD_VAL_GET(FLD_RSZ_DCM_DIS, con1), REG_FLD_VAL_GET(FLD_RSZ_INTEN, con1), REG_FLD_VAL_GET(FLD_RSZ_INT_WCLR_EN, con1)); DDPDUMP("%s", msg); n = snprintf(msg, len, "power_saving:%d,rgb_bit_mode:%d,frm_start:%d,frm_end:%d,", REG_FLD_VAL_GET(FLD_RSZ_POWER_SAVING, con2), REG_FLD_VAL_GET(FLD_RSZ_RGB_BIT_MODE, con2), REG_FLD_VAL_GET(FLD_RSZ_FRAME_START, int_flag), REG_FLD_VAL_GET(FLD_RSZ_FRAME_END, int_flag)); n += snprintf(msg + n, len - n, "size_err:%d,sof_rst:%d\n", REG_FLD_VAL_GET(FLD_RSZ_SIZE_ERR, int_flag), REG_FLD_VAL_GET(FLD_RSZ_SOF_RESET, int_flag)); DDPDUMP("%s", msg); n = snprintf(msg, len, "in(%ux%u),out(%ux%u),h_step:%d,v_step:%d\n", REG_FLD_VAL_GET(FLD_RSZ_INPUT_IMAGE_W, in_size), REG_FLD_VAL_GET(FLD_RSZ_INPUT_IMAGE_H, in_size), REG_FLD_VAL_GET(FLD_RSZ_OUTPUT_IMAGE_W, out_size), REG_FLD_VAL_GET(FLD_RSZ_OUTPUT_IMAGE_H, out_size), readl(baddr + DISP_REG_RSZ_HORIZONTAL_COEFF_STEP), readl(baddr + DISP_REG_RSZ_VERTICAL_COEFF_STEP)); DDPDUMP("%s", msg); n = snprintf( msg, len, "luma_h:%d.%d,luma_v:%d.%d\n", readl(baddr + DISP_REG_RSZ_LUMA_HORIZONTAL_INTEGER_OFFSET), readl(baddr + DISP_REG_RSZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET), readl(baddr + DISP_REG_RSZ_LUMA_VERTICAL_INTEGER_OFFSET), readl(baddr + DISP_REG_RSZ_LUMA_VERTICAL_SUBPIXEL_OFFSET)); DDPDUMP("%s", msg); n = snprintf(msg, len, "dbg_sel:%d, in(%u,%u);shadow_ctrl:bypass:%d,force:%d,", readl(baddr + DISP_REG_RSZ_DEBUG_SEL), in_pos & 0xFFFF, (in_pos >> 16) & 0xFFFF, REG_FLD_VAL_GET(FLD_RSZ_BYPASS_SHADOW, shadow), REG_FLD_VAL_GET(FLD_RSZ_FORCE_COMMIT, shadow)); n += snprintf(msg + n, len - n, "read_working:%d\n", REG_FLD_VAL_GET(FLD_RSZ_READ_WRK_REG, shadow)); DDPDUMP("%s", msg); return 0; } static void mtk_rsz_prepare(struct mtk_ddp_comp *comp) { #if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT) struct mtk_disp_rsz *rsz = comp_to_rsz(comp); #endif mtk_ddp_comp_clk_prepare(comp); #if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT) if (rsz->data->support_shadow) { /* Enable shadow register and read shadow register */ mtk_ddp_write_mask_cpu(comp, 0x0, DISP_REG_RSZ_SHADOW_CTRL, RSZ_BYPASS_SHADOW); } else { /* Bypass shadow register and read shadow register */ mtk_ddp_write_mask_cpu(comp, RSZ_BYPASS_SHADOW, DISP_REG_RSZ_SHADOW_CTRL, RSZ_BYPASS_SHADOW); } #else #if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \ || defined(CONFIG_MACH_MT6833) \ || defined(CONFIG_MACH_MT6877) \ || defined(CONFIG_MACH_MT6781) /* Bypass shadow register and read shadow register */ mtk_ddp_write_mask_cpu(comp, RSZ_BYPASS_SHADOW, DISP_REG_RSZ_SHADOW_CTRL, RSZ_BYPASS_SHADOW); #endif #endif } static void mtk_rsz_unprepare(struct mtk_ddp_comp *comp) { mtk_ddp_comp_clk_unprepare(comp); } static const struct mtk_ddp_comp_funcs mtk_disp_rsz_funcs = { .start = mtk_rsz_start, .stop = mtk_rsz_stop, .addon_config = mtk_rsz_addon_config, .prepare = mtk_rsz_prepare, .unprepare = mtk_rsz_unprepare, }; static int mtk_disp_rsz_bind(struct device *dev, struct device *master, void *data) { struct mtk_disp_rsz *priv = dev_get_drvdata(dev); struct drm_device *drm_dev = data; struct mtk_drm_private *private = drm_dev->dev_private; int ret; pr_info("%s\n", __func__); ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp); if (ret < 0) { dev_err(dev, "Failed to register component %s: %d\n", dev->of_node->full_name, ret); return ret; } private->rsz_in_max[0] = priv->data->tile_length; private->rsz_in_max[1] = priv->data->in_max_height; return 0; } static void mtk_disp_rsz_unbind(struct device *dev, struct device *master, void *data) { struct mtk_disp_rsz *priv = dev_get_drvdata(dev); struct drm_device *drm_dev = data; mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp); } static const struct component_ops mtk_disp_rsz_component_ops = { .bind = mtk_disp_rsz_bind, .unbind = mtk_disp_rsz_unbind, }; static int mtk_disp_rsz_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_disp_rsz *priv; enum mtk_ddp_comp_id comp_id; int ret; DDPINFO("%s+\n", __func__); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_RSZ); if ((int)comp_id < 0) { dev_err(dev, "Failed to identify by alias: %d\n", comp_id); return comp_id; } ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id, &mtk_disp_rsz_funcs); if (ret) { dev_err(dev, "Failed to initialize component: %d\n", ret); return ret; } priv->data = of_device_get_match_data(dev); platform_set_drvdata(pdev, priv); pm_runtime_enable(dev); ret = component_add(dev, &mtk_disp_rsz_component_ops); if (ret != 0) { dev_err(dev, "Failed to add component: %d\n", ret); pm_runtime_disable(dev); } DDPINFO("%s-\n", __func__); return ret; } static int mtk_disp_rsz_remove(struct platform_device *pdev) { component_del(&pdev->dev, &mtk_disp_rsz_component_ops); pm_runtime_disable(&pdev->dev); return 0; } static const struct mtk_disp_rsz_data mt6779_rsz_driver_data = { .tile_length = 1088, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6885_rsz_driver_data = { .tile_length = 1440, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6873_rsz_driver_data = { .tile_length = 1440, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6853_rsz_driver_data = { .tile_length = 1088, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6877_rsz_driver_data = { .tile_length = 1088, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6833_rsz_driver_data = { .tile_length = 1088, .in_max_height = 4096, .support_shadow = false, }; static const struct mtk_disp_rsz_data mt6781_rsz_driver_data = { .tile_length = 1200, .in_max_height = 4096, .support_shadow = false, }; static const struct of_device_id mtk_disp_rsz_driver_dt_match[] = { {.compatible = "mediatek,mt6779-disp-rsz", .data = &mt6779_rsz_driver_data}, {.compatible = "mediatek,mt6885-disp-rsz", .data = &mt6885_rsz_driver_data}, {.compatible = "mediatek,mt6873-disp-rsz", .data = &mt6873_rsz_driver_data}, {.compatible = "mediatek,mt6853-disp-rsz", .data = &mt6853_rsz_driver_data}, {.compatible = "mediatek,mt6877-disp-rsz", .data = &mt6877_rsz_driver_data}, {.compatible = "mediatek,mt6833-disp-rsz", .data = &mt6833_rsz_driver_data}, {.compatible = "mediatek,mt6781-disp-rsz", .data = &mt6781_rsz_driver_data}, {}, }; MODULE_DEVICE_TABLE(of, mtk_disp_rsz_driver_dt_match); struct platform_driver mtk_disp_rsz_driver = { .probe = mtk_disp_rsz_probe, .remove = mtk_disp_rsz_remove, .driver = { .name = "mediatek-disp-rsz", .owner = THIS_MODULE, .of_match_table = mtk_disp_rsz_driver_dt_match, }, };