162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2019 NXP. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/clk.h> 762306a36Sopenharmony_ci#include <linux/delay.h> 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/of.h> 1062306a36Sopenharmony_ci#include <linux/platform_device.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "dcss-dev.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define DCSS_DTG_TC_CONTROL_STATUS 0x00 1662306a36Sopenharmony_ci#define CH3_EN BIT(0) 1762306a36Sopenharmony_ci#define CH2_EN BIT(1) 1862306a36Sopenharmony_ci#define CH1_EN BIT(2) 1962306a36Sopenharmony_ci#define OVL_DATA_MODE BIT(3) 2062306a36Sopenharmony_ci#define BLENDER_VIDEO_ALPHA_SEL BIT(7) 2162306a36Sopenharmony_ci#define DTG_START BIT(8) 2262306a36Sopenharmony_ci#define DBY_MODE_EN BIT(9) 2362306a36Sopenharmony_ci#define CH1_ALPHA_SEL BIT(10) 2462306a36Sopenharmony_ci#define CSS_PIX_COMP_SWAP_POS 12 2562306a36Sopenharmony_ci#define CSS_PIX_COMP_SWAP_MASK GENMASK(14, 12) 2662306a36Sopenharmony_ci#define DEFAULT_FG_ALPHA_POS 24 2762306a36Sopenharmony_ci#define DEFAULT_FG_ALPHA_MASK GENMASK(31, 24) 2862306a36Sopenharmony_ci#define DCSS_DTG_TC_DTG 0x04 2962306a36Sopenharmony_ci#define DCSS_DTG_TC_DISP_TOP 0x08 3062306a36Sopenharmony_ci#define DCSS_DTG_TC_DISP_BOT 0x0C 3162306a36Sopenharmony_ci#define DCSS_DTG_TC_CH1_TOP 0x10 3262306a36Sopenharmony_ci#define DCSS_DTG_TC_CH1_BOT 0x14 3362306a36Sopenharmony_ci#define DCSS_DTG_TC_CH2_TOP 0x18 3462306a36Sopenharmony_ci#define DCSS_DTG_TC_CH2_BOT 0x1C 3562306a36Sopenharmony_ci#define DCSS_DTG_TC_CH3_TOP 0x20 3662306a36Sopenharmony_ci#define DCSS_DTG_TC_CH3_BOT 0x24 3762306a36Sopenharmony_ci#define TC_X_POS 0 3862306a36Sopenharmony_ci#define TC_X_MASK GENMASK(12, 0) 3962306a36Sopenharmony_ci#define TC_Y_POS 16 4062306a36Sopenharmony_ci#define TC_Y_MASK GENMASK(28, 16) 4162306a36Sopenharmony_ci#define DCSS_DTG_TC_CTXLD 0x28 4262306a36Sopenharmony_ci#define TC_CTXLD_DB_Y_POS 0 4362306a36Sopenharmony_ci#define TC_CTXLD_DB_Y_MASK GENMASK(12, 0) 4462306a36Sopenharmony_ci#define TC_CTXLD_SB_Y_POS 16 4562306a36Sopenharmony_ci#define TC_CTXLD_SB_Y_MASK GENMASK(28, 16) 4662306a36Sopenharmony_ci#define DCSS_DTG_TC_CH1_BKRND 0x2C 4762306a36Sopenharmony_ci#define DCSS_DTG_TC_CH2_BKRND 0x30 4862306a36Sopenharmony_ci#define BKRND_R_Y_COMP_POS 20 4962306a36Sopenharmony_ci#define BKRND_R_Y_COMP_MASK GENMASK(29, 20) 5062306a36Sopenharmony_ci#define BKRND_G_U_COMP_POS 10 5162306a36Sopenharmony_ci#define BKRND_G_U_COMP_MASK GENMASK(19, 10) 5262306a36Sopenharmony_ci#define BKRND_B_V_COMP_POS 0 5362306a36Sopenharmony_ci#define BKRND_B_V_COMP_MASK GENMASK(9, 0) 5462306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_DBY_RANGEINV 0x38 5562306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_DBY_RANGEMIN 0x3C 5662306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_DBY_BDP 0x40 5762306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_BKRND_I 0x44 5862306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_BKRND_P 0x48 5962306a36Sopenharmony_ci#define DCSS_DTG_BLENDER_BKRND_T 0x4C 6062306a36Sopenharmony_ci#define DCSS_DTG_LINE0_INT 0x50 6162306a36Sopenharmony_ci#define DCSS_DTG_LINE1_INT 0x54 6262306a36Sopenharmony_ci#define DCSS_DTG_BG_ALPHA_DEFAULT 0x58 6362306a36Sopenharmony_ci#define DCSS_DTG_INT_STATUS 0x5C 6462306a36Sopenharmony_ci#define DCSS_DTG_INT_CONTROL 0x60 6562306a36Sopenharmony_ci#define DCSS_DTG_TC_CH3_BKRND 0x64 6662306a36Sopenharmony_ci#define DCSS_DTG_INT_MASK 0x68 6762306a36Sopenharmony_ci#define LINE0_IRQ BIT(0) 6862306a36Sopenharmony_ci#define LINE1_IRQ BIT(1) 6962306a36Sopenharmony_ci#define LINE2_IRQ BIT(2) 7062306a36Sopenharmony_ci#define LINE3_IRQ BIT(3) 7162306a36Sopenharmony_ci#define DCSS_DTG_LINE2_INT 0x6C 7262306a36Sopenharmony_ci#define DCSS_DTG_LINE3_INT 0x70 7362306a36Sopenharmony_ci#define DCSS_DTG_DBY_OL 0x74 7462306a36Sopenharmony_ci#define DCSS_DTG_DBY_BL 0x78 7562306a36Sopenharmony_ci#define DCSS_DTG_DBY_EL 0x7C 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistruct dcss_dtg { 7862306a36Sopenharmony_ci struct device *dev; 7962306a36Sopenharmony_ci struct dcss_ctxld *ctxld; 8062306a36Sopenharmony_ci void __iomem *base_reg; 8162306a36Sopenharmony_ci u32 base_ofs; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci u32 ctx_id; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci bool in_use; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci u32 dis_ulc_x; 8862306a36Sopenharmony_ci u32 dis_ulc_y; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci u32 control_status; 9162306a36Sopenharmony_ci u32 alpha; 9262306a36Sopenharmony_ci u32 alpha_cfg; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci int ctxld_kick_irq; 9562306a36Sopenharmony_ci bool ctxld_kick_irq_en; 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic void dcss_dtg_write(struct dcss_dtg *dtg, u32 val, u32 ofs) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci if (!dtg->in_use) 10162306a36Sopenharmony_ci dcss_writel(val, dtg->base_reg + ofs); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci dcss_ctxld_write(dtg->ctxld, dtg->ctx_id, 10462306a36Sopenharmony_ci val, dtg->base_ofs + ofs); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic irqreturn_t dcss_dtg_irq_handler(int irq, void *data) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct dcss_dtg *dtg = data; 11062306a36Sopenharmony_ci u32 status; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (!(status & LINE0_IRQ)) 11562306a36Sopenharmony_ci return IRQ_NONE; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci dcss_ctxld_kick(dtg->ctxld); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci dcss_writel(status & LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return IRQ_HANDLED; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic int dcss_dtg_irq_config(struct dcss_dtg *dtg, 12562306a36Sopenharmony_ci struct platform_device *pdev) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci int ret; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci dtg->ctxld_kick_irq = platform_get_irq_byname(pdev, "ctxld_kick"); 13062306a36Sopenharmony_ci if (dtg->ctxld_kick_irq < 0) 13162306a36Sopenharmony_ci return dtg->ctxld_kick_irq; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci dcss_update(0, LINE0_IRQ | LINE1_IRQ, 13462306a36Sopenharmony_ci dtg->base_reg + DCSS_DTG_INT_MASK); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ret = request_irq(dtg->ctxld_kick_irq, dcss_dtg_irq_handler, 13762306a36Sopenharmony_ci 0, "dcss_ctxld_kick", dtg); 13862306a36Sopenharmony_ci if (ret) { 13962306a36Sopenharmony_ci dev_err(dtg->dev, "dtg: irq request failed.\n"); 14062306a36Sopenharmony_ci return ret; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci disable_irq(dtg->ctxld_kick_irq); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci dtg->ctxld_kick_irq_en = false; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci return 0; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciint dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci int ret = 0; 15362306a36Sopenharmony_ci struct dcss_dtg *dtg; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci dtg = kzalloc(sizeof(*dtg), GFP_KERNEL); 15662306a36Sopenharmony_ci if (!dtg) 15762306a36Sopenharmony_ci return -ENOMEM; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci dcss->dtg = dtg; 16062306a36Sopenharmony_ci dtg->dev = dcss->dev; 16162306a36Sopenharmony_ci dtg->ctxld = dcss->ctxld; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci dtg->base_reg = ioremap(dtg_base, SZ_4K); 16462306a36Sopenharmony_ci if (!dtg->base_reg) { 16562306a36Sopenharmony_ci dev_err(dcss->dev, "dtg: unable to remap dtg base\n"); 16662306a36Sopenharmony_ci ret = -ENOMEM; 16762306a36Sopenharmony_ci goto err_ioremap; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci dtg->base_ofs = dtg_base; 17162306a36Sopenharmony_ci dtg->ctx_id = CTX_DB; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci dtg->alpha = 255; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci dtg->control_status |= OVL_DATA_MODE | BLENDER_VIDEO_ALPHA_SEL | 17662306a36Sopenharmony_ci ((dtg->alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci ret = dcss_dtg_irq_config(dtg, to_platform_device(dcss->dev)); 17962306a36Sopenharmony_ci if (ret) 18062306a36Sopenharmony_ci goto err_irq; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cierr_irq: 18562306a36Sopenharmony_ci iounmap(dtg->base_reg); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cierr_ioremap: 18862306a36Sopenharmony_ci kfree(dtg); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_civoid dcss_dtg_exit(struct dcss_dtg *dtg) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci free_irq(dtg->ctxld_kick_irq, dtg); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (dtg->base_reg) 19862306a36Sopenharmony_ci iounmap(dtg->base_reg); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci kfree(dtg); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_civoid dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dtg->dev); 20662306a36Sopenharmony_ci u16 dtg_lrc_x, dtg_lrc_y; 20762306a36Sopenharmony_ci u16 dis_ulc_x, dis_ulc_y; 20862306a36Sopenharmony_ci u16 dis_lrc_x, dis_lrc_y; 20962306a36Sopenharmony_ci u32 sb_ctxld_trig, db_ctxld_trig; 21062306a36Sopenharmony_ci u32 pixclock = vm->pixelclock; 21162306a36Sopenharmony_ci u32 actual_clk; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci dtg_lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len + 21462306a36Sopenharmony_ci vm->hactive - 1; 21562306a36Sopenharmony_ci dtg_lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len + 21662306a36Sopenharmony_ci vm->vactive - 1; 21762306a36Sopenharmony_ci dis_ulc_x = vm->hsync_len + vm->hback_porch - 1; 21862306a36Sopenharmony_ci dis_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch - 1; 21962306a36Sopenharmony_ci dis_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1; 22062306a36Sopenharmony_ci dis_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch + 22162306a36Sopenharmony_ci vm->vactive - 1; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci clk_disable_unprepare(dcss->pix_clk); 22462306a36Sopenharmony_ci clk_set_rate(dcss->pix_clk, vm->pixelclock); 22562306a36Sopenharmony_ci clk_prepare_enable(dcss->pix_clk); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci actual_clk = clk_get_rate(dcss->pix_clk); 22862306a36Sopenharmony_ci if (pixclock != actual_clk) { 22962306a36Sopenharmony_ci dev_info(dtg->dev, 23062306a36Sopenharmony_ci "Pixel clock set to %u kHz instead of %u kHz.\n", 23162306a36Sopenharmony_ci (actual_clk / 1000), (pixclock / 1000)); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci dcss_dtg_write(dtg, ((dtg_lrc_y << TC_Y_POS) | dtg_lrc_x), 23562306a36Sopenharmony_ci DCSS_DTG_TC_DTG); 23662306a36Sopenharmony_ci dcss_dtg_write(dtg, ((dis_ulc_y << TC_Y_POS) | dis_ulc_x), 23762306a36Sopenharmony_ci DCSS_DTG_TC_DISP_TOP); 23862306a36Sopenharmony_ci dcss_dtg_write(dtg, ((dis_lrc_y << TC_Y_POS) | dis_lrc_x), 23962306a36Sopenharmony_ci DCSS_DTG_TC_DISP_BOT); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci dtg->dis_ulc_x = dis_ulc_x; 24262306a36Sopenharmony_ci dtg->dis_ulc_y = dis_ulc_y; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci sb_ctxld_trig = ((0 * dis_lrc_y / 100) << TC_CTXLD_SB_Y_POS) & 24562306a36Sopenharmony_ci TC_CTXLD_SB_Y_MASK; 24662306a36Sopenharmony_ci db_ctxld_trig = ((99 * dis_lrc_y / 100) << TC_CTXLD_DB_Y_POS) & 24762306a36Sopenharmony_ci TC_CTXLD_DB_Y_MASK; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci dcss_dtg_write(dtg, sb_ctxld_trig | db_ctxld_trig, DCSS_DTG_TC_CTXLD); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* vblank trigger */ 25262306a36Sopenharmony_ci dcss_dtg_write(dtg, 0, DCSS_DTG_LINE1_INT); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* CTXLD trigger */ 25562306a36Sopenharmony_ci dcss_dtg_write(dtg, ((90 * dis_lrc_y) / 100) << 16, DCSS_DTG_LINE0_INT); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_civoid dcss_dtg_plane_pos_set(struct dcss_dtg *dtg, int ch_num, 25962306a36Sopenharmony_ci int px, int py, int pw, int ph) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci u16 p_ulc_x, p_ulc_y; 26262306a36Sopenharmony_ci u16 p_lrc_x, p_lrc_y; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci p_ulc_x = dtg->dis_ulc_x + px; 26562306a36Sopenharmony_ci p_ulc_y = dtg->dis_ulc_y + py; 26662306a36Sopenharmony_ci p_lrc_x = p_ulc_x + pw; 26762306a36Sopenharmony_ci p_lrc_y = p_ulc_y + ph; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (!px && !py && !pw && !ph) { 27062306a36Sopenharmony_ci dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num); 27162306a36Sopenharmony_ci dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num); 27262306a36Sopenharmony_ci } else { 27362306a36Sopenharmony_ci dcss_dtg_write(dtg, ((p_ulc_y << TC_Y_POS) | p_ulc_x), 27462306a36Sopenharmony_ci DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num); 27562306a36Sopenharmony_ci dcss_dtg_write(dtg, ((p_lrc_y << TC_Y_POS) | p_lrc_x), 27662306a36Sopenharmony_ci DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cibool dcss_dtg_global_alpha_changed(struct dcss_dtg *dtg, int ch_num, int alpha) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci if (ch_num) 28362306a36Sopenharmony_ci return false; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return alpha != dtg->alpha; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid dcss_dtg_plane_alpha_set(struct dcss_dtg *dtg, int ch_num, 28962306a36Sopenharmony_ci const struct drm_format_info *format, int alpha) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci /* we care about alpha only when channel 0 is concerned */ 29262306a36Sopenharmony_ci if (ch_num) 29362306a36Sopenharmony_ci return; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* 29662306a36Sopenharmony_ci * Use global alpha if pixel format does not have alpha channel or the 29762306a36Sopenharmony_ci * user explicitly chose to use global alpha (i.e. alpha is not OPAQUE). 29862306a36Sopenharmony_ci */ 29962306a36Sopenharmony_ci if (!format->has_alpha || alpha != 255) 30062306a36Sopenharmony_ci dtg->alpha_cfg = (alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK; 30162306a36Sopenharmony_ci else /* use per-pixel alpha otherwise */ 30262306a36Sopenharmony_ci dtg->alpha_cfg = CH1_ALPHA_SEL; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci dtg->alpha = alpha; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_civoid dcss_dtg_css_set(struct dcss_dtg *dtg) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci dtg->control_status |= 31062306a36Sopenharmony_ci (0x5 << CSS_PIX_COMP_SWAP_POS) & CSS_PIX_COMP_SWAP_MASK; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_civoid dcss_dtg_enable(struct dcss_dtg *dtg) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci dtg->control_status |= DTG_START; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci dtg->control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK); 31862306a36Sopenharmony_ci dtg->control_status |= dtg->alpha_cfg; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci dcss_dtg_write(dtg, dtg->control_status, DCSS_DTG_TC_CONTROL_STATUS); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci dtg->in_use = true; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_civoid dcss_dtg_shutoff(struct dcss_dtg *dtg) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci dtg->control_status &= ~DTG_START; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci dcss_writel(dtg->control_status, 33062306a36Sopenharmony_ci dtg->base_reg + DCSS_DTG_TC_CONTROL_STATUS); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci dtg->in_use = false; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cibool dcss_dtg_is_enabled(struct dcss_dtg *dtg) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci return dtg->in_use; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_civoid dcss_dtg_ch_enable(struct dcss_dtg *dtg, int ch_num, bool en) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci u32 ch_en_map[] = {CH1_EN, CH2_EN, CH3_EN}; 34362306a36Sopenharmony_ci u32 control_status; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci control_status = dtg->control_status & ~ch_en_map[ch_num]; 34662306a36Sopenharmony_ci control_status |= en ? ch_en_map[ch_num] : 0; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK); 34962306a36Sopenharmony_ci control_status |= dtg->alpha_cfg; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (dtg->control_status != control_status) 35262306a36Sopenharmony_ci dcss_dtg_write(dtg, control_status, DCSS_DTG_TC_CONTROL_STATUS); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci dtg->control_status = control_status; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_civoid dcss_dtg_vblank_irq_enable(struct dcss_dtg *dtg, bool en) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci u32 status; 36062306a36Sopenharmony_ci u32 mask = en ? LINE1_IRQ : 0; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (en) { 36362306a36Sopenharmony_ci status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); 36462306a36Sopenharmony_ci dcss_writel(status & LINE1_IRQ, 36562306a36Sopenharmony_ci dtg->base_reg + DCSS_DTG_INT_CONTROL); 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci dcss_update(mask, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_civoid dcss_dtg_ctxld_kick_irq_enable(struct dcss_dtg *dtg, bool en) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci u32 status; 37462306a36Sopenharmony_ci u32 mask = en ? LINE0_IRQ : 0; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (en) { 37762306a36Sopenharmony_ci status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (!dtg->ctxld_kick_irq_en) { 38062306a36Sopenharmony_ci dcss_writel(status & LINE0_IRQ, 38162306a36Sopenharmony_ci dtg->base_reg + DCSS_DTG_INT_CONTROL); 38262306a36Sopenharmony_ci enable_irq(dtg->ctxld_kick_irq); 38362306a36Sopenharmony_ci dtg->ctxld_kick_irq_en = true; 38462306a36Sopenharmony_ci dcss_update(mask, LINE0_IRQ, 38562306a36Sopenharmony_ci dtg->base_reg + DCSS_DTG_INT_MASK); 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (!dtg->ctxld_kick_irq_en) 39262306a36Sopenharmony_ci return; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci disable_irq_nosync(dtg->ctxld_kick_irq); 39562306a36Sopenharmony_ci dtg->ctxld_kick_irq_en = false; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci dcss_update(mask, LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK); 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_civoid dcss_dtg_vblank_irq_clear(struct dcss_dtg *dtg) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci dcss_update(LINE1_IRQ, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cibool dcss_dtg_vblank_irq_valid(struct dcss_dtg *dtg) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci return !!(dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS) & LINE1_IRQ); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 410