blob: 1b3f6a8b515bed909a991d532b4b7958d03c1a19 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Samsung Electronics Co., Ltd.
* Gwanghui Lee <gwanghui.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __COPR_H__
#define __COPR_H__
#include "panel.h"
#include "timenval.h"
#include <linux/ktime.h>
#include <linux/wait.h>
#define CONFIG_SUPPORT_COPR_AVG
#define COPR_V1_SPI_RX_SIZE (8)
#define COPR_V1_DSI_RX_SIZE (10)
#define COPR_V2_SPI_RX_SIZE (9)
#define COPR_V2_DSI_RX_SIZE (12)
#define COPR_V3_SPI_RX_SIZE (41)
#define COPR_V3_DSI_RX_SIZE (41)
enum {
COPR_SET_SEQ,
/* if necessary, add new seq */
COPR_CLR_CNT_ON_SEQ,
COPR_CLR_CNT_OFF_SEQ,
COPR_SPI_GET_SEQ,
COPR_DSI_GET_SEQ,
MAX_COPR_SEQ,
};
enum {
COPR_MAPTBL,
/* if necessary, add new maptbl */
MAX_COPR_MAPTBL,
};
enum COPR_STATE {
COPR_UNINITIALIZED,
COPR_REG_ON,
COPR_REG_OFF,
MAX_COPR_REG_STATE,
};
enum COPR_VER {
COPR_VER_0,
COPR_VER_1,
COPR_VER_2,
COPR_VER_3,
MAX_COPR_VER,
};
struct copr_options {
u8 thread_on; /* copr_thread 0: off, 1: on */
u8 check_avg; /* check_avg when lcd on/off 0: not update avg, 1 : updateavg */
};
struct copr_reg_info {
const char *name;
u32 offset;
};
struct copr_ergb {
u16 copr_er;
u16 copr_eg;
u16 copr_eb;
};
struct copr_roi {
u32 roi_xs;
u32 roi_ys;
u32 roi_xe;
u32 roi_ye;
};
struct copr_reg_v0 {
u32 copr_gamma; /* 0:GAMMA_1, 1:GAMMA_2.2 */
u32 copr_en;
u32 copr_er;
u32 copr_eg;
u32 copr_eb;
u32 roi_on;
u32 roi_xs;
u32 roi_ys;
u32 roi_xe;
u32 roi_ye;
};
struct copr_reg_v1 {
u32 cnt_re;
u32 copr_gamma; /* 0:GAMMA_1, 1:GAMMA_2.2 */
u32 copr_en;
u32 copr_er;
u32 copr_eg;
u32 copr_eb;
u32 max_cnt;
u32 roi_on;
u32 roi_xs;
u32 roi_ys;
u32 roi_xe;
u32 roi_ye;
};
struct copr_reg_v2 {
u32 cnt_re;
u32 copr_ilc;
u32 copr_gamma; /* 0:GAMMA_1, 1:GAMMA_2.2 */
u32 copr_en;
u32 copr_er;
u32 copr_eg;
u32 copr_eb;
u32 copr_erc;
u32 copr_egc;
u32 copr_ebc;
u32 max_cnt;
u32 roi_on;
u32 roi_xs;
u32 roi_ys;
u32 roi_xe;
u32 roi_ye;
};
struct copr_reg_v3 {
u32 copr_mask;
u32 cnt_re;
u32 copr_ilc;
u32 copr_gamma; /* 0:GAMMA_1, 1:GAMMA_2.2 */
u32 copr_en;
u32 copr_er;
u32 copr_eg;
u32 copr_eb;
u32 copr_erc;
u32 copr_egc;
u32 copr_ebc;
u32 max_cnt;
u32 roi_on;
struct copr_roi roi[6];
};
struct copr_reg {
union {
struct copr_reg_v0 v0;
struct copr_reg_v1 v1;
struct copr_reg_v2 v2;
struct copr_reg_v3 v3;
};
};
struct copr_properties {
bool support;
u32 version;
u32 enable;
u32 state;
struct copr_reg reg;
struct copr_options options;
u32 copr_ready;
u32 cur_cnt;
u32 cur_copr;
u32 avg_copr;
u32 s_cur_cnt;
u32 s_avg_copr;
u32 comp_copr;
u32 copr_roi_r[5][3];
struct copr_roi roi[32];
int nr_roi;
};
struct copr_wq {
wait_queue_head_t wait;
atomic_t count;
struct task_struct *thread;
};
struct copr_info {
struct device *dev;
struct class *class;
struct mutex lock;
atomic_t stop;
struct copr_wq wq;
struct timenval res;
struct copr_properties props;
struct notifier_block fb_notif;
struct maptbl *maptbl;
u32 nr_maptbl;
struct seqinfo *seqtbl;
u32 nr_seqtbl;
};
struct panel_copr_data {
struct copr_reg reg;
u32 version;
struct copr_options options;
struct seqinfo *seqtbl;
u32 nr_seqtbl;
struct maptbl *maptbl;
u32 nr_maptbl;
struct copr_roi roi[32];
int nr_roi;
};
static inline int get_copr_ver(struct copr_info *copr)
{
return copr->props.version;
}
static inline void SET_COPR_REG_GAMMA(struct copr_info *copr, bool copr_gamma)
{
if (copr->props.version == COPR_VER_0)
copr->props.reg.v0.copr_gamma = copr_gamma;
else if (copr->props.version == COPR_VER_1)
copr->props.reg.v1.copr_gamma = copr_gamma;
else if (copr->props.version == COPR_VER_2)
copr->props.reg.v2.copr_gamma = copr_gamma;
else if (copr->props.version == COPR_VER_3)
copr->props.reg.v3.copr_gamma = copr_gamma;
else
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
}
static inline void SET_COPR_REG_E(struct copr_info *copr, int r, int g, int b)
{
if (copr->props.version == COPR_VER_0) {
copr->props.reg.v0.copr_er = r;
copr->props.reg.v0.copr_eg = g;
copr->props.reg.v0.copr_eb = b;
} else if (copr->props.version == COPR_VER_1) {
copr->props.reg.v1.copr_er = r;
copr->props.reg.v1.copr_eg = g;
copr->props.reg.v1.copr_eb = b;
} else if (copr->props.version == COPR_VER_2) {
copr->props.reg.v2.copr_er = r;
copr->props.reg.v2.copr_eg = g;
copr->props.reg.v2.copr_eb = b;
} else if (copr->props.version == COPR_VER_3) {
copr->props.reg.v3.copr_er = r;
copr->props.reg.v3.copr_eg = g;
copr->props.reg.v3.copr_eb = b;
} else {
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
}
}
static inline void SET_COPR_REG_EC(struct copr_info *copr, int r, int g, int b)
{
if (copr->props.version == COPR_VER_0) {
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
} else if (copr->props.version == COPR_VER_1) {
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
} else if (copr->props.version == COPR_VER_2) {
copr->props.reg.v2.copr_erc = r;
copr->props.reg.v2.copr_egc = g;
copr->props.reg.v2.copr_ebc = b;
} else if (copr->props.version == COPR_VER_3) {
copr->props.reg.v3.copr_erc = r;
copr->props.reg.v3.copr_egc = g;
copr->props.reg.v3.copr_ebc = b;
} else {
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
}
}
static inline void SET_COPR_REG_CNT_RE(struct copr_info *copr, int cnt_re)
{
if (copr->props.version == COPR_VER_0)
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
else if (copr->props.version == COPR_VER_1)
copr->props.reg.v1.cnt_re = cnt_re;
else if (copr->props.version == COPR_VER_2)
copr->props.reg.v2.cnt_re = cnt_re;
else if (copr->props.version == COPR_VER_3)
copr->props.reg.v3.cnt_re = cnt_re;
else
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
}
static inline void SET_COPR_REG_ROI(struct copr_info *copr, struct copr_roi *roi, int nr_roi)
{
struct copr_properties *props = &copr->props;
int i;
if (copr->props.version == COPR_VER_2) {
if (roi == NULL) {
props->reg.v2.roi_xs = 0;
props->reg.v2.roi_ys = 0;
props->reg.v2.roi_xe = 0;
props->reg.v2.roi_ye = 0;
props->reg.v2.roi_on = 0;
} else {
props->reg.v2.roi_xs = roi[0].roi_xs;
props->reg.v2.roi_ys = roi[0].roi_ys;
props->reg.v2.roi_xe = roi[0].roi_xe;
props->reg.v2.roi_ye = roi[0].roi_ye;
props->reg.v2.roi_on = true;
}
} else if (copr->props.version == COPR_VER_3) {
if (roi == NULL) {
props->reg.v3.roi_on = 0;
memset(props->reg.v3.roi, 0, sizeof(props->reg.v3.roi));
} else {
props->reg.v3.roi_on = 0;
for (i = 0; i < min_t(int, ARRAY_SIZE(props->reg.v3.roi), nr_roi); i++) {
props->reg.v3.roi[i].roi_xs = roi[i].roi_xs;
props->reg.v3.roi[i].roi_ys = roi[i].roi_ys;
props->reg.v3.roi[i].roi_xe = roi[i].roi_xe;
props->reg.v3.roi[i].roi_ye = roi[i].roi_ye;
props->reg.v3.roi_on |= 0x1 << i;
}
}
}
}
static inline int get_copr_reg_copr_en(struct copr_info *copr)
{
int copr_en = COPR_REG_OFF;
if (copr->props.version == COPR_VER_0)
copr_en = copr->props.reg.v0.copr_en;
else if (copr->props.version == COPR_VER_1)
copr_en = copr->props.reg.v1.copr_en;
else if (copr->props.version == COPR_VER_2)
copr_en = copr->props.reg.v2.copr_en;
else if (copr->props.version == COPR_VER_3)
copr_en = copr->props.reg.v3.copr_en;
else
pr_warn("%s unsupprted in ver%d\n",
__func__, copr->props.version);
return copr_en;
}
#ifdef CONFIG_EXYNOS_DECON_LCD_COPR
bool copr_is_enabled(struct copr_info *copr);
int copr_enable(struct copr_info *copr);
int copr_disable(struct copr_info *copr);
int copr_update_start(struct copr_info *copr, int count);
int copr_update_average(struct copr_info *copr);
int copr_get_value(struct copr_info *copr);
//int copr_get_average(struct copr_info *, int *, int *);
int copr_get_average_and_clear(struct copr_info *copr);
int copr_roi_set_value(struct copr_info *copr, struct copr_roi *roi, int size);
int copr_roi_get_value(struct copr_info *copr, struct copr_roi *roi, int size, u32 *out);
int copr_probe(struct panel_device *panel, struct panel_copr_data *copr_data);
int copr_res_update(struct copr_info *copr, int index, int cur_value, struct timespec cur_ts);
int get_copr_reg_size(int version);
const char *get_copr_reg_name(int version, int index);
int get_copr_reg_offset(int version, int index);
u32 *get_copr_reg_ptr(struct copr_reg *reg, int version, int index);
int find_copr_reg_by_name(int version, char *s);
ssize_t copr_reg_show(struct copr_info *copr, char *buf);
int copr_reg_store(struct copr_info *copr, int index, u32 value);
#else
static inline bool copr_is_enabled(struct copr_info *copr) { return 0; }
static inline int copr_enable(struct copr_info *copr) { return 0; }
static inline int copr_disable(struct copr_info *copr) { return 0; }
static inline int copr_update_start(struct copr_info *copr, int count) { return 0; }
static inline int copr_update_average(struct copr_info *copr) { return 0; }
static inline int copr_get_value(struct copr_info *copr) { return 0; }
static inline int copr_get_average_and_clear(struct copr_info *copr) { return 0; }
static inline int copr_roi_set_value(struct copr_info *copr, struct copr_roi *roi, int size) { return 0; }
static inline int copr_roi_get_value(struct copr_info *copr, struct copr_roi *roi, int size, u32 *out) { return 0; }
static inline int copr_probe(struct panel_device *panel, struct panel_copr_data *copr_data) { return 0; }
static inline int copr_res_update(struct copr_info *copr, int index, int cur_value, struct timespec cur_ts) { return 0; }
static inline int get_copr_reg_size(int version) { return 0; }
static inline const char *get_copr_reg_name(int version, int index) { return NULL; }
static inline int get_copr_reg_offset(int version, int index) { return 0; }
static inline u32 *get_copr_reg_ptr(struct copr_reg *reg, int version, int index) { return NULL; }
static inline int find_copr_reg_by_name(int version, char *s) { return -EINVAL; }
static inline ssize_t copr_reg_show(struct copr_info *copr, char *buf) { return 0; }
static inline int copr_reg_store(struct copr_info *copr, int index, u32 value) { return 0; }
#endif
#endif /* __COPR_H__ */