/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include #include #include //For 120Hz rotation issue #include #ifdef CONFIG_MTK_LEDS #include #ifdef CONFIG_LEDS_MTK_DISP #ifdef CONFIG_MTK_AAL_SUPPORT #define CONFIG_LEDS_BRIGHTNESS_CHANGED #endif #include #elif defined CONFIG_LEDS_MTK_PWM #ifdef CONFIG_MTK_AAL_SUPPORT #define CONFIG_LEDS_BRIGHTNESS_CHANGED #endif #include #elif defined CONFIG_LEDS_MTK_I2C #ifdef CONFIG_MTK_AAL_SUPPORT #define CONFIG_LEDS_BRIGHTNESS_CHANGED #endif #include #endif #else #define mt_leds_brightness_set(x, y) do { } while (0) #define MT65XX_LED_MODE_NONE (0) #define MT65XX_LED_MODE_CUST_LCM (4) #endif #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_drm_lowpower.h" #include "mtk_log.h" #include "mtk_dump.h" #include "mtk_disp_aal.h" #include "mtk_disp_color.h" #undef pr_fmt #define pr_fmt(fmt) "[disp_aal]" fmt // It's a work around for no comp assigned in functions. static struct mtk_ddp_comp *default_comp; static struct mtk_ddp_comp *aal1_default_comp; //For 120Hz rotation issue struct timeval start, end; /* To enable debug log: */ /* # echo aal_dbg:1 > /sys/kernel/debug/dispsys */ int aal_dbg_en; static int g_max_backlight = 1023; static DECLARE_WAIT_QUEUE_HEAD(g_aal_hist_wq); static DEFINE_SPINLOCK(g_aal_clock_lock); static DEFINE_SPINLOCK(g_aal_hist_lock); static DEFINE_SPINLOCK(g_aal_irq_en_lock); static struct DISP_AAL_HIST g_aal_hist = { .serviceFlags = 0, .backlight = -1, .essStrengthIndex = ESS_LEVEL_BY_CUSTOM_LIB, .ess_enable = ESS_EN_BY_CUSTOM_LIB, .dre_enable = DRE_EN_BY_CUSTOM_LIB }; static struct DISP_AAL_HIST g_aal_hist_db; //static ddp_module_notify g_ddp_notify; static atomic_t g_aal0_hist_available = ATOMIC_INIT(0); static atomic_t g_aal1_hist_available = ATOMIC_INIT(0); static atomic_t g_aal_is_init_regs_valid = ATOMIC_INIT(0); static atomic_t g_aal_backlight_notified = ATOMIC_INIT(1023); static atomic_t g_aal_initialed = ATOMIC_INIT(0); static atomic_t g_aal_allowPartial = ATOMIC_INIT(0); static atomic_t g_aal_force_enable_irq = ATOMIC_INIT(0); static atomic_t g_led_mode = ATOMIC_INIT(MT65XX_LED_MODE_NONE); static atomic_t g_aal_force_relay = ATOMIC_INIT(0); static atomic_t g_aal_eof_irq = ATOMIC_INIT(0); static atomic_t g_aal1_eof_irq = ATOMIC_INIT(0); static atomic_t g_aal_first_frame = ATOMIC_INIT(1); static atomic_t g_aal1_first_frame = ATOMIC_INIT(1); static struct workqueue_struct *aal_flip_wq; static struct workqueue_struct *aal_refresh_wq; enum AAL_UPDATE_HIST { UPDATE_NONE = 0, UPDATE_SINGLE, UPDATE_MULTIPLE }; #if defined(CONFIG_MTK_DRE30_SUPPORT) /* #define DRE3_IN_DISP_AAL */ /* HW specified */ #define AAL_DRE_HIST_START (1152) #define AAL_DRE_HIST_END (4220) #define AAL_DRE_GAIN_START (4224) #define AAL_DRE_GAIN_END (6396) static DEFINE_SPINLOCK(g_aal_dre3_gain_lock); static atomic_t g_aal_force_hist_apb = ATOMIC_INIT(0); static atomic_t g_aal1_force_hist_apb = ATOMIC_INIT(0); static atomic_t g_aal_dre_halt = ATOMIC_INIT(0); static atomic_t g_aal_dre_hw_init = ATOMIC_INIT(0); static atomic_t g_aal1_dre_hw_init = ATOMIC_INIT(0); static struct DISP_DRE30_INIT g_aal_init_dre30; static struct DISP_DRE30_PARAM g_aal_gain; static struct DISP_DRE30_PARAM g_aal_gain_db; static struct DISP_DRE30_HIST g_aal_dre30_hist; static struct DISP_DRE30_HIST g_aal_dre30_hist_db; static atomic_t g_aal_change_to_dre30 = ATOMIC_INIT(0); static atomic_t g_aal_dre_config = ATOMIC_INIT(0); static atomic_t g_aal1_dre_config = ATOMIC_INIT(0); static atomic_t g_aal_first_frame_flip = ATOMIC_INIT(0); static atomic_t g_aal1_first_frame_flip = ATOMIC_INIT(0); #define AAL_SRAM_SOF 1 #define AAL_SRAM_EOF 0 static u32 aal_sram_method = AAL_SRAM_SOF; #endif /* CONFIG_MTK_DRE30_SUPPORT */ static DECLARE_WAIT_QUEUE_HEAD(g_aal_size_wq); static bool g_aal_get_size_available; static struct DISP_AAL_DISPLAY_SIZE g_aal_size; static struct DISP_AAL_DISPLAY_SIZE g_dual_aal_size; static atomic_t g_aal_panel_type = ATOMIC_INIT(CONFIG_BY_CUSTOM_LIB); static int g_aal_ess_level = ESS_LEVEL_BY_CUSTOM_LIB; static int g_aal_dre_en = DRE_EN_BY_CUSTOM_LIB; static int g_aal_ess_en = ESS_EN_BY_CUSTOM_LIB; static int g_aal_ess_level_cmd_id; static int g_aal_dre_en_cmd_id; static int g_aal_ess_en_cmd_id; #define aal_min(a, b) (((a) < (b)) ? (a) : (b)) static bool isDualPQ; enum AAL_IOCTL_CMD { INIT_REG = 0, SET_PARAM, EVENTCTL, FLIP_SRAM, BYPASS_AAL }; struct dre3_node { struct device *dev; void __iomem *va; phys_addr_t pa; struct clk *clk; }; struct mtk_disp_aal_data { bool support_shadow; int aal_dre_hist_start; int aal_dre_hist_end; int aal_dre_gain_start; int aal_dre_gain_end; int bitShift; }; struct mtk_disp_aal { struct mtk_ddp_comp ddp_comp; struct drm_crtc *crtc; struct dre3_node dre3_hw; atomic_t dirty_frame_retrieved; atomic_t is_clock_on; const struct mtk_disp_aal_data *data; struct work_struct aal_flip_task; struct work_struct aal_refresh_task; }; static struct mtk_disp_aal *g_aal_data; static struct mtk_disp_aal *g_aal1_data; static inline struct mtk_disp_aal *comp_to_aal(struct mtk_ddp_comp *comp) { return container_of(comp, struct mtk_disp_aal, ddp_comp); } #if defined(CONFIG_MTK_DRE30_SUPPORT) static inline phys_addr_t mtk_aal_dre3_pa(struct mtk_ddp_comp *comp) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); return (aal_data->dre3_hw.dev) ? aal_data->dre3_hw.pa : comp->regs_pa; } static inline void __iomem *mtk_aal_dre3_va(struct mtk_ddp_comp *comp) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); return (aal_data->dre3_hw.dev) ? aal_data->dre3_hw.va : comp->regs; } static void mtk_aal_write_mask(void __iomem *address, u32 data, u32 mask) { u32 value = data; if (mask != ~0) { value = readl(address); value &= ~mask; data &= mask; value |= data; } writel(value, address); } #endif #define AALERR(fmt, arg...) pr_notice("[ERR]%s:" fmt, __func__, ##arg) static bool debug_flow_log; #define AALFLOW_LOG(fmt, arg...) do { \ if (debug_flow_log) \ pr_notice("[FLOW]%s:" fmt, __func__, ##arg); \ } while (0) static bool debug_api_log; #define AALAPI_LOG(fmt, arg...) do { \ if (debug_api_log) \ pr_notice("[API]%s:" fmt, __func__, ##arg); \ } while (0) static bool debug_write_cmdq_log; #define AALWC_LOG(fmt, arg...) do { \ if (debug_write_cmdq_log) \ pr_notice("[WC]%s:" fmt, __func__, ##arg); \ } while (0) static bool debug_irq_log; #define AALIRQ_LOG(fmt, arg...) do { \ if (debug_irq_log) \ pr_notice("[IRQ]%s:" fmt, __func__, ##arg); \ } while (0) /* config register which might have extra DRE3 aal hw */ static inline s32 basic_cmdq_write(struct cmdq_pkt *handle, struct mtk_ddp_comp *comp, u32 offset, u32 value, u32 mask) { #if defined(CONFIG_MTK_DRE30_SUPPORT) s32 result; struct mtk_disp_aal *aal_data = comp_to_aal(comp); phys_addr_t dre3_pa = mtk_aal_dre3_pa(comp); result = cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + offset, value, mask); if (result) { AALERR("write reg fail, offset:%#x\n", offset); return result; } AALWC_LOG("write 0x%03x with 0x%08x (0x%08x)\n", offset, value, mask); if (aal_data->dre3_hw.dev) result = cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + offset, value, mask); return result; #else return cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + offset, value, mask); #endif } static int disp_aal_get_cust_led(void) { struct device_node *led_node = NULL; int ret = 0; int led_mode; int pwm_config[5] = { 0 }; led_node = of_find_compatible_node(NULL, NULL, "mediatek,lcd-backlight"); if (!led_node) { ret = -1; pr_notice("Cannot find LED node from dts\n"); } else { ret = of_property_read_u32(led_node, "led_mode", &led_mode); if (!ret) atomic_set(&g_led_mode, led_mode); else pr_notice("led dts can not get led mode data.\n"); ret = of_property_read_u32_array(led_node, "pwm_config", pwm_config, ARRAY_SIZE(pwm_config)); } if (ret) pr_notice("get pwm cust info fail\n"); pr_notice("%s mode=%u\n", __func__, atomic_read(&g_led_mode)); return ret; } #define LOG_INTERVAL_TH 200 #define LOG_BUFFER_SIZE 4 static char g_aal_log_buffer[256] = ""; static int g_aal_log_index; struct timeval g_aal_log_prevtime = {0}; bool disp_aal_is_support(void) { #ifdef CONFIG_MTK_AAL_SUPPORT return true; #else return false; #endif // CONFIG_MTK_AAL_SUPPORT } static void disp_aal_set_interrupt(struct mtk_ddp_comp *comp, int enable) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); if (!disp_aal_is_support()) { AALIRQ_LOG("aal is not support\n"); return; } if (enable && (atomic_read(&g_aal_force_relay) != 1 || m_new_pq_persist_property[DISP_PQ_CCORR_SILKY_BRIGHTNESS])) { /* Enable output frame end interrupt */ if (comp == NULL) { if (isDualPQ) { writel(0x2, default_comp->regs + DISP_AAL_INTEN); writel(0x2, aal1_default_comp->regs + DISP_AAL_INTEN); } else writel(0x2, default_comp->regs + DISP_AAL_INTEN); } else writel(0x2, comp->regs + DISP_AAL_INTEN); AALIRQ_LOG("interrupt enabled\n"); } else if (!enable) { if (atomic_read(&aal_data->dirty_frame_retrieved) == 1) { if (comp == NULL) { if (isDualPQ) { writel(0x0, default_comp->regs + DISP_AAL_INTEN); writel(0x0, aal1_default_comp->regs + DISP_AAL_INTEN); } else { writel(0x0, default_comp->regs + DISP_AAL_INTEN); } } else { writel(0x0, comp->regs + DISP_AAL_INTEN); } AALIRQ_LOG("interrupt disabled"); } //else { /* Dirty histogram was not retrieved. */ /* Only if the dirty hist was retrieved, */ /* interrupt can be disabled. */ /* Continue interrupt until AALService can get */ /* the latest histogram. */ //} } } static unsigned long timevaldiff(struct timeval *starttime, struct timeval *finishtime) { unsigned long msec; msec = (finishtime->tv_sec-starttime->tv_sec)*1000; msec += (finishtime->tv_usec-starttime->tv_usec)/1000; return msec; } static void disp_aal_notify_backlight_log(int bl_1024) { struct timeval aal_time; unsigned long diff_mesc = 0; unsigned long tsec; unsigned long tusec; do_gettimeofday(&aal_time); tsec = (unsigned long)aal_time.tv_sec % 100; tusec = (unsigned long)aal_time.tv_usec / 1000; diff_mesc = timevaldiff(&g_aal_log_prevtime, &aal_time); if (!debug_api_log) return; pr_notice("time diff = %lu\n", diff_mesc); if (diff_mesc > LOG_INTERVAL_TH) { if (g_aal_log_index == 0) { pr_notice("%s: %d/1023\n", __func__, bl_1024); } else { sprintf(g_aal_log_buffer + strlen(g_aal_log_buffer), "%s, %d/1023 %03lu.%03lu", __func__, bl_1024, tsec, tusec); pr_notice("%s\n", g_aal_log_buffer); g_aal_log_index = 0; } } else { if (g_aal_log_index == 0) { sprintf(g_aal_log_buffer, "%s %d/1023 %03lu.%03lu", __func__, bl_1024, tsec, tusec); g_aal_log_index += 1; } else { sprintf(g_aal_log_buffer + strlen(g_aal_log_buffer), "%s, %d/1023 %03lu.%03lu", __func__, bl_1024, tsec, tusec); g_aal_log_index += 1; } if ((g_aal_log_index >= LOG_BUFFER_SIZE) || (bl_1024 == 0)) { pr_notice("%s\n", g_aal_log_buffer); g_aal_log_index = 0; } } memcpy(&g_aal_log_prevtime, &aal_time, sizeof(struct timeval)); } void disp_aal_refresh_by_kernel(void) { unsigned long flags, clockflags; if (atomic_read(&g_aal_is_init_regs_valid) == 1) { spin_lock_irqsave(&g_aal_irq_en_lock, flags); atomic_set(&g_aal_force_enable_irq, 1); if (spin_trylock_irqsave(&g_aal_clock_lock, clockflags)) { if (atomic_read(&g_aal_data->is_clock_on) != 1) AALFLOW_LOG("aal clock is off\n"); else if (isDualPQ && atomic_read(&g_aal1_data->is_clock_on) != 1) AALFLOW_LOG("aal1 clock is off\n"); else disp_aal_set_interrupt(NULL, true); spin_unlock_irqrestore(&g_aal_clock_lock, clockflags); } spin_unlock_irqrestore(&g_aal_irq_en_lock, flags); /* Backlight or Kernel API latency should be smallest */ mtk_crtc_check_trigger(default_comp->mtk_crtc, false, true); } } void disp_aal_notify_backlight_changed(int trans_backlight) { unsigned long flags; unsigned int service_flags; AALAPI_LOG("%d/%d\n", trans_backlight, g_max_backlight); disp_aal_notify_backlight_log(trans_backlight); //disp_aal_exit_idle(__func__, 1); if (trans_backlight > g_max_backlight) trans_backlight = g_max_backlight; atomic_set(&g_aal_backlight_notified, trans_backlight); service_flags = 0; if (trans_backlight == 0) { mt_leds_brightness_set("lcd-backlight", 0); /* set backlight = 0 may be not from AAL, */ /* we have to let AALService can turn on backlight */ /* on phone resumption */ service_flags = AAL_SERVICE_FORCE_UPDATE; } else if (atomic_read(&g_aal_is_init_regs_valid) == 0 || (atomic_read(&g_aal_force_relay) == 1 && !m_new_pq_persist_property[DISP_PQ_CCORR_SILKY_BRIGHTNESS])) { /* AAL Service is not running */ mt_leds_brightness_set("lcd-backlight", trans_backlight); } spin_lock_irqsave(&g_aal_hist_lock, flags); g_aal_hist.backlight = trans_backlight; g_aal_hist.serviceFlags |= service_flags; spin_unlock_irqrestore(&g_aal_hist_lock, flags); // always notify aal service for LED changed mtk_drm_idlemgr_kick(__func__, &default_comp->mtk_crtc->base, 1); disp_aal_refresh_by_kernel(); } #ifdef CONFIG_LEDS_BRIGHTNESS_CHANGED int led_brightness_changed_event(struct notifier_block *nb, unsigned long event, void *v) { int trans_level; struct led_conf_info *led_conf; led_conf = (struct led_conf_info *)v; g_max_backlight = (1 << led_conf->trans_bits) - 1; switch (event) { case 1: trans_level = ( (((1 << led_conf->trans_bits) - 1) * led_conf->cdev.brightness + ((led_conf->cdev.max_brightness) / 2)) / (led_conf->cdev.max_brightness)); if (led_conf->cdev.brightness != 0 && trans_level == 0) trans_level = 1; disp_aal_notify_backlight_changed(trans_level); AALAPI_LOG("brightness changed: %d(%d)\n", trans_level, led_conf->cdev.brightness); break; case 2: disp_aal_notify_backlight_changed(0); break; case 3: trans_level = ( (((1 << led_conf->trans_bits) - 1) * led_conf->max_level + ((led_conf->cdev.max_brightness) / 2)) / (led_conf->cdev.max_brightness)); AALAPI_LOG("set Maxbrightness %d(%d)\n", trans_level, led_conf->max_level); break; default: break; } return NOTIFY_DONE; } static struct notifier_block leds_init_notifier = { .notifier_call = led_brightness_changed_event, }; #endif int mtk_drm_ioctl_aal_eventctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct mtk_drm_private *private = dev->dev_private; struct mtk_ddp_comp *comp = private->ddp_comp[DDP_COMPONENT_AAL0]; struct mtk_disp_aal *aal_data = comp_to_aal(comp); #ifdef CONFIG_MTK_DRE30_SUPPORT struct drm_crtc *crtc = private->crtc[0]; #endif int ret = 0; unsigned long flags, clockflags; int *enabled = (int *)data; AALFLOW_LOG("%d\n", *enabled); spin_lock_irqsave(&g_aal_irq_en_lock, flags); if (atomic_read(&g_aal_force_enable_irq) == 1) { if (*enabled == 0) AALFLOW_LOG("force enable aal ieq 0 -> 1\n"); *enabled = 1; } if (spin_trylock_irqsave(&g_aal_clock_lock, clockflags)) { if (atomic_read(&aal_data->is_clock_on) != 1) { AALFLOW_LOG("clock is off\n"); ret = -EFAULT; } else disp_aal_set_interrupt(comp, *enabled); spin_unlock_irqrestore(&g_aal_clock_lock, clockflags); } spin_unlock_irqrestore(&g_aal_irq_en_lock, flags); if (*enabled) { #ifdef CONFIG_MTK_DRE30_SUPPORT mtk_crtc_user_cmd(crtc, comp, EVENTCTL, data); mtk_crtc_check_trigger(comp->mtk_crtc, true, true); #else mtk_crtc_check_trigger(comp->mtk_crtc, true, true); #endif } return ret; } static void mtk_crtc_user_cmd_work(struct work_struct *work_item) { mtk_crtc_user_cmd(g_aal_data->crtc, default_comp, FLIP_SRAM, NULL); mtk_crtc_check_trigger(default_comp->mtk_crtc, true, true); AALFLOW_LOG("end"); } static void mtk_disp_aal_refresh_trigger(struct work_struct *work_item) { AALFLOW_LOG("start"); mtk_crtc_check_trigger(default_comp->mtk_crtc, true, true); AALFLOW_LOG("end"); } void disp_aal_flip_sram(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const char *caller) { #ifdef CONFIG_MTK_DRE30_SUPPORT u32 hist_apb = 0, hist_int = 0, sram_cfg = 0; phys_addr_t dre3_pa = mtk_aal_dre3_pa(comp); if (aal_sram_method != AAL_SRAM_SOF) return; if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) { if (atomic_read(&g_aal_dre_config) == 1) { AALFLOW_LOG("[SRAM] %s g_aal_dre_config not 0 in %s", mtk_dump_comp_str_id(comp->id), caller); return; } atomic_set(&g_aal_dre_config, 1); if (atomic_cmpxchg(&g_aal_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } } else if (comp->id == DDP_COMPONENT_AAL1) { if (atomic_read(&g_aal1_dre_config) == 1) { AALFLOW_LOG("[SRAM] %s g_aal1_dre_config not 0 in %s", mtk_dump_comp_str_id(comp->id), caller); return; } atomic_set(&g_aal1_dre_config, 1); if (atomic_cmpxchg(&g_aal1_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal1_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } } } else { if (atomic_read(&g_aal_dre_config) == 1) { AALFLOW_LOG("[SRAM] g_aal_dre_config not 0 in %s", caller); return; } atomic_set(&g_aal_dre_config, 1); if (atomic_cmpxchg(&g_aal_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } } sram_cfg = (hist_int << 6)|(hist_apb << 5)|(1 << 4); AALFLOW_LOG("[SRAM] hist_apb(%d) hist_int(%d) 0x%08x comp_id[%d] in %s", hist_apb, hist_int, sram_cfg, comp->id, caller); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_SRAM_CFG, sram_cfg, (0x7 << 4)); AALFLOW_LOG("end comp_id[%d]", comp->id); #endif } void disp_aal_first_flip_sram(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const char *caller) { #ifdef CONFIG_MTK_DRE30_SUPPORT u32 hist_apb = 0, hist_int = 0, sram_cfg = 0; phys_addr_t dre3_pa = mtk_aal_dre3_pa(comp); if (aal_sram_method != AAL_SRAM_SOF) return; if ((comp->mtk_crtc->is_dual_pipe)) { if (comp->id == DDP_COMPONENT_AAL0) { if (atomic_cmpxchg(&g_aal_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } atomic_set(&g_aal_first_frame_flip, 1); } else if (comp->id == DDP_COMPONENT_AAL1) { if (atomic_cmpxchg(&g_aal1_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal1_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } atomic_set(&g_aal1_first_frame_flip, 1); } } else { if (atomic_cmpxchg(&g_aal_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("[SRAM] Error when get hist_apb in %s", caller); } } sram_cfg = (hist_int << 6)|(hist_apb << 5)|(1 << 4); AALFLOW_LOG("[SRAM] hist_apb(%d) hist_int(%d) 0x%08x in %s", hist_apb, hist_int, sram_cfg, caller); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_SRAM_CFG, sram_cfg, (0x7 << 4)); AALFLOW_LOG("end comp_id[%d]", comp->id); #endif } static void mtk_aal_init(struct mtk_ddp_comp *comp, struct mtk_ddp_config *cfg, struct cmdq_pkt *handle) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); AALFLOW_LOG("+ comd id :%d\n", comp->id); if (disp_aal_is_support() == true && atomic_read(&g_aal_force_relay) != 1) { AALFLOW_LOG("Enable AAL histogram\n"); // Enable AAL histogram, engine cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CFG, 0x3 << 1, (0x3 << 1)); } else { AALFLOW_LOG("Disable AAL histogram\n"); // Disable AAL histogram, engine cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CFG, 0x0 << 1, (0x3 << 1)); } /* get lcd-backlight mode from dts */ if (atomic_read(&g_led_mode) == MT65XX_LED_MODE_NONE) disp_aal_get_cust_led(); if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) { atomic_set(&g_aal0_hist_available, 0); atomic_set(&g_aal_eof_irq, 0); } else if (comp->id == DDP_COMPONENT_AAL1) { atomic_set(&g_aal1_hist_available, 0); atomic_set(&g_aal1_eof_irq, 0); } } else { atomic_set(&g_aal_eof_irq, 0); atomic_set(&g_aal0_hist_available, 0); } atomic_set(&aal_data->dirty_frame_retrieved, 1); AALFLOW_LOG("led mode: %d-\n", atomic_read(&g_led_mode)); } static bool debug_bypass_alg_mode; static void mtk_aal_config(struct mtk_ddp_comp *comp, struct mtk_ddp_config *cfg, struct cmdq_pkt *handle) { unsigned int val = 0; int width = cfg->w, height = cfg->h; if (comp->mtk_crtc->is_dual_pipe) { isDualPQ = true; width = cfg->w / 2; } else { isDualPQ = false; width = cfg->w; } AALFLOW_LOG("(w,h)=(%d,%d)+, %d\n", width, height, g_aal_get_size_available); if (g_aal_get_size_available == false) { g_aal_size.height = height; g_aal_size.width = width; g_aal_size.isdualpipe = isDualPQ; g_dual_aal_size.height = height; g_dual_aal_size.width = cfg->w; g_dual_aal_size.isdualpipe = isDualPQ; g_aal_get_size_available = true; wake_up_interruptible(&g_aal_size_wq); AALFLOW_LOG("size available: (w,h)=(%d,%d)+\n", width, height); } val = (width << 16) | (height); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_SIZE, val, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_OUTPUT_SIZE, val, ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_OUTPUT_OFFSET, (0 << 16) | 0, ~0); if (atomic_read(&g_aal_force_relay) == 1) { // Set reply mode AALFLOW_LOG("g_aal_force_relay\n"); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CFG, 1, 1); } else { // Disable reply mode cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CFG, 0, 1); } mtk_aal_init(comp, cfg, handle); disp_aal_flip_sram(comp, handle, __func__); AALWC_LOG("AAL_CFG=0x%x compid:%d\n", readl(comp->regs + DISP_AAL_CFG), comp->id); } static void disp_aal_wait_hist(void) { int ret = 0; if (isDualPQ) { if ((atomic_read(&g_aal0_hist_available) == 0) || (atomic_read(&g_aal1_hist_available) == 0)) ret = wait_event_interruptible(g_aal_hist_wq, (atomic_read(&g_aal0_hist_available) == 1) && (atomic_read(&g_aal1_hist_available) == 1)); AALFLOW_LOG("aal0 and aal1 hist_available = 1, waken up, ret = %d", ret); } else if (atomic_read(&g_aal0_hist_available) == 0) { AALFLOW_LOG("wait_event_interruptible\n"); ret = wait_event_interruptible(g_aal_hist_wq, atomic_read(&g_aal0_hist_available) == 1); AALFLOW_LOG("hist_available = 1, waken up, ret = %d", ret); } else AALFLOW_LOG("hist_available = 0"); } static bool disp_aal_read_single_hist(struct mtk_ddp_comp *comp) { bool read_success = true; int i; if (((comp->id == DDP_COMPONENT_AAL0) && (atomic_read(&g_aal_eof_irq) == 0)) || ((comp->id == DDP_COMPONENT_AAL1) && (atomic_read(&g_aal1_eof_irq) == 0))) return false; if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) { for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal0_maxHist[i] = readl(comp->regs + DISP_AAL_STATUS_00 + (i << 2)); } for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal0_yHist[i] = readl(comp->regs + DISP_Y_HISTOGRAM_00 + (i << 2)); } read_success = disp_color_reg_get(comp, DISP_COLOR_TWO_D_W1_RESULT, &g_aal_hist.aal0_colorHist); } else if (comp->id == DDP_COMPONENT_AAL1) { for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal1_maxHist[i] = readl(comp->regs + DISP_AAL_STATUS_00 + (i << 2)); } for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal1_yHist[i] = readl(comp->regs + DISP_Y_HISTOGRAM_00 + (i << 2)); } read_success = disp_color_reg_get(comp, DISP_COLOR_TWO_D_W1_RESULT, &g_aal_hist.aal1_colorHist); } } else { for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal0_maxHist[i] = readl(comp->regs + DISP_AAL_STATUS_00 + (i << 2)); } for (i = 0; i < AAL_HIST_BIN; i++) { g_aal_hist.aal0_yHist[i] = readl(comp->regs + DISP_Y_HISTOGRAM_00 + (i << 2)); } read_success = disp_color_reg_get(comp, DISP_COLOR_TWO_D_W1_RESULT, &g_aal_hist.aal0_colorHist); } if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal_eof_irq, 0); if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_eof_irq, 0); return read_success; } static int disp_aal_copy_hist_to_user(struct DISP_AAL_HIST *hist) { unsigned long flags; int ret = 0; if (hist == NULL) { AALERR("%s DstHist is NULL\n", __func__); return -1; } /* We assume only one thread will call this function */ spin_lock_irqsave(&g_aal_hist_lock, flags); #if defined(CONFIG_MTK_DRE30_SUPPORT) memcpy(&g_aal_dre30_hist_db, &g_aal_dre30_hist, sizeof(g_aal_dre30_hist)); #endif g_aal_hist.panel_type = atomic_read(&g_aal_panel_type); g_aal_hist.essStrengthIndex = g_aal_ess_level; g_aal_hist.ess_enable = g_aal_ess_en; g_aal_hist.dre_enable = g_aal_dre_en; g_aal_hist.serviceFlags = 0; atomic_set(&g_aal0_hist_available, 0); atomic_set(&g_aal1_hist_available, 0); memcpy(&g_aal_hist_db, &g_aal_hist, sizeof(g_aal_hist)); spin_unlock_irqrestore(&g_aal_hist_lock, flags); #if defined(CONFIG_MTK_DRE30_SUPPORT) g_aal_hist_db.dre30_hist = g_aal_init_dre30.dre30_hist_addr; #endif memcpy(hist, &g_aal_hist_db, sizeof(g_aal_hist_db)); #if defined(CONFIG_MTK_DRE30_SUPPORT) ret = copy_to_user(AAL_U32_PTR(g_aal_init_dre30.dre30_hist_addr), &g_aal_dre30_hist_db, sizeof(g_aal_dre30_hist_db)); #endif AALFLOW_LOG("%s set g_aal_force_enable_irq to 0 +\n", __func__); atomic_set(&g_aal_force_enable_irq, 0); return ret; } void dump_hist(struct DISP_AAL_HIST *data) { int i = 0; pr_notice("aal0_maxHist:\n"); for (i = 0; i < 3; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", data->aal0_maxHist[i*10 + 0], data->aal0_maxHist[i*10 + 1], data->aal0_maxHist[i*10 + 2], data->aal0_maxHist[i*10 + 3], data->aal0_maxHist[i*10 + 4], data->aal0_maxHist[i*10 + 5], data->aal0_maxHist[i*10 + 6], data->aal0_maxHist[i*10 + 7], data->aal0_maxHist[i*10 + 9], data->aal0_maxHist[i*10 + 9]); } pr_notice("%d %d %d", data->aal0_maxHist[30], data->aal0_maxHist[31], data->aal0_maxHist[32]); pr_notice("aal0_yHist:\n"); for (i = 0; i < 3; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", data->aal0_yHist[i*10 + 0], data->aal0_yHist[i*10 + 1], data->aal0_yHist[i*10 + 2], data->aal0_yHist[i*10 + 3], data->aal0_yHist[i*10 + 4], data->aal0_yHist[i*10 + 5], data->aal0_yHist[i*10 + 6], data->aal0_yHist[i*10 + 7], data->aal0_yHist[i*10 + 9], data->aal0_yHist[i*10 + 9]); } pr_notice("%d %d %d", data->aal0_yHist[30], data->aal0_yHist[31], data->aal0_yHist[32]); if (isDualPQ) { pr_err("aal1_maxHist:\n"); for (i = 0; i < 3; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", data->aal1_maxHist[i*10 + 0], data->aal1_maxHist[i*10 + 1], data->aal1_maxHist[i*10 + 2], data->aal1_maxHist[i*10 + 3], data->aal1_maxHist[i*10 + 4], data->aal1_maxHist[i*10 + 5], data->aal1_maxHist[i*10 + 6], data->aal1_maxHist[i*10 + 7], data->aal1_maxHist[i*10 + 9], data->aal1_maxHist[i*10 + 9]); } pr_notice("%d %d %d", data->aal1_maxHist[30], data->aal1_maxHist[31], data->aal1_maxHist[32]); pr_notice("aal1_yHist:\n"); for (i = 0; i < 3; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", data->aal1_yHist[i*10 + 0], data->aal1_yHist[i*10 + 1], data->aal1_yHist[i*10 + 2], data->aal1_yHist[i*10 + 3], data->aal1_yHist[i*10 + 4], data->aal1_yHist[i*10 + 5], data->aal1_yHist[i*10 + 6], data->aal1_yHist[i*10 + 7], data->aal1_yHist[i*10 + 9], data->aal1_yHist[i*10 + 9]); } pr_notice("%d %d %d", data->aal1_yHist[30], data->aal1_yHist[31], data->aal1_yHist[32]); } pr_notice("serviceFlags:%u, backlight: %d, colorHist: %d\n", data->serviceFlags, data->backlight, data->aal0_colorHist); pr_notice("requestPartial:%d, panel_type: %u\n", data->requestPartial, data->panel_type); pr_notice("essStrengthIndex:%d, ess_enable: %d, dre_enable: %d\n", data->essStrengthIndex, data->ess_enable, data->dre_enable); } static bool debug_dump_aal_hist; int mtk_drm_ioctl_aal_get_hist(struct drm_device *dev, void *data, struct drm_file *file_priv) { disp_aal_wait_hist(); if (disp_aal_copy_hist_to_user((struct DISP_AAL_HIST *) data) < 0) return -EFAULT; if (debug_dump_aal_hist) dump_hist(data); return 0; } #if defined(CONFIG_MTK_DRE30_SUPPORT) static void disp_aal_dre3_config(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const struct DISP_AAL_INITREG *init_regs) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); phys_addr_t dre3_pa = mtk_aal_dre3_pa(comp); int dre_alg_mode = 1; AALFLOW_LOG("start, bitShift: %d compId%d\n", aal_data->data->bitShift, comp->id); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_00, (g_aal_size.width - 1) << (aal_data->data->bitShift), ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_01, (init_regs->dre_blk_y_num << 5) | init_regs->dre_blk_x_num, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_02, (init_regs->dre_blk_height << (aal_data->data->bitShift)) | init_regs->dre_blk_width, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_04, (init_regs->dre_flat_length_slope << 13) | init_regs->dre_flat_length_th, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_CHROMA_HIST_00, (init_regs->dre_s_upper << 24) | (init_regs->dre_s_lower << 16) | (init_regs->dre_y_upper << 8) | init_regs->dre_y_lower, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_CHROMA_HIST_01, (init_regs->dre_h_slope << 24) | (init_regs->dre_s_slope << 20) | (init_regs->dre_y_slope << 16) | (init_regs->dre_h_upper << 8) | init_regs->dre_h_lower, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_ALPHA_BLEND_00, (init_regs->dre_y_alpha_shift_bit << 25) | (init_regs->dre_y_alpha_base << 16) | (init_regs->dre_x_alpha_shift_bit << 9) | init_regs->dre_x_alpha_base, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_05, init_regs->dre_blk_area, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_06, init_regs->dre_blk_area_min, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DRE_BLOCK_INFO_07, (g_aal_size.height - 1) << (aal_data->data->bitShift), ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_SRAM_CFG, init_regs->hist_bin_type, 0x1); #if defined(DRE3_IN_DISP_AAL) cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DUAL_PIPE_INFO_00, (0 << 13) | 0, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_DUAL_PIPE_INFO_01, ((init_regs->dre_blk_x_num-1) << 13) | (init_regs->dre_blk_width-1), ~0); #else if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) { cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + MDP_AAL_TILE_00, (0x1 << 21) | (0x1 << 20) | (init_regs->dre0_blk_num_x_end << 15) | (init_regs->dre0_blk_num_x_start << 10) | (init_regs->blk_num_y_end << 5) | init_regs->blk_num_y_start, ~0); } else if (comp->id == DDP_COMPONENT_AAL1) { cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + MDP_AAL_TILE_00, (0x1 << 21) | (0x1 << 20) | (init_regs->dre1_blk_num_x_end << 15) | (init_regs->dre1_blk_num_x_start << 10) | (init_regs->blk_num_y_end << 5) | init_regs->blk_num_y_start, ~0); } } else { cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + MDP_AAL_TILE_00, (0x1 << 21) | (0x1 << 20) | (init_regs->blk_num_x_end << 15) | (init_regs->blk_num_x_start << 10) | (init_regs->blk_num_y_end << 5) | init_regs->blk_num_y_start, ~0); } cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + MDP_AAL_TILE_01, (init_regs->blk_cnt_x_end << (aal_data->data->bitShift)) | init_regs->blk_cnt_x_start, ~0); cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + MDP_AAL_TILE_02, (init_regs->blk_cnt_y_end << (aal_data->data->bitShift)) | init_regs->blk_cnt_y_start, ~0); #endif /* Change to Local DRE version */ if (debug_bypass_alg_mode) dre_alg_mode = 0; cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_CFG_MAIN, dre_alg_mode << 4, 1 << 4); if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) atomic_or(0x1, &g_aal_change_to_dre30); } else atomic_or(0x1, &g_aal_change_to_dre30); } #endif /* CONFIG_MTK_DRE30_SUPPORT */ #define CABC_GAINLMT(v0, v1, v2) (((v2) << 20) | ((v1) << 10) | (v0)) static struct DISP_AAL_INITREG g_aal_init_regs; static int disp_aal_write_init_regs(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle) { int ret = -EFAULT; if (atomic_read(&g_aal_is_init_regs_valid) == 1) { struct DISP_AAL_INITREG *init_regs = &g_aal_init_regs; int i, j = 0; int *gain; gain = init_regs->cabc_gainlmt; basic_cmdq_write(handle, comp, DISP_AAL_DRE_MAPPING_00, (init_regs->dre_map_bypass << 4), 1 << 4); for (i = 0; i <= 10; i++) { cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CABC_GAINLMT_TBL(i), CABC_GAINLMT(gain[j], gain[j + 1], gain[j + 2]), ~0); j += 3; } #if defined(CONFIG_MTK_DRE30_SUPPORT) disp_aal_dre3_config(comp, handle, init_regs); #endif AALFLOW_LOG("init done\n"); ret = 0; } return ret; } #define PRINT_INIT_REG(x1) pr_notice("[INIT]%s=0x%x\n", #x1, data->x1) void dump_init_reg(struct DISP_AAL_INITREG *data) { PRINT_INIT_REG(dre_s_lower); PRINT_INIT_REG(dre_s_upper); PRINT_INIT_REG(dre_y_lower); PRINT_INIT_REG(dre_y_upper); PRINT_INIT_REG(dre_h_lower); PRINT_INIT_REG(dre_h_upper); PRINT_INIT_REG(dre_h_slope); PRINT_INIT_REG(dre_s_slope); PRINT_INIT_REG(dre_y_slope); PRINT_INIT_REG(dre_x_alpha_base); PRINT_INIT_REG(dre_x_alpha_shift_bit); PRINT_INIT_REG(dre_y_alpha_base); PRINT_INIT_REG(dre_y_alpha_shift_bit); PRINT_INIT_REG(dre_blk_x_num); PRINT_INIT_REG(dre_blk_y_num); PRINT_INIT_REG(dre_blk_height); PRINT_INIT_REG(dre_blk_width); PRINT_INIT_REG(dre_blk_area); PRINT_INIT_REG(dre_blk_area_min); PRINT_INIT_REG(hist_bin_type); PRINT_INIT_REG(dre_flat_length_slope); PRINT_INIT_REG(dre_flat_length_th); PRINT_INIT_REG(blk_num_x_start); PRINT_INIT_REG(blk_num_x_end); PRINT_INIT_REG(dre0_blk_num_x_start); PRINT_INIT_REG(dre0_blk_num_x_end); PRINT_INIT_REG(dre1_blk_num_x_start); PRINT_INIT_REG(dre1_blk_num_x_end); PRINT_INIT_REG(blk_cnt_x_start); PRINT_INIT_REG(blk_cnt_x_end); PRINT_INIT_REG(blk_num_y_start); PRINT_INIT_REG(blk_num_y_end); PRINT_INIT_REG(blk_cnt_y_start); PRINT_INIT_REG(blk_cnt_y_end); } static bool debug_dump_init_reg = true; static int disp_aal_set_init_reg(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, struct DISP_AAL_INITREG *user_regs) { int ret = -EFAULT; struct DISP_AAL_INITREG *init_regs; if (!disp_aal_is_support()) return ret; init_regs = &g_aal_init_regs; memcpy(init_regs, user_regs, sizeof(*init_regs)); if (debug_dump_init_reg) dump_init_reg(init_regs); atomic_set(&g_aal_is_init_regs_valid, 1); AALFLOW_LOG("Set init reg: %lu\n", sizeof(*init_regs)); AALFLOW_LOG("init_reg.dre_map_bypass:%d\n", init_regs->dre_map_bypass); ret = disp_aal_write_init_regs(comp, handle); if (comp->mtk_crtc->is_dual_pipe) { struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc; struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_ddp_comp *comp_aal1 = priv->ddp_comp[DDP_COMPONENT_AAL1]; ret = disp_aal_write_init_regs(comp_aal1, handle); } AALFLOW_LOG("ret = %d\n", ret); return ret; } int mtk_drm_ioctl_aal_init_reg(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct mtk_drm_private *private = dev->dev_private; struct mtk_ddp_comp *comp = private->ddp_comp[DDP_COMPONENT_AAL0]; struct drm_crtc *crtc = private->crtc[0]; g_aal_data->crtc = crtc; return mtk_crtc_user_cmd(crtc, comp, INIT_REG, data); } static struct DISP_AAL_PARAM g_aal_param; #define DRE_REG_2(v0, off0, v1, off1) (((v1) << (off1)) | \ ((v0) << (off0))) #define DRE_REG_3(v0, off0, v1, off1, v2, off2) \ (((v2) << (off2)) | (v1 << (off1)) | ((v0) << (off0))) #if defined(CONFIG_MTK_DRE30_SUPPORT) static int disp_aal_write_dre3_to_reg(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const struct DISP_AAL_PARAM *param) { unsigned long flags; AALFLOW_LOG("\n"); if (atomic_read(&g_aal_change_to_dre30) == 0x3) { if (copy_from_user(&g_aal_gain_db, AAL_U32_PTR(param->dre30_gain), sizeof(g_aal_gain_db)) == 0) { spin_lock_irqsave(&g_aal_dre3_gain_lock, flags); memcpy(&g_aal_gain, &g_aal_gain_db, sizeof(g_aal_gain)); spin_unlock_irqrestore(&g_aal_dre3_gain_lock, flags); } } return 0; } #endif static int disp_aal_write_dre_to_reg(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const struct DISP_AAL_PARAM *param) { const int *gain; gain = param->DREGainFltStatus; #if defined(CONFIG_MACH_MT6885) || defined(CONFIG_MACH_MT6873) \ || defined(CONFIG_MACH_MT6893) || defined(CONFIG_MACH_MT6853) \ || defined(CONFIG_MACH_MT6833) || defined(CONFIG_MACH_MT6877) \ || defined(CONFIG_MACH_MT6781) cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(0), DRE_REG_2(gain[0], 0, gain[1], 14), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(1), DRE_REG_2(gain[2], 0, gain[3], 13), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(2), DRE_REG_2(gain[4], 0, gain[5], 12), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(3), DRE_REG_2(gain[6], 0, gain[7], 11), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(4), DRE_REG_2(gain[8], 0, gain[9], 11), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(5), DRE_REG_2(gain[10], 0, gain[11], 11), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(6), DRE_REG_3(gain[12], 0, gain[13], 11, gain[14], 22), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(7), DRE_REG_3(gain[15], 0, gain[16], 10, gain[17], 20), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(8), DRE_REG_3(gain[18], 0, gain[19], 10, gain[20], 20), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(9), DRE_REG_3(gain[21], 0, gain[22], 9, gain[23], 18), ~0); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(10), DRE_REG_3(gain[24], 0, gain[25], 9, gain[26], 18), ~0); /* Write dre curve to different register */ cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_DRE_FLT_FORCE(11), DRE_REG_2(gain[27], 0, gain[28], 9), ~0); return 0; } #endif /* CONFIG_MTK_DRE30_SUPPORT */ #if defined(CONFIG_MTK_DRE30_SUPPORT) || !defined(NOT_SUPPORT_CABC_HW) static int disp_aal_write_cabc_to_reg(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const struct DISP_AAL_PARAM *param) { int i; const int *gain; AALFLOW_LOG("\n"); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CABC_00, 1 << 31, 1 << 31); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CABC_02, param->cabc_fltgain_force, 0x3ff); gain = param->cabc_gainlmt; for (i = 0; i <= 10; i++) { cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CABC_GAINLMT_TBL(i), CABC_GAINLMT(gain[0], gain[1], gain[2]), ~0); gain += 3; } return 0; } #endif /* not define NOT_SUPPORT_CABC_HW */ static int disp_aal_write_param_to_reg(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, const struct DISP_AAL_PARAM *param) { // From mt6885, on DRE3.5+ESS mode, ESS function was // controlled by DREGainFltStatus, not cabc_gainlmt, so need to // set DREGainFltStatus to hw whether DRE3.5 or 2.5 disp_aal_write_dre_to_reg(comp, handle, param); #if defined(CONFIG_MTK_DRE30_SUPPORT) disp_aal_write_dre3_to_reg(comp, handle, param); disp_aal_write_cabc_to_reg(comp, handle, param); #else #ifndef NOT_SUPPORT_CABC_HW disp_aal_write_cabc_to_reg(comp, handle, param); #endif #endif return 0; } void dump_param(const struct DISP_AAL_PARAM *param) { int i = 0; pr_notice("DREGainFltStatus: "); for (i = 0; i < 2; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", param->DREGainFltStatus[i*10 + 0], param->DREGainFltStatus[i*10 + 1], param->DREGainFltStatus[i*10 + 2], param->DREGainFltStatus[i*10 + 3], param->DREGainFltStatus[i*10 + 4], param->DREGainFltStatus[i*10 + 5], param->DREGainFltStatus[i*10 + 6], param->DREGainFltStatus[i*10 + 7], param->DREGainFltStatus[i*10 + 8], param->DREGainFltStatus[i*10 + 9]); } pr_notice("%d %d %d %d %d %d %d %d %d", param->DREGainFltStatus[20], param->DREGainFltStatus[21], param->DREGainFltStatus[22], param->DREGainFltStatus[23], param->DREGainFltStatus[24], param->DREGainFltStatus[25], param->DREGainFltStatus[26], param->DREGainFltStatus[27], param->DREGainFltStatus[28]); pr_notice("cabc_gainlmt: "); for (i = 0; i < 3; i++) { pr_notice("%d %d %d %d %d %d %d %d %d %d", param->cabc_gainlmt[i*10 + 0], param->cabc_gainlmt[i*10 + 1], param->cabc_gainlmt[i*10 + 2], param->cabc_gainlmt[i*10 + 3], param->cabc_gainlmt[i*10 + 4], param->cabc_gainlmt[i*10 + 5], param->cabc_gainlmt[i*10 + 6], param->cabc_gainlmt[i*10 + 7], param->cabc_gainlmt[i*10 + 8], param->cabc_gainlmt[i*10 + 9]); } pr_notice("%d %d %d", param->cabc_gainlmt[30], param->cabc_gainlmt[31], param->cabc_gainlmt[32]); pr_notice("cabc_fltgain_force: %d, FinalBacklight: %d", param->cabc_fltgain_force, param->FinalBacklight); pr_notice("allowPartial: %d, refreshLatency: %d", param->allowPartial, param->refreshLatency); } static bool debug_dump_input_param; int disp_aal_set_param(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, struct DISP_AAL_PARAM *param) { int ret = -EFAULT; u64 time_use = 0; if (debug_dump_input_param) dump_param(&g_aal_param); //For 120Hz rotation issue do_gettimeofday(&end); time_use = (end.tv_sec-start.tv_sec) * 1000000 + (end.tv_usec-start.tv_usec); //pr_notice("set_param time_use is %lu us\n",time_use); // tbd. to be fixd if (time_use < 260) { // Workaround for 120hz rotation,do not let //aal command too fast,else it will merged with //DISP commmand and caused trigger loop clear EOF //before config loop.The DSI EOF has 100 us later then //RDMA EOF,and the worst DISP config time is 153us, //so if intervel less than 260 should delay usleep_range(260-time_use, 270-time_use); } ret = disp_aal_write_param_to_reg(comp, handle, &g_aal_param); disp_aal_flip_sram(comp, handle, __func__); if (comp->mtk_crtc->is_dual_pipe) { struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc; struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_ddp_comp *comp_aal1 = priv->ddp_comp[DDP_COMPONENT_AAL1]; ret = disp_aal_write_param_to_reg(comp_aal1, handle, &g_aal_param); disp_aal_flip_sram(comp_aal1, handle, __func__); } /* FIXME * if (ret == 0) * ret |= disp_pwm_set_backlight_cmdq(DISP_PWM0, * backlight_value, cmdq); */ // FIXME return ret; } #define PRINT_AAL_REG(x1, x2, x3, x4) \ pr_notice("[2]0x%x=0x%x 0x%x=0x%x 0x%x=0x%x 0x%x=0x%x\n", \ x1, readl(comp->regs + x1), x2, readl(comp->regs + x2), \ x3, readl(comp->regs + x3), x4, readl(comp->regs + x4)) #define PRINT_AAL3_REG(x1, x2, x3, x4) \ pr_notice("[3]0x%x=0x%x 0x%x=0x%x 0x%x=0x%x 0x%x=0x%x\n", \ x1, readl(dre3_va + x1), x2, readl(dre3_va + x2), \ x3, readl(dre3_va + x3), x4, readl(dre3_va + x4)) bool dump_reg(struct mtk_ddp_comp *comp, bool locked) { unsigned long flags = 0; struct mtk_disp_aal *aal_data = comp_to_aal(comp); bool dump_success = false; #if defined(CONFIG_MTK_DRE30_SUPPORT) void __iomem *dre3_va = mtk_aal_dre3_va(comp); #endif if (locked || spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal_data->is_clock_on)) { PRINT_AAL_REG(0x0, 0x8, 0x10, 0x20); PRINT_AAL_REG(0x30, 0xFC, 0x160, 0x200); PRINT_AAL_REG(0x204, 0x20C, 0x3B4, 0x45C); PRINT_AAL_REG(0x460, 0x464, 0x468, 0x4D8); PRINT_AAL_REG(0x4DC, 0x500, 0x224, 0x504); #if defined(CONFIG_MTK_DRE30_SUPPORT) PRINT_AAL3_REG(0x0, 0x8, 0x10, 0x20); PRINT_AAL3_REG(0x30, 0x34, 0x38, 0xC4); PRINT_AAL3_REG(0xC8, 0xF4, 0xF8, 0x200); PRINT_AAL3_REG(0x204, 0x45C, 0x460, 0x464); PRINT_AAL3_REG(0x468, 0x46C, 0x470, 0x474); PRINT_AAL3_REG(0x478, 0x480, 0x484, 0x488); PRINT_AAL3_REG(0x48C, 0x490, 0x494, 0x498); PRINT_AAL3_REG(0x49C, 0x4B4, 0x4B8, 0x4BC); PRINT_AAL3_REG(0x4D4, 0x4EC, 0x4F0, 0x53C); #endif dump_success = true; } else AALIRQ_LOG("clock is not enabled\n"); if (!locked) spin_unlock_irqrestore(&g_aal_clock_lock, flags); } else AALIRQ_LOG("clock lock is locked\n"); return dump_success; } static bool debug_skip_set_param; int mtk_drm_ioctl_aal_set_param(struct drm_device *dev, void *data, struct drm_file *file_priv) { int ret = 0; struct mtk_drm_private *private = dev->dev_private; struct mtk_ddp_comp *comp = private->ddp_comp[DDP_COMPONENT_AAL0]; struct drm_crtc *crtc = private->crtc[0]; int backlight_value = 0; struct DISP_AAL_PARAM *param = (struct DISP_AAL_PARAM *) data; bool delay_refresh = false; if (debug_skip_set_param) { pr_notice("skip_set_param for debug\n"); return ret; } /* Not need to protect g_aal_param, */ /* since only AALService can set AAL parameters. */ memcpy(&g_aal_param, param, sizeof(*param)); backlight_value = g_aal_param.FinalBacklight; /* set cabc gain zero when detect backlight */ /* setting equal to zero */ if (backlight_value == 0) g_aal_param.cabc_fltgain_force = 0; ret = mtk_crtc_user_cmd(crtc, comp, SET_PARAM, data); atomic_set(&g_aal_allowPartial, g_aal_param.allowPartial); if (atomic_read(&g_aal_backlight_notified) == 0) backlight_value = 0; if (m_new_pq_persist_property[DISP_PQ_CCORR_SILKY_BRIGHTNESS]) { if (g_aal_param.silky_bright_flag == 0) { AALAPI_LOG("backlight_value = %d, silky_bright_flag = %d", backlight_value, g_aal_param.silky_bright_flag); mt_leds_brightness_set("lcd-backlight", backlight_value); } } else { AALAPI_LOG("%d", backlight_value); mt_leds_brightness_set("lcd-backlight", backlight_value); } AALFLOW_LOG("delay refresh: %d", g_aal_param.refreshLatency); if (g_aal_param.refreshLatency == 33) delay_refresh = true; mtk_crtc_check_trigger(comp->mtk_crtc, delay_refresh, true); return ret; } static DEFINE_SPINLOCK(g_aal_get_irq_lock); static void disp_aal_clear_irq(struct mtk_ddp_comp *comp, bool cleared) { unsigned int intsta; unsigned long flags; struct mtk_disp_aal *aal_data = comp_to_aal(comp); /* Check current irq status */ do { intsta = readl(comp->regs + DISP_AAL_INTSTA); if (spin_trylock_irqsave(&g_aal_get_irq_lock, flags)) { writel(intsta & ~0x3, comp->regs + DISP_AAL_INTSTA); spin_unlock_irqrestore(&g_aal_get_irq_lock, flags); } } while (0); atomic_set(&aal_data->dirty_frame_retrieved, 1); /* * no need per-frame wakeup. * We stop interrupt until next frame dirty. */ if (cleared == true) { if (spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal_data->is_clock_on) != 1) AALIRQ_LOG("clock is off\n"); else disp_aal_set_interrupt(comp, false); spin_unlock_irqrestore(&g_aal_clock_lock, flags); } } AALIRQ_LOG("AAL Module, process:(%d) compID:%d\n", cleared, comp->id); } static bool debug_skip_dre3_irq; static bool debug_dump_reg_irq; static int dump_blk_x = -1; static int dump_blk_y = -1; #if defined(CONFIG_MTK_DRE30_SUPPORT) #define AAL_DRE_BLK_NUM (16) #define AAL_BLK_MAX_ALLOWED_NUM (128) #define AAL_DRE3_POINT_NUM (17) #define AAL_DRE_GAIN_POINT16_START (512) #define DRE_POLL_SLEEP_TIME_US (10) #define DRE_MAX_POLL_TIME_US (1000) static inline bool disp_aal_reg_poll(struct mtk_ddp_comp *comp, unsigned long addr, unsigned int value, unsigned int mask) { bool return_value = false; unsigned int reg_value = 0; unsigned int polling_time = 0; void __iomem *dre3_va = mtk_aal_dre3_va(comp); do { reg_value = readl(dre3_va + addr); if ((reg_value & mask) == value) { return_value = true; break; } udelay(DRE_POLL_SLEEP_TIME_US); polling_time += DRE_POLL_SLEEP_TIME_US; } while (polling_time < DRE_MAX_POLL_TIME_US); return return_value; } static inline bool disp_aal_sram_write(struct mtk_ddp_comp *comp, unsigned int addr, unsigned int value) { bool return_value = false; void __iomem *dre3_va = mtk_aal_dre3_va(comp); do { writel(addr, dre3_va + DISP_AAL_SRAM_RW_IF_0); if (disp_aal_reg_poll(comp, DISP_AAL_SRAM_STATUS, (0x1 << 16), (0x1 << 16)) != true) break; writel(value, dre3_va + DISP_AAL_SRAM_RW_IF_1); return_value = true; } while (0); return return_value; } static inline bool disp_aal_sram_read(struct mtk_ddp_comp *comp, unsigned int addr, unsigned int *value) { bool return_value = false; void __iomem *dre3_va = mtk_aal_dre3_va(comp); do { writel(addr, dre3_va + DISP_AAL_SRAM_RW_IF_2); if (disp_aal_reg_poll(comp, DISP_AAL_SRAM_STATUS, (0x1 << 17), (0x1 << 17)) != true) break; *value = readl(dre3_va + DISP_AAL_SRAM_RW_IF_3); return_value = true; } while (0); return return_value; } static bool disp_aal_read_dre3(struct mtk_ddp_comp *comp, const int dre_blk_x_num, const int dre_blk_y_num) { int hist_offset; int arry_offset = 0; unsigned int read_value; int dump_start = -1; u32 dump_table[6] = {0}; struct mtk_disp_aal *aal_data = comp_to_aal(comp); /* Read Global histogram for ESS */ if (disp_aal_read_single_hist(comp) != true) return false; AALIRQ_LOG("start\n"); if (dump_blk_x >= 0 && dump_blk_x < 16 && dump_blk_y >= 0 && dump_blk_y < 8) dump_start = 6 * (dump_blk_x + dump_blk_y * 16); /* Read Local histogram for DRE 3 */ for (hist_offset = aal_data->data->aal_dre_hist_start; hist_offset <= aal_data->data->aal_dre_hist_end; hist_offset += 4) { if (disp_aal_sram_read(comp, hist_offset, &read_value) != true) return false; if (arry_offset >= AAL_DRE30_HIST_REGISTER_NUM) return false; if (dump_start >= 0 && arry_offset >= dump_start && arry_offset < (dump_start + 6)) dump_table[arry_offset-dump_start] = read_value; if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) g_aal_dre30_hist.aal0_dre_hist[arry_offset++] = read_value; else if (comp->id == DDP_COMPONENT_AAL1) g_aal_dre30_hist.aal1_dre_hist[arry_offset++] = read_value; } else { g_aal_dre30_hist.aal0_dre_hist[arry_offset++] = read_value; } } if (comp->mtk_crtc->is_dual_pipe) { int i = 0, j = 0; if (comp->id == DDP_COMPONENT_AAL0) { for (i = 0; i < 8; i++) { g_aal_hist.MaxHis_denominator_pipe0[i] = readl(comp->regs + MDP_AAL_DUAL_PIPE00 + (i << 2)); } for (j = 0; j < 8; j++) { g_aal_hist.MaxHis_denominator_pipe0[j+i] = readl(comp->regs + MDP_AAL_DUAL_PIPE08 + (j << 2)); } } else if (comp->id == DDP_COMPONENT_AAL1) { for (i = 0; i < 8; i++) { g_aal_hist.MaxHis_denominator_pipe1[i] = readl(comp->regs + MDP_AAL_DUAL_PIPE00 + (i << 2)); } for (j = 0; j < 8; j++) { g_aal_hist.MaxHis_denominator_pipe1[j+i] = readl(comp->regs + MDP_AAL_DUAL_PIPE08 + (j << 2)); } } } if (dump_start >= 0) pr_notice("[DRE3][HIST][%d-%d] %08x %08x %08x %08x %08x %08x\n", dump_blk_x, dump_blk_y, dump_table[0], dump_table[1], dump_table[2], dump_table[3], dump_table[4], dump_table[5]); return true; } static bool disp_aal_write_dre3(struct mtk_ddp_comp *comp) { int gain_offset; int arry_offset = 0; unsigned int write_value; struct mtk_disp_aal *aal_data = comp_to_aal(comp); /* Write Local Gain Curve for DRE 3 */ AALIRQ_LOG("start\n"); for (gain_offset = aal_data->data->aal_dre_gain_start; gain_offset <= aal_data->data->aal_dre_gain_end; gain_offset += 4) { if (arry_offset >= AAL_DRE30_GAIN_REGISTER_NUM) return false; write_value = g_aal_gain.dre30_gain[arry_offset++]; if (!disp_aal_sram_write(comp, gain_offset, write_value)) return false; } return true; } static void disp_aal_update_dre3_sram(struct mtk_ddp_comp *comp, bool check_sram) { bool result = false; unsigned long flags; int dre_blk_x_num, dre_blk_y_num; unsigned int read_value; int hist_apb = 0, hist_int = 0; void __iomem *dre3_va = mtk_aal_dre3_va(comp); AALIRQ_LOG("[g_aal_first_frame = %d", atomic_read(&g_aal_first_frame)); AALIRQ_LOG("[g_aal0_hist_available = %d", atomic_read(&g_aal0_hist_available)); AALIRQ_LOG("[g_aal_eof_irq = %d", atomic_read(&g_aal_eof_irq)); AALIRQ_LOG("[g_aal1_eof_irq = %d", atomic_read(&g_aal1_eof_irq)); if (check_sram) { read_value = readl(dre3_va + DISP_AAL_SRAM_CFG); hist_apb = (read_value >> 5) & 0x1; hist_int = (read_value >> 6) & 0x1; AALIRQ_LOG("[SRAM] hist_apb(%d) hist_int(%d) 0x%08x in (SOF) compID:%d", hist_apb, hist_int, read_value, comp->id); if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL1) { if (hist_int != atomic_read(&g_aal1_force_hist_apb)) { AALIRQ_LOG("dre3 aal1: SRAM config %d != %d config?", hist_int, atomic_read(&g_aal1_force_hist_apb)); if (atomic_read(&g_aal1_first_frame_flip) == 1) { atomic_set(&g_aal1_first_frame_flip, 0); atomic_set(&g_aal1_eof_irq, 0); AALIRQ_LOG("comp_id[1] first_frame_flip end"); } } else if (atomic_read(&g_aal1_first_frame_flip) == 1) { atomic_set(&g_aal1_first_frame_flip, 0); AALIRQ_LOG("comp_id[1] aal1_first_frame_flip[0]"); } } else if (comp->id == DDP_COMPONENT_AAL0) { if (hist_int != atomic_read(&g_aal_force_hist_apb)) { AALIRQ_LOG("dre3 aal0: SRAM config %d != %d config?", hist_int, atomic_read(&g_aal_force_hist_apb)); if (atomic_read(&g_aal_first_frame_flip) == 1) { atomic_set(&g_aal_first_frame_flip, 0); atomic_set(&g_aal_eof_irq, 0); AALIRQ_LOG("comp_id[0] first_frame_flip end"); } } else if (atomic_read(&g_aal_first_frame_flip) == 1) { atomic_set(&g_aal_first_frame_flip, 0); AALIRQ_LOG("comp_id[0] aal_first_frame_flip[0]"); } } } else if (hist_int != atomic_read(&g_aal_force_hist_apb)) AALIRQ_LOG("dre3: SRAM config %d != %d config?", hist_int, atomic_read(&g_aal_force_hist_apb)); } read_value = readl(dre3_va + DISP_AAL_DRE_BLOCK_INFO_01); dre_blk_x_num = aal_min(AAL_DRE_BLK_NUM, read_value & 0x1F); dre_blk_y_num = aal_min(AAL_BLK_MAX_ALLOWED_NUM/dre_blk_x_num, (read_value >> 5) & 0x1F); if (spin_trylock_irqsave(&g_aal_hist_lock, flags)) { result = disp_aal_read_dre3(comp, dre_blk_x_num, dre_blk_y_num); if (result) { g_aal_dre30_hist.dre_blk_x_num = dre_blk_x_num; g_aal_dre30_hist.dre_blk_y_num = dre_blk_y_num; if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal0_hist_available, 1); else if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_hist_available, 1); } else atomic_set(&g_aal0_hist_available, 1); } spin_unlock_irqrestore(&g_aal_hist_lock, flags); if (result) { AALIRQ_LOG("wake_up_interruptible"); wake_up_interruptible(&g_aal_hist_wq); } else if (!(comp->mtk_crtc->is_dual_pipe)) { if (atomic_read(&g_aal_first_frame) == 1) { AALIRQ_LOG("single pipe g_aal_first_frame[1] queue_work"); queue_work(aal_flip_wq, &g_aal_data->aal_flip_task); } } } if (spin_trylock_irqsave(&g_aal_dre3_gain_lock, flags)) { /* Write DRE 3.0 gain */ disp_aal_write_dre3(comp); spin_unlock_irqrestore(&g_aal_dre3_gain_lock, flags); } } static void disp_aal_dre3_irq_handle(struct mtk_ddp_comp *comp) { int hist_apb = 0, hist_int = 0; void __iomem *dre3_va = mtk_aal_dre3_va(comp); /* Only process AAL0 in single module state */ disp_aal_clear_irq(comp, false); if (atomic_read(&g_aal_change_to_dre30) != 0x3) return; if (debug_dump_reg_irq) debug_dump_reg_irq = !dump_reg(comp, true); if (debug_skip_dre3_irq) { pr_notice("skip dre3 irq for debug\n"); return; } if (aal_sram_method == AAL_SRAM_EOF && atomic_read(&g_aal_dre_halt) == 0) { if (comp->mtk_crtc->is_dual_pipe && comp->id == DDP_COMPONENT_AAL1) { if (atomic_cmpxchg(&g_aal1_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal1_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("Error when get hist_apb irq_handler\n"); return; } } else { if (atomic_cmpxchg(&g_aal_force_hist_apb, 0, 1) == 0) { hist_apb = 0; hist_int = 1; } else if (atomic_cmpxchg(&g_aal_force_hist_apb, 1, 0) == 1) { hist_apb = 1; hist_int = 0; } else { AALERR("Error when get hist_apb irq_handler\n"); return; } } AALIRQ_LOG("[SRAM] %s hist_apb (%d) hist_int (%d) in(EOF) comp:%d", __func__, hist_apb, hist_int, comp->id); mtk_aal_write_mask(dre3_va + DISP_AAL_SRAM_CFG, (hist_int << 6)|(hist_apb << 5)|(1 << 4), (0x7 << 4)); atomic_set(&g_aal_dre_halt, 1); disp_aal_update_dre3_sram(comp, false); atomic_set(&g_aal_dre_halt, 0); } else if (aal_sram_method == AAL_SRAM_SOF) { if (mtk_drm_is_idle(&(comp->mtk_crtc->base))) { AALIRQ_LOG("[SRAM] when idle, operate SRAM in (EOF) comp id:%d ", comp->id); disp_aal_update_dre3_sram(comp, false); } AALIRQ_LOG("[SRAM] clean dre_config in (EOF) comp->id = %d", comp->id); if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal_dre_config, 0); else if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_dre_config, 0); } else atomic_set(&g_aal_dre_config, 0); } } static void disp_aal_set_init_dre30(struct DISP_DRE30_INIT *user_regs) { struct DISP_DRE30_INIT *init_dre3; init_dre3 = &g_aal_init_dre30; memcpy(init_dre3, user_regs, sizeof(*init_dre3)); /* Modify DRE3.0 config flag */ atomic_or(0x2, &g_aal_change_to_dre30); } static void ddp_aal_dre3_write_curve_full(struct mtk_ddp_comp *comp) { void __iomem *dre3_va = mtk_aal_dre3_va(comp); mtk_aal_write_mask(dre3_va + DISP_AAL_SRAM_CFG, (1 << 6)|(0 << 5)|(1 << 4), (0x7 << 4)); disp_aal_write_dre3(comp); mtk_aal_write_mask(dre3_va + DISP_AAL_SRAM_CFG, (0 << 6)|(1 << 5)|(1 << 4), (0x7 << 4)); disp_aal_write_dre3(comp); if (comp->mtk_crtc->is_dual_pipe && comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_force_hist_apb, 0); else atomic_set(&g_aal_force_hist_apb, 0); } static bool write_block(const unsigned int *dre3_gain, const int block_x, const int block_y, const int dre_blk_x_num) { bool return_value = false; uint32_t block_offset = 4 * (block_y * dre_blk_x_num + block_x); do { if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) break; g_aal_gain.dre30_gain[block_offset++] = ((dre3_gain[0] & 0xff) | ((dre3_gain[1] & 0xff) << 8) | ((dre3_gain[2] & 0xff) << 16) | ((dre3_gain[3] & 0xff) << 24)); if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) break; g_aal_gain.dre30_gain[block_offset++] = ((dre3_gain[4] & 0xff) | ((dre3_gain[5] & 0xff) << 8) | ((dre3_gain[6] & 0xff) << 16) | ((dre3_gain[7] & 0xff) << 24)); if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) break; g_aal_gain.dre30_gain[block_offset++] = ((dre3_gain[8] & 0xff) | ((dre3_gain[9] & 0xff) << 8) | ((dre3_gain[10] & 0xff) << 16) | ((dre3_gain[11] & 0xff) << 24)); if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) break; g_aal_gain.dre30_gain[block_offset++] = ((dre3_gain[12] & 0xff) | ((dre3_gain[13] & 0xff) << 8) | ((dre3_gain[14] & 0xff) << 16) | ((dre3_gain[15] & 0xff) << 24)); return_value = true; } while (0); return return_value; } static bool write_curve16(const unsigned int *dre3_gain, const int dre_blk_x_num, const int dre_blk_y_num) { int32_t blk_x, blk_y; const int32_t blk_num_max = dre_blk_x_num * dre_blk_y_num; unsigned int write_value = 0x0; uint32_t bit_shift = 0; uint32_t block_offset = AAL_DRE_GAIN_POINT16_START; for (blk_y = 0; blk_y < dre_blk_y_num; blk_y++) { for (blk_x = 0; blk_x < dre_blk_x_num; blk_x++) { write_value |= ((dre3_gain[16] & 0xff) << (8*bit_shift)); bit_shift++; if (bit_shift >= 4) { if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) return false; g_aal_gain.dre30_gain[block_offset++] = write_value; write_value = 0x0; bit_shift = 0; } } } if ((blk_num_max>>2)<<2 != blk_num_max) { /* configure last curve */ if (block_offset >= AAL_DRE30_GAIN_REGISTER_NUM) return false; g_aal_gain.dre30_gain[block_offset] = write_value; } return true; } static void disp_aal_dre3_init(struct mtk_ddp_comp *comp) { const int dre_blk_x_num = 8; const int dre_blk_y_num = 16; unsigned long flags; int blk_x, blk_y, curve_point; unsigned int dre3_gain[AAL_DRE3_POINT_NUM]; AALFLOW_LOG("start\n"); for (curve_point = 0; curve_point < AAL_DRE3_POINT_NUM; curve_point++) { /* assign initial gain curve */ dre3_gain[curve_point] = aal_min(255, 16 * curve_point); } spin_lock_irqsave(&g_aal_dre3_gain_lock, flags); for (blk_y = 0; blk_y < dre_blk_y_num; blk_y++) { for (blk_x = 0; blk_x < dre_blk_x_num; blk_x++) { /* write each block dre curve */ write_block(dre3_gain, blk_x, blk_y, dre_blk_x_num); } } /* write each block dre curve last point */ write_curve16(dre3_gain, dre_blk_x_num, dre_blk_y_num); ddp_aal_dre3_write_curve_full(comp); spin_unlock_irqrestore(&g_aal_dre3_gain_lock, flags); } #else static void disp_aal_single_pipe_hist_update(struct mtk_ddp_comp *comp) { unsigned int intsta; unsigned long flags; struct mtk_disp_aal *aal_data = comp_to_aal(comp); bool read_success = false; do { intsta = readl(comp->regs + DISP_AAL_INTSTA); AALIRQ_LOG("AAL Module, intsta: 0x%x\n", intsta); /* Only process end of frame state */ if ((intsta & 0x2) == 0x0) { AALERR("break\n"); break; } if (spin_trylock_irqsave(&g_aal_get_irq_lock, flags)) { writel(intsta & ~0x3, comp->regs + DISP_AAL_INTSTA); spin_unlock_irqrestore(&g_aal_get_irq_lock, flags); } /* Allow to disable interrupt */ AALIRQ_LOG("set dirty_frame_retrieved to 1\n"); atomic_set(&aal_data->dirty_frame_retrieved, 1); if (spin_trylock_irqsave(&g_aal_hist_lock, flags)) { read_success = disp_aal_read_single_hist(comp); if (read_success == true) { if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal0_hist_available, 1); else if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_hist_available, 1); } else atomic_set(&g_aal0_hist_available, 1); } spin_unlock_irqrestore(&g_aal_hist_lock, flags); AALIRQ_LOG("wake_up_interruptible g_aal_hist_wq:%d\n", read_success); if (read_success == true) wake_up_interruptible(&g_aal_hist_wq); } else { /* * Histogram was not be retrieved, but it's OK. * Another interrupt will come until histogram available * See: disp_aal_set_interrupt() */ } if (atomic_read(&g_aal_is_init_regs_valid) == 0) { /* * AAL service is not running, not need per-frame wakeup * We stop interrupt until next frame dirty. */ AALIRQ_LOG("set disp_aal_set_interrupt to 0\n"); if (spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal_data->is_clock_on) != 1) AALIRQ_LOG("clock is off\n"); else disp_aal_set_interrupt(comp, false); spin_unlock_irqrestore(&g_aal_clock_lock, flags); } } } while (0); } #endif /* CONFIG_MTK_DRE30_SUPPORT */ int mtk_drm_ioctl_aal_init_dre30(struct drm_device *dev, void *data, struct drm_file *file_priv) { #if defined(CONFIG_MTK_DRE30_SUPPORT) AALFLOW_LOG("\n"); disp_aal_set_init_dre30((struct DISP_DRE30_INIT *) data); #else AALFLOW_LOG("DRE30 not support\n"); #endif return 0; } static int disp_aal_wait_size(unsigned long timeout) { int ret = 0; if (g_aal_get_size_available == false) { ret = wait_event_interruptible(g_aal_size_wq, g_aal_get_size_available == true); pr_notice("size_available = 1, Waken up, ret = %d\n", ret); } else { /* If g_aal_get_size_available is already set, */ /* means AALService was delayed */ pr_notice("size_available = 0\n"); } return ret; } int mtk_drm_ioctl_aal_get_size(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct DISP_AAL_DISPLAY_SIZE *dst = (struct DISP_AAL_DISPLAY_SIZE *)data; struct mtk_drm_private *private = dev->dev_private; struct mtk_ddp_comp *comp = private->ddp_comp[DDP_COMPONENT_AAL0]; AALFLOW_LOG("\n"); disp_aal_wait_size(60); if (comp->mtk_crtc->is_dual_pipe) memcpy(dst, &g_dual_aal_size, sizeof(g_dual_aal_size)); else memcpy(dst, &g_aal_size, sizeof(g_aal_size)); return 0; } static void mtk_aal_start(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle) { #if defined(CONFIG_MTK_DRE30_SUPPORT) int dre_alg_mode = 0; phys_addr_t dre3_pa = mtk_aal_dre3_pa(comp); if (atomic_read(&g_aal_change_to_dre30) & 0x1) dre_alg_mode = 1; if (debug_bypass_alg_mode) dre_alg_mode = 0; cmdq_pkt_write(handle, comp->cmdq_base, dre3_pa + DISP_AAL_CFG_MAIN, dre_alg_mode << 4, 1 << 4); #endif AALFLOW_LOG("\n"); basic_cmdq_write(handle, comp, DISP_AAL_EN, 0x1, ~0); } static void mtk_aal_stop(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle) { basic_cmdq_write(handle, comp, DISP_AAL_EN, 0x0, ~0); } static void mtk_aal_bypass(struct mtk_ddp_comp *comp, int bypass, struct cmdq_pkt *handle) { #if 1 if (atomic_read(&g_aal_force_relay) != bypass) { AALFLOW_LOG("\n"); cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DISP_AAL_CFG, bypass, 0x1); if (comp->mtk_crtc->is_dual_pipe) { struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc; struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_ddp_comp *comp_aal1 = priv->ddp_comp[DDP_COMPONENT_AAL1]; cmdq_pkt_write(handle, comp_aal1->cmdq_base, comp_aal1->regs_pa + DISP_AAL_CFG, bypass, 0x1); } atomic_set(&g_aal_force_relay, bypass); } #else AALFLOW_LOG("is ignored\n"); #endif } static int mtk_aal_user_cmd(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, unsigned int cmd, void *data) { AALFLOW_LOG("cmd: %d\n", cmd); switch (cmd) { case INIT_REG: if (disp_aal_set_init_reg(comp, handle, (struct DISP_AAL_INITREG *) data) < 0) { AALERR("INIT_REG: fail\n"); return -EFAULT; } break; case SET_PARAM: if (disp_aal_set_param(comp, handle, (struct DISP_AAL_PARAM *) data) < 0) { AALERR("SET_PARAM: fail\n"); return -EFAULT; } break; case EVENTCTL: disp_aal_flip_sram(comp, handle, __func__); if (comp->mtk_crtc->is_dual_pipe) { struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc; struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_ddp_comp *comp_aal1 = priv->ddp_comp[DDP_COMPONENT_AAL1]; disp_aal_flip_sram(comp_aal1, handle, __func__); } break; case FLIP_SRAM: disp_aal_first_flip_sram(comp, handle, __func__); if (comp->mtk_crtc->is_dual_pipe) { struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc; struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_ddp_comp *comp_aal1 = priv->ddp_comp[DDP_COMPONENT_AAL1]; disp_aal_first_flip_sram(comp_aal1, handle, __func__); } break; case BYPASS_AAL: { int *value = data; mtk_aal_bypass(comp, *value, handle); } break; default: AALERR("error cmd: %d\n", cmd); return -EINVAL; } return 0; } #define DRE_FLT_NUM (12) #define CABC_GAINLMT_NUM (11) struct aal_backup { /* structure for backup AAL register value */ unsigned int DRE_MAPPING; unsigned int DRE_FLT_FORCE[DRE_FLT_NUM]; unsigned int CABC_00; unsigned int CABC_02; unsigned int CABC_GAINLMT[CABC_GAINLMT_NUM]; #if defined(DRE3_IN_DISP_AAL) unsigned int DRE_BLOCK_INFO_00; unsigned int DRE_BLOCK_INFO_01; unsigned int DRE_BLOCK_INFO_02; unsigned int DRE_BLOCK_INFO_04; unsigned int DRE_BLOCK_INFO_05; unsigned int DRE_BLOCK_INFO_06; unsigned int DRE_BLOCK_INFO_07; unsigned int DRE_CHROMA_HIST_00; unsigned int DRE_CHROMA_HIST_01; unsigned int DRE_ALPHA_BLEND_00; unsigned int SRAM_CFG; unsigned int DUAL_PIPE_INFO_00; unsigned int DUAL_PIPE_INFO_01; #endif unsigned int AAL_CFG; }; static struct aal_backup g_aal_backup; static void ddp_aal_dre3_backup(struct mtk_ddp_comp *comp) { #if defined(DRE3_IN_DISP_AAL) struct mtk_disp_aal *aal_data = comp_to_aal(comp); g_aal_backup.DRE_BLOCK_INFO_00 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_00); g_aal_backup.DRE_BLOCK_INFO_01 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_01); g_aal_backup.DRE_BLOCK_INFO_02 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_02); g_aal_backup.DRE_BLOCK_INFO_04 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_04); g_aal_backup.DRE_CHROMA_HIST_00 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_CHROMA_HIST_00); g_aal_backup.DRE_CHROMA_HIST_01 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_CHROMA_HIST_01); g_aal_backup.DRE_ALPHA_BLEND_00 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_ALPHA_BLEND_00); g_aal_backup.DRE_BLOCK_INFO_05 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_05); g_aal_backup.DRE_BLOCK_INFO_06 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_06); g_aal_backup.DRE_BLOCK_INFO_07 = readl(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_07); g_aal_backup.SRAM_CFG = readl(aal_data->dre3_hw.va + DISP_AAL_SRAM_CFG); g_aal_backup.DUAL_PIPE_INFO_00 = readl(aal_data->dre3_hw.va + DISP_AAL_DUAL_PIPE_INFO_00); g_aal_backup.DUAL_PIPE_INFO_01 = readl(aal_data->dre3_hw.va + DISP_AAL_DUAL_PIPE_INFO_01); #endif /* CONFIG_MTK_DRE30_SUPPORT */ } static void ddp_aal_dre_backup(struct mtk_ddp_comp *comp) { int i; g_aal_backup.DRE_MAPPING = readl(comp->regs + DISP_AAL_DRE_MAPPING_00); for (i = 0; i < DRE_FLT_NUM; i++) g_aal_backup.DRE_FLT_FORCE[i] = readl(comp->regs + DISP_AAL_DRE_FLT_FORCE(i)); } static void ddp_aal_cabc_backup(struct mtk_ddp_comp *comp) { #if defined(CONFIG_MTK_DRE30_SUPPORT) || !defined(NOT_SUPPORT_CABC_HW) int i; g_aal_backup.CABC_00 = readl(comp->regs + DISP_AAL_CABC_00); g_aal_backup.CABC_02 = readl(comp->regs + DISP_AAL_CABC_02); for (i = 0; i < CABC_GAINLMT_NUM; i++) g_aal_backup.CABC_GAINLMT[i] = readl(comp->regs + DISP_AAL_CABC_GAINLMT_TBL(i)); #endif /* not define NOT_SUPPORT_CABC_HW */ } static void ddp_aal_cfg_backup(struct mtk_ddp_comp *comp) { g_aal_backup.AAL_CFG = readl(comp->regs + DISP_AAL_CFG); } static void ddp_aal_backup(struct mtk_ddp_comp *comp) { AALFLOW_LOG("\n"); ddp_aal_cabc_backup(comp); ddp_aal_dre_backup(comp); ddp_aal_dre3_backup(comp); ddp_aal_cfg_backup(comp); atomic_set(&g_aal_initialed, 1); } static void ddp_aal_dre3_restore(struct mtk_ddp_comp *comp) { #if defined(DRE3_IN_DISP_AAL) struct mtk_disp_aal *aal_data = comp_to_aal(comp); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_00, g_aal_backup.DRE_BLOCK_INFO_00 & (0x1FFF << 13), 0x1FFF << 13); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_01, g_aal_backup.DRE_BLOCK_INFO_01, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_02, g_aal_backup.DRE_BLOCK_INFO_02, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_04, g_aal_backup.DRE_BLOCK_INFO_04 & (0x3FF << 13), 0x3FF << 13); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_CHROMA_HIST_00, g_aal_backup.DRE_CHROMA_HIST_00, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_CHROMA_HIST_01, g_aal_backup.DRE_CHROMA_HIST_01 & 0xFFFF, 0xFFFF); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_ALPHA_BLEND_00, g_aal_backup.DRE_ALPHA_BLEND_00, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_05, g_aal_backup.DRE_BLOCK_INFO_05, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_06, g_aal_backup.DRE_BLOCK_INFO_06, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DRE_BLOCK_INFO_07, g_aal_backup.DRE_BLOCK_INFO_07, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_SRAM_CFG, g_aal_backup.SRAM_CFG, 0x1); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DUAL_PIPE_INFO_00, g_aal_backup.DUAL_PIPE_INFO_00, ~0); mtk_aal_write_mask(aal_data->dre3_hw.va + DISP_AAL_DUAL_PIPE_INFO_01, g_aal_backup.DUAL_PIPE_INFO_01, ~0); #endif #if defined(CONFIG_MTK_DRE30_SUPPORT) unsigned long flags; spin_lock_irqsave(&g_aal_dre3_gain_lock, flags); ddp_aal_dre3_write_curve_full(comp); spin_unlock_irqrestore(&g_aal_dre3_gain_lock, flags); #endif /* CONFIG_MTK_DRE30_SUPPORT */ } static void ddp_aal_dre_restore(struct mtk_ddp_comp *comp) { int i; writel(g_aal_backup.DRE_MAPPING, comp->regs + DISP_AAL_DRE_MAPPING_00); for (i = 0; i < DRE_FLT_NUM; i++) writel(g_aal_backup.DRE_FLT_FORCE[i], comp->regs + DISP_AAL_DRE_FLT_FORCE(i)); } static void ddp_aal_cabc_restore(struct mtk_ddp_comp *comp) { #if defined(CONFIG_MTK_DRE30_SUPPORT) || !defined(NOT_SUPPORT_CABC_HW) int i; writel(g_aal_backup.CABC_00, comp->regs + DISP_AAL_CABC_00); writel(g_aal_backup.CABC_02, comp->regs + DISP_AAL_CABC_02); for (i = 0; i < CABC_GAINLMT_NUM; i++) writel(g_aal_backup.CABC_GAINLMT[i], comp->regs + DISP_AAL_CABC_GAINLMT_TBL(i)); #endif /* not define NOT_SUPPORT_CABC_HW */ } static void ddp_aal_cfg_restore(struct mtk_ddp_comp *comp) { writel(g_aal_backup.AAL_CFG, comp->regs + DISP_AAL_CFG); } static void ddp_aal_restore(struct mtk_ddp_comp *comp) { if (atomic_read(&g_aal_initialed) != 1) return; AALFLOW_LOG("\n"); ddp_aal_cabc_restore(comp); ddp_aal_dre_restore(comp); ddp_aal_dre3_restore(comp); ddp_aal_cfg_restore(comp); } static bool debug_skip_first_br; static void mtk_aal_prepare(struct mtk_ddp_comp *comp) { #if defined(CONFIG_MTK_DRE30_SUPPORT) int ret = 0; #endif struct mtk_disp_aal *aal_data = comp_to_aal(comp); bool first_restore = (atomic_read(&aal_data->is_clock_on) == 0); AALFLOW_LOG("\n"); mtk_ddp_comp_clk_prepare(comp); atomic_set(&aal_data->is_clock_on, 1); if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal_data->is_clock_on, 1); if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_data->is_clock_on, 1); AALFLOW_LOG("[aal_data, g_aal_data] addr[%x, %x] val[%d, %d]\n", &aal_data->is_clock_on, &g_aal_data->is_clock_on, atomic_read(&aal_data->is_clock_on), atomic_read(&g_aal_data->is_clock_on)); #if defined(CONFIG_MTK_DRE30_SUPPORT) if (aal_data->dre3_hw.clk) { ret = clk_prepare(aal_data->dre3_hw.clk); if (ret) { AALERR("Can't prepare dre3 hw clk: %d\n", ret); return; } } #endif if (!first_restore && !debug_skip_first_br) return; #if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT) if (aal_data->data->support_shadow) { /* Enable shadow register and read shadow register */ mtk_ddp_write_mask_cpu(comp, 0x0, DISP_AAL_SHADOW_CTRL, AAL_BYPASS_SHADOW); } else { /* Bypass shadow register and read shadow register */ mtk_ddp_write_mask_cpu(comp, AAL_BYPASS_SHADOW, DISP_AAL_SHADOW_CTRL, AAL_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, AAL_BYPASS_SHADOW, DISP_AAL_SHADOW_CTRL, AAL_BYPASS_SHADOW); #endif #endif ddp_aal_restore(comp); #if defined(CONFIG_MTK_DRE30_SUPPORT) if (comp->mtk_crtc->is_dual_pipe) { if (comp->id == DDP_COMPONENT_AAL0) { if (atomic_cmpxchg(&g_aal_dre_hw_init, 0, 1) == 0) disp_aal_dre3_init(comp); } else if (comp->id == DDP_COMPONENT_AAL1) { if (atomic_cmpxchg(&g_aal1_dre_hw_init, 0, 1) == 0) disp_aal_dre3_init(comp); } } else if (atomic_cmpxchg(&g_aal_dre_hw_init, 0, 1) == 0) disp_aal_dre3_init(comp); #endif } static void mtk_aal_unprepare(struct mtk_ddp_comp *comp) { struct mtk_disp_aal *aal_data = comp_to_aal(comp); unsigned long flags; bool first_backup = (atomic_read(&aal_data->is_clock_on) == 1); AALFLOW_LOG("\n"); spin_lock_irqsave(&g_aal_clock_lock, flags); atomic_set(&aal_data->is_clock_on, 0); if (comp->id == DDP_COMPONENT_AAL0) { atomic_set(&g_aal_data->is_clock_on, 0); atomic_set(&g_aal_first_frame, 1); #if defined(CONFIG_MTK_DRE30_SUPPORT) atomic_set(&g_aal_dre_config, 0); atomic_set(&g_aal_first_frame_flip, 0); #endif } else if (comp->id == DDP_COMPONENT_AAL1) { atomic_set(&g_aal1_data->is_clock_on, 0); atomic_set(&g_aal1_first_frame, 1); #if defined(CONFIG_MTK_DRE30_SUPPORT) atomic_set(&g_aal1_dre_config, 0); atomic_set(&g_aal1_first_frame_flip, 0); #endif } spin_unlock_irqrestore(&g_aal_clock_lock, flags); if (first_backup || debug_skip_first_br) ddp_aal_backup(comp); //disp_aal_clear_irq(comp, true); mtk_ddp_comp_clk_unprepare(comp); #if defined(CONFIG_MTK_DRE30_SUPPORT) if (aal_data->dre3_hw.clk) clk_unprepare(aal_data->dre3_hw.clk); #endif } void mtk_aal_first_cfg(struct mtk_ddp_comp *comp, struct mtk_ddp_config *cfg, struct cmdq_pkt *handle) { AALFLOW_LOG("\n"); mtk_aal_config(comp, cfg, handle); } int mtk_aal_io_cmd(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle, enum mtk_ddp_io_cmd cmd, void *params) { unsigned long flags; struct mtk_disp_aal *aal_data = comp_to_aal(comp); if (cmd == FRAME_DIRTY) { AALFLOW_LOG("FRAME_DIRTY comp id:%d\n", comp->id); if (spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal_data->is_clock_on) != 1) AALIRQ_LOG("clock is off\n"); else disp_aal_set_interrupt(comp, true); spin_unlock_irqrestore(&g_aal_clock_lock, flags); } } return 0; } static const struct mtk_ddp_comp_funcs mtk_disp_aal_funcs = { .config = mtk_aal_config, .first_cfg = mtk_aal_first_cfg, .start = mtk_aal_start, .stop = mtk_aal_stop, .bypass = mtk_aal_bypass, .user_cmd = mtk_aal_user_cmd, .io_cmd = mtk_aal_io_cmd, .prepare = mtk_aal_prepare, .unprepare = mtk_aal_unprepare, }; static int mtk_disp_aal_bind(struct device *dev, struct device *master, void *data) { struct mtk_disp_aal *priv = dev_get_drvdata(dev); struct drm_device *drm_dev = data; int ret; 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; } return 0; } static void mtk_disp_aal_unbind(struct device *dev, struct device *master, void *data) { struct mtk_disp_aal *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_aal_component_ops = { .bind = mtk_disp_aal_bind, .unbind = mtk_disp_aal_unbind, }; void mtk_aal_dump(struct mtk_ddp_comp *comp) { void __iomem *baddr = comp->regs; DDPDUMP("== %s REGS ==\n", mtk_dump_comp_str(comp)); mtk_cust_dump_reg(baddr, 0x0, 0x20, 0x30, 0x4D8); mtk_cust_dump_reg(baddr, 0x24, 0x28, 0x200, 0x10); } void disp_aal_on_end_of_frame(struct mtk_ddp_comp *comp) { //For 120Hz rotation issue do_gettimeofday(&start); if (comp->id == DDP_COMPONENT_AAL0) atomic_set(&g_aal_eof_irq, 1); if (comp->id == DDP_COMPONENT_AAL1) atomic_set(&g_aal1_eof_irq, 1); if (atomic_read(&g_aal_force_relay) == 1) { disp_aal_clear_irq(comp, true); return; } #if defined(CONFIG_MTK_DRE30_SUPPORT) disp_aal_dre3_irq_handle(comp); #else disp_aal_single_pipe_hist_update(comp); #endif /* CONFIG_MTK_DRE30_SUPPORT */ AALIRQ_LOG("g_aal_first_frame = %d, g_aal_eof_irq = %d", atomic_read(&g_aal_first_frame), atomic_read(&g_aal_eof_irq)); if (isDualPQ) { AALIRQ_LOG("g_aal1_first_frame = %d, g_aal1_eof_irq = %d", atomic_read(&g_aal1_first_frame), atomic_read(&g_aal1_eof_irq)); if (atomic_read(&g_aal_first_frame) == 1 && atomic_read(&g_aal1_first_frame) == 1) { if (atomic_read(&g_aal_eof_irq) == 1 && atomic_read(&g_aal1_eof_irq) == 1) { AALIRQ_LOG("aal_refresh_task"); atomic_set(&g_aal_first_frame, 0); atomic_set(&g_aal1_first_frame, 0); queue_work(aal_refresh_wq, &g_aal_data->aal_refresh_task); } } } else { if (atomic_read(&g_aal_first_frame) == 1) { AALIRQ_LOG("aal_refresh_task"); atomic_set(&g_aal_first_frame, 0); queue_work(aal_refresh_wq, &g_aal_data->aal_refresh_task); } } } void disp_aal_on_start_of_frame(void) { #ifdef CONFIG_MTK_DRE30_SUPPORT unsigned long flags; struct mtk_disp_aal *aal_data = comp_to_aal(default_comp); if (atomic_read(&g_aal_force_relay) == 1 && !m_new_pq_persist_property[DISP_PQ_CCORR_SILKY_BRIGHTNESS]) return; if (atomic_read(&g_aal_change_to_dre30) != 0x3) return; if (aal_sram_method != AAL_SRAM_SOF) return; AALIRQ_LOG("[SRAM] g_aal_dre_config(%d) in SOF", atomic_read(&g_aal_dre_config)); spin_lock_irqsave(&g_aal_clock_lock, flags); if (atomic_read(&aal_data->is_clock_on) != 1) AALIRQ_LOG("clock is off\n"); else disp_aal_update_dre3_sram(default_comp, true); spin_unlock_irqrestore(&g_aal_clock_lock, flags); if (isDualPQ) { struct mtk_disp_aal *aal1_data = comp_to_aal(aal1_default_comp); AALIRQ_LOG("[SRAM] g_aal1_dre_config(%d) in SOF", atomic_read(&g_aal1_dre_config)); if (spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal1_data->is_clock_on) != 1) AALIRQ_LOG("aal1 clock is off\n"); else disp_aal_update_dre3_sram(aal1_default_comp, true); spin_unlock_irqrestore(&g_aal_clock_lock, flags); } if (atomic_read(&g_aal_first_frame) == 1 && atomic_read(&g_aal1_first_frame) == 1) { AALFLOW_LOG("dual pipe first_flip queue_work"); queue_work(aal_flip_wq, &g_aal_data->aal_flip_task); AALFLOW_LOG("end first_flip queue_work"); } } #endif } static irqreturn_t mtk_disp_aal_irq_handler(int irq, void *dev_id) { unsigned long flags; irqreturn_t ret = IRQ_NONE; struct mtk_disp_aal *priv = dev_id; struct mtk_ddp_comp *comp = &priv->ddp_comp; struct mtk_disp_aal *aal_data = comp_to_aal(comp); if (spin_trylock_irqsave(&g_aal_clock_lock, flags)) { if (atomic_read(&aal_data->is_clock_on) != 1) AALIRQ_LOG("clock is off\n"); else { disp_aal_on_end_of_frame(comp); ret = IRQ_HANDLED; } spin_unlock_irqrestore(&g_aal_clock_lock, flags); } AALIRQ_LOG("end\n"); return ret; } static int mtk_disp_aal_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_disp_aal *priv; enum mtk_ddp_comp_id comp_id; int ret, irq; #if defined(CONFIG_MTK_DRE30_SUPPORT) struct device_node *dre3_dev_node; struct platform_device *dre3_pdev; struct resource dre3_res; #endif DDPINFO("%s+\n", __func__); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_AAL); if ((int)comp_id < 0) { AALERR("Failed to identify by alias: %d\n", comp_id); return comp_id; } if (comp_id == DDP_COMPONENT_AAL0) g_aal_data = priv; if (comp_id == DDP_COMPONENT_AAL1) g_aal1_data = priv; atomic_set(&priv->dirty_frame_retrieved, 1); atomic_set(&priv->is_clock_on, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id, &mtk_disp_aal_funcs); if (ret) { AALERR("Failed to initialize component: %d\n", ret); return ret; } if (!default_comp && comp_id == DDP_COMPONENT_AAL0) default_comp = &priv->ddp_comp; if (!aal1_default_comp && comp_id == DDP_COMPONENT_AAL1) aal1_default_comp = &priv->ddp_comp; priv->data = of_device_get_match_data(dev); platform_set_drvdata(pdev, priv); ret = devm_request_irq(dev, irq, mtk_disp_aal_irq_handler, IRQF_TRIGGER_NONE | IRQF_SHARED, dev_name(dev), priv); if (ret) dev_err(dev, "devm_request_irq fail: %d\n", ret); pm_runtime_enable(dev); #if defined(CONFIG_MTK_DRE30_SUPPORT) do { dre3_dev_node = of_parse_phandle( pdev->dev.of_node, "aal_dre3", 0); if (dre3_dev_node) pr_notice("found dre3 aal node, it's another hw\n"); else break; dre3_pdev = of_find_device_by_node(dre3_dev_node); if (dre3_pdev) pr_notice("found dre3 aal device, it's another hw\n"); else break; of_node_put(dre3_dev_node); priv->dre3_hw.dev = &dre3_pdev->dev; priv->dre3_hw.va = of_iomap(dre3_pdev->dev.of_node, 0); if (!priv->dre3_hw.va) { pr_notice("cannot found allocate dre3 va!\n"); break; } ret = of_address_to_resource( dre3_pdev->dev.of_node, 0, &dre3_res); if (ret) { pr_notice("cannot found allocate dre3 resource!\n"); break; } priv->dre3_hw.pa = dre3_res.start; if (comp_id == DDP_COMPONENT_AAL0) { priv->dre3_hw.clk = of_clk_get_by_name( dre3_dev_node, "DRE3_AAL0"); } else if (comp_id == DDP_COMPONENT_AAL1) { priv->dre3_hw.clk = of_clk_get_by_name( dre3_dev_node, "DRE3_AAL1"); } if (IS_ERR(priv->dre3_hw.clk)) { pr_notice("fail @ dre3 clock. name:%s\n", "DRE3_AAL0"); break; } pr_notice("dre3 dev:%p va:%p pa:%pa", priv->dre3_hw.dev, priv->dre3_hw.va, &priv->dre3_hw.pa); } while (0); #endif ret = component_add(dev, &mtk_disp_aal_component_ops); if (ret) { dev_err(dev, "Failed to add component: %d\n", ret); pm_runtime_disable(dev); } #ifdef CONFIG_LEDS_BRIGHTNESS_CHANGED if (comp_id == DDP_COMPONENT_AAL0) mtk_leds_register_notifier(&leds_init_notifier); #endif aal_flip_wq = create_singlethread_workqueue("aal_flip_sram"); INIT_WORK(&g_aal_data->aal_flip_task, mtk_crtc_user_cmd_work); aal_refresh_wq = create_singlethread_workqueue("aal_refresh_trigger"); INIT_WORK(&g_aal_data->aal_refresh_task, mtk_disp_aal_refresh_trigger); AALFLOW_LOG("-\n"); return ret; } static int mtk_disp_aal_remove(struct platform_device *pdev) { struct mtk_disp_aal *priv = dev_get_drvdata(&pdev->dev); component_del(&pdev->dev, &mtk_disp_aal_component_ops); pm_runtime_disable(&pdev->dev); if (priv->dre3_hw.dev) pm_runtime_disable(priv->dre3_hw.dev); #ifdef CONFIG_LEDS_BRIGHTNESS_CHANGED if (priv->ddp_comp.id == DDP_COMPONENT_AAL0) mtk_leds_unregister_notifier(&leds_init_notifier); #endif return 0; } static const struct mtk_disp_aal_data mt6885_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1152, .aal_dre_hist_end = 4220, .aal_dre_gain_start = 4224, .aal_dre_gain_end = 6396, .bitShift = 13, }; static const struct mtk_disp_aal_data mt6873_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1536, .aal_dre_hist_end = 4604, .aal_dre_gain_start = 4608, .aal_dre_gain_end = 6780, .bitShift = 16, }; static const struct mtk_disp_aal_data mt6853_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1536, .aal_dre_hist_end = 4604, .aal_dre_gain_start = 4608, .aal_dre_gain_end = 6780, .bitShift = 16, }; static const struct mtk_disp_aal_data mt6877_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1536, .aal_dre_hist_end = 4604, .aal_dre_gain_start = 4608, .aal_dre_gain_end = 6780, .bitShift = 16, }; static const struct mtk_disp_aal_data mt6833_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1536, .aal_dre_hist_end = 4604, .aal_dre_gain_start = 4608, .aal_dre_gain_end = 6780, .bitShift = 16, }; static const struct mtk_disp_aal_data mt6781_aal_driver_data = { .support_shadow = false, .aal_dre_hist_start = 1536, .aal_dre_hist_end = 4604, .aal_dre_gain_start = 4608, .aal_dre_gain_end = 6780, .bitShift = 16, }; static const struct of_device_id mtk_disp_aal_driver_dt_match[] = { { .compatible = "mediatek,mt6885-disp-aal", .data = &mt6885_aal_driver_data}, { .compatible = "mediatek,mt6873-disp-aal", .data = &mt6873_aal_driver_data}, { .compatible = "mediatek,mt6853-disp-aal", .data = &mt6853_aal_driver_data}, { .compatible = "mediatek,mt6877-disp-aal", .data = &mt6877_aal_driver_data}, { .compatible = "mediatek,mt6833-disp-aal", .data = &mt6833_aal_driver_data}, { .compatible = "mediatek,mt6781-disp-aal", .data = &mt6781_aal_driver_data}, {}, }; MODULE_DEVICE_TABLE(of, mtk_disp_aal_driver_dt_match); struct platform_driver mtk_disp_aal_driver = { .probe = mtk_disp_aal_probe, .remove = mtk_disp_aal_remove, .driver = { .name = "mediatek-disp-aal", .owner = THIS_MODULE, .of_match_table = mtk_disp_aal_driver_dt_match, }, }; /* Legacy AAL_SUPPORT_KERNEL_API */ void disp_aal_set_lcm_type(unsigned int panel_type) { unsigned long flags; spin_lock_irqsave(&g_aal_hist_lock, flags); atomic_set(&g_aal_panel_type, panel_type); spin_unlock_irqrestore(&g_aal_hist_lock, flags); AALAPI_LOG("panel_type = %d", panel_type); } #define AAL_CONTROL_CMD(ID, CONTROL) (ID << 16 | CONTROL) void disp_aal_set_ess_level(int level) { unsigned long flags; int level_command = 0; spin_lock_irqsave(&g_aal_hist_lock, flags); g_aal_ess_level_cmd_id += 1; g_aal_ess_level_cmd_id = g_aal_ess_level_cmd_id % 64; level_command = AAL_CONTROL_CMD(g_aal_ess_level_cmd_id, level); g_aal_ess_level = level_command; spin_unlock_irqrestore(&g_aal_hist_lock, flags); disp_aal_refresh_by_kernel(); AALAPI_LOG("level = %d (cmd = 0x%x)", level, level_command); } void disp_aal_set_ess_en(int enable) { unsigned long flags; int enable_command = 0; int level_command = 0; spin_lock_irqsave(&g_aal_hist_lock, flags); g_aal_ess_en_cmd_id += 1; g_aal_ess_en_cmd_id = g_aal_ess_en_cmd_id % 64; enable_command = AAL_CONTROL_CMD(g_aal_ess_en_cmd_id, enable); g_aal_ess_en = enable_command; spin_unlock_irqrestore(&g_aal_hist_lock, flags); disp_aal_refresh_by_kernel(); AALAPI_LOG("en = %d (cmd = 0x%x) level = 0x%08x (cmd = 0x%x)", enable, enable_command, ESS_LEVEL_BY_CUSTOM_LIB, level_command); } void disp_aal_set_dre_en(int enable) { unsigned long flags; int enable_command = 0; spin_lock_irqsave(&g_aal_hist_lock, flags); g_aal_dre_en_cmd_id += 1; g_aal_dre_en_cmd_id = g_aal_dre_en_cmd_id % 64; enable_command = AAL_CONTROL_CMD(g_aal_dre_en_cmd_id, enable); g_aal_dre_en = enable_command; spin_unlock_irqrestore(&g_aal_hist_lock, flags); disp_aal_refresh_by_kernel(); AALAPI_LOG("en = %d (cmd = 0x%x)", enable, enable_command); } void disp_aal_debug(const char *opt) { pr_notice("[debug]: %s\n", opt); if (strncmp(opt, "setparam:", 9) == 0) { debug_skip_set_param = strncmp(opt + 9, "skip", 4) == 0; pr_notice("[debug] skip_set_param=%d\n", debug_skip_set_param); } else if (strncmp(opt, "dre3irq:", 8) == 0) { debug_skip_dre3_irq = strncmp(opt + 8, "skip", 4) == 0; pr_notice("[debug] skip_dre3_irq=%d\n", debug_skip_dre3_irq); } else if (strncmp(opt, "dre3algmode:", 12) == 0) { debug_bypass_alg_mode = strncmp(opt + 12, "bypass", 6) == 0; pr_notice("[debug] bypass_alg_mode=%d\n", debug_bypass_alg_mode); } else if (strncmp(opt, "dumpregirq", 10) == 0) { debug_dump_reg_irq = true; pr_notice("[debug] debug_dump_reg_irq=%d\n", debug_dump_reg_irq); } else if (strncmp(opt, "dumpdre3hist:", 13) == 0) { if (sscanf(opt + 13, "%d %d", &dump_blk_x, &dump_blk_y) == 2) pr_notice("[debug] dump_blk_x=%d dump_blk_y=%d\n", dump_blk_x, dump_blk_y); else pr_notice("[debug] dump_blk parse fail\n"); } else if (strncmp(opt, "first_br:", 9) == 0) { debug_skip_first_br = strncmp(opt + 9, "skip", 4) == 0; pr_notice("[debug] skip_first_br=%d\n", debug_skip_first_br); } else if (strncmp(opt, "flow_log:", 9) == 0) { debug_flow_log = strncmp(opt + 9, "1", 1) == 0; pr_notice("[debug] debug_flow_log=%d\n", debug_flow_log); } else if (strncmp(opt, "api_log:", 8) == 0) { debug_api_log = strncmp(opt + 8, "1", 1) == 0; pr_notice("[debug] debug_api_log=%d\n", debug_api_log); } else if (strncmp(opt, "write_cmdq_log:", 15) == 0) { debug_write_cmdq_log = strncmp(opt + 15, "1", 1) == 0; pr_notice("[debug] debug_write_cmdq_log=%d\n", debug_write_cmdq_log); } else if (strncmp(opt, "irq_log:", 8) == 0) { debug_irq_log = strncmp(opt + 8, "1", 1) == 0; pr_notice("[debug] debug_irq_log=%d\n", debug_irq_log); } else if (strncmp(opt, "dump_aal_hist:", 14) == 0) { debug_dump_aal_hist = strncmp(opt + 14, "1", 1) == 0; pr_notice("[debug] debug_dump_aal_hist=%d\n", debug_dump_aal_hist); } else if (strncmp(opt, "dump_input_param:", 17) == 0) { debug_dump_input_param = strncmp(opt + 17, "1", 1) == 0; pr_notice("[debug] debug_dump_input_param=%d\n", debug_dump_input_param); } else if (strncmp(opt, "set_ess_level:", 14) == 0) { int debug_ess_level; if (sscanf(opt + 14, "%d", &debug_ess_level) == 1) { pr_notice("[debug] ess_level=%d\n", debug_ess_level); disp_aal_set_ess_level(debug_ess_level); } else pr_notice("[debug] set_ess_level failed\n"); } else if (strncmp(opt, "set_ess_en:", 11) == 0) { bool debug_ess_en; debug_ess_en = !strncmp(opt + 11, "1", 1); pr_notice("[debug] debug_ess_en=%d\n", debug_ess_en); disp_aal_set_ess_en(debug_ess_en); } else if (strncmp(opt, "set_dre_en:", 11) == 0) { bool debug_dre_en; debug_dre_en = !strncmp(opt + 11, "1", 1); pr_notice("[debug] debug_dre_en=%d\n", debug_dre_en); disp_aal_set_dre_en(debug_dre_en); #ifdef CONFIG_MTK_DRE30_SUPPORT } else if (strncmp(opt, "aal_sram_method:", 16) == 0) { bool aal_align_eof; aal_align_eof = !strncmp(opt + 11, "0", 1); aal_sram_method = aal_align_eof ? AAL_SRAM_EOF : AAL_SRAM_SOF; pr_notice("[debug] aal_sram_method=%d\n", aal_sram_method); #endif } else if (strncmp(opt, "debugdump:", 10) == 0) { pr_notice("[debug] skip_set_param=%d\n", debug_skip_set_param); pr_notice("[debug] skip_dre3_irq=%d\n", debug_skip_dre3_irq); pr_notice("[debug] bypass_alg_mode=%d\n", debug_bypass_alg_mode); pr_notice("[debug] debug_dump_reg_irq=%d\n", debug_dump_reg_irq); pr_notice("[debug] dump_blk_x=%d dump_blk_y=%d\n", dump_blk_x, dump_blk_y); pr_notice("[debug] skip_first_br=%d\n", debug_skip_first_br); pr_notice("[debug] debug_flow_log=%d\n", debug_flow_log); pr_notice("[debug] debug_api_log=%d\n", debug_api_log); pr_notice("[debug] debug_write_cmdq_log=%d\n", debug_write_cmdq_log); pr_notice("[debug] debug_irq_log=%d\n", debug_irq_log); pr_notice("[debug] debug_dump_aal_hist=%d\n", debug_dump_aal_hist); pr_notice("[debug] debug_dump_input_param=%d\n", debug_dump_input_param); pr_notice("[debug] debug_ess_level=%d\n", g_aal_ess_level); pr_notice("[debug] debug_ess_en=%d\n", g_aal_ess_en); pr_notice("[debug] debug_dre_en=%d\n", g_aal_dre_en); } } void disp_aal_set_bypass(struct drm_crtc *crtc, int bypass) { int ret; if (atomic_read(&g_aal_force_relay) == bypass) return; ret = mtk_crtc_user_cmd(crtc, default_comp, BYPASS_AAL, &bypass); if (default_comp->mtk_crtc->is_dual_pipe) ret = mtk_crtc_user_cmd(crtc, aal1_default_comp, BYPASS_AAL, &bypass); DDPFUNC("ret = %d", ret); }