6db4831e98
Android 14
3200 lines
94 KiB
C
3200 lines
94 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <drm/drmP.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/component.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/soc/mediatek/mtk-cmdq.h>
|
|
#include <linux/module.h>
|
|
#include <linux/workqueue.h>
|
|
|
|
//For 120Hz rotation issue
|
|
#include <linux/time.h>
|
|
|
|
#ifdef CONFIG_MTK_LEDS
|
|
#include <mtk_leds_drv.h>
|
|
#ifdef CONFIG_LEDS_MTK_DISP
|
|
#ifdef CONFIG_MTK_AAL_SUPPORT
|
|
#define CONFIG_LEDS_BRIGHTNESS_CHANGED
|
|
#endif
|
|
#include <leds-mtk-disp.h>
|
|
#elif defined CONFIG_LEDS_MTK_PWM
|
|
#ifdef CONFIG_MTK_AAL_SUPPORT
|
|
#define CONFIG_LEDS_BRIGHTNESS_CHANGED
|
|
#endif
|
|
#include <leds-mtk-pwm.h>
|
|
#elif defined CONFIG_LEDS_MTK_I2C
|
|
#ifdef CONFIG_MTK_AAL_SUPPORT
|
|
#define CONFIG_LEDS_BRIGHTNESS_CHANGED
|
|
#endif
|
|
#include <leds-mtk-i2c.h>
|
|
#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);
|
|
}
|