mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Merge "Merge Amlogic mainline partially." into odroidg12-4.9.y-android
This commit is contained in:
@@ -14370,6 +14370,7 @@ F: drivers/amlogic/media/vout/vout_serve/vout2_notify.c
|
||||
F: drivers/amlogic/media/vout/vout_serve/vout2_serve.c
|
||||
F: drivers/amlogic/media/vout/vout_serve/vout_func.c
|
||||
F: drivers/amlogic/media/vout/vout_serve/vout_func.h
|
||||
F: drivers/amlogic/media/vout/vout_serve/vout_reg.h
|
||||
|
||||
AMLOGIC GPIO IRQ
|
||||
M: Xingyu Chen <xingyu.chen@amlogic.com>
|
||||
@@ -14759,6 +14760,7 @@ F: arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi
|
||||
AMLOGIC BACKLIGHT LDIM DRIVER
|
||||
M: Evoke Zhang <evoke.zhang@amlogic.com>
|
||||
F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_spi.c
|
||||
F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c
|
||||
|
||||
AMLOGIC CAMERA DRIVER
|
||||
M: Guosong Zhou <guosong.zhou@amlogic.com>
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
DEBUGFS_CREATE_NODE(atvdemod_isr_en, 0640, dentry, bool)\
|
||||
DEBUGFS_CREATE_NODE(atv_audio_overmodulated_cnt, 0640, dentry, u32)\
|
||||
DEBUGFS_CREATE_NODE(support_secam_l, 0640, dentry, bool)\
|
||||
DEBUGFS_CREATE_NODE(atvdemod_horiz_freq_det_en, 0640, dentry, bool)\
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,8 +44,10 @@
|
||||
#include "atvdemod_func.h"
|
||||
#include "atvauddemod_func.h"
|
||||
|
||||
|
||||
#define AMLATVDEMOD_VER "V2.13"
|
||||
/********************************CODE CHANGE LIST*****************************/
|
||||
/* Date --- Version --- Note *************************************************/
|
||||
/* 2019/11/05 --- V2.15 --- Add dynamic monitoring line frequency deviation. */
|
||||
#define AMLATVDEMOD_VER "V2.15"
|
||||
|
||||
struct aml_atvdemod_device *amlatvdemod_devp;
|
||||
|
||||
@@ -358,7 +360,7 @@ static ssize_t aml_atvdemod_store(struct class *class,
|
||||
int blk = 0, reg = 0;
|
||||
|
||||
for (blk = 0; blk <= APB_BLOCK_ADDR_TOP; ++blk) {
|
||||
for (reg = 0; reg <= 0x40; ++reg) {
|
||||
for (reg = 0; reg < 0x40; ++reg) {
|
||||
val = atv_dmd_rd_long(blk, reg);
|
||||
pr_err("[0x%04x] = 0x%x.\n",
|
||||
(blk << 8) + (reg << 2), val);
|
||||
|
||||
@@ -37,6 +37,7 @@ bool audio_thd_en;
|
||||
bool atvdemod_det_nonstd_en;
|
||||
bool atvaudio_det_outputmode_en = true;
|
||||
bool audio_carrier_offset_det_en;
|
||||
bool atvdemod_horiz_freq_det_en = true;
|
||||
|
||||
unsigned int atvdemod_timer_delay = 100; /* 1s */
|
||||
unsigned int atvdemod_timer_delay2 = 10; /* 100ms */
|
||||
@@ -87,6 +88,9 @@ static void atv_demod_monitor_do_work(struct work_struct *work)
|
||||
|
||||
if (atvdemod_det_nonstd_en)
|
||||
atv_dmd_non_std_set(true);
|
||||
|
||||
if (atvdemod_horiz_freq_det_en)
|
||||
atvdemod_horiz_freq_detection();
|
||||
}
|
||||
|
||||
static void atv_demod_monitor_timer_handler(unsigned long arg)
|
||||
|
||||
@@ -129,6 +129,11 @@ int aml_atvdemod_get_btsc_sap_mode(void)
|
||||
return btsc_sap_mode;
|
||||
}
|
||||
|
||||
static bool atvdemod_check_exited(struct atv_demod_priv *priv)
|
||||
{
|
||||
return (priv->state != ATVDEMOD_STATE_WORK);
|
||||
}
|
||||
|
||||
int atv_demod_enter_mode(struct dvb_frontend *fe)
|
||||
{
|
||||
int err_code = 0;
|
||||
@@ -532,9 +537,16 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe,
|
||||
unsigned int broad_std = 0;
|
||||
unsigned int audio = 0;
|
||||
|
||||
*video_fmt = 0;
|
||||
*audio_fmt = 0;
|
||||
*soundsys = 0;
|
||||
|
||||
if (auto_search_std & AUTO_DETECT_COLOR) {
|
||||
for (i = 0; i < try_vfmt_cnt; i++) {
|
||||
|
||||
if (atvdemod_check_exited(priv))
|
||||
return;
|
||||
|
||||
/* SECAM-L/L' */
|
||||
if ((p->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))
|
||||
&& (p->std & V4L2_COLOR_STD_SECAM)) {
|
||||
@@ -719,6 +731,9 @@ static void atvdemod_fe_try_signal(struct v4l2_frontend *v4l2_fe,
|
||||
|
||||
*lock = false;
|
||||
do {
|
||||
if (atvdemod_check_exited(priv))
|
||||
break;
|
||||
|
||||
if (tuner_id == AM_TUNER_MXL661) {
|
||||
usleep_range(30 * 1000, 30 * 1000 + 100);
|
||||
} else if (tuner_id == AM_TUNER_R840 ||
|
||||
@@ -844,6 +859,9 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq,
|
||||
|
||||
set_freq = p->frequency;
|
||||
while (abs(afc) > AFC_BEST_LOCK) {
|
||||
if (atvdemod_check_exited(priv))
|
||||
return -1;
|
||||
|
||||
if (tuner_id == AM_TUNER_MXL661)
|
||||
usleep_range(30 * 1000, 30 * 1000 + 100);
|
||||
else
|
||||
@@ -1118,13 +1136,15 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
v4l2_std_id std_bk = 0;
|
||||
unsigned int audio = 0;
|
||||
unsigned int soundsys = 0;
|
||||
int double_check_cnt = 1;
|
||||
/* int double_check_cnt = 1; */
|
||||
int auto_search_std = 0;
|
||||
int search_count = 0;
|
||||
/* bool try_secam = false; */
|
||||
int ret = -1;
|
||||
unsigned int tuner_id = 0;
|
||||
int priv_cfg = 0;
|
||||
int exit_status = 0;
|
||||
char *exit_str = "";
|
||||
|
||||
if (unlikely(!fe || !p ||
|
||||
!fe->ops.tuner_ops.get_status ||
|
||||
@@ -1137,7 +1157,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
}
|
||||
|
||||
priv = fe->analog_demod_priv;
|
||||
if (priv->state != ATVDEMOD_STATE_WORK) {
|
||||
if (atvdemod_check_exited(priv)) {
|
||||
pr_err("[%s] ATV state is not work.\n", __func__);
|
||||
return V4L2_SEARCH_INVALID;
|
||||
}
|
||||
@@ -1217,6 +1237,11 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
while (minafcfreq <= p->frequency &&
|
||||
p->frequency <= maxafcfreq) {
|
||||
|
||||
if (atvdemod_check_exited(priv)) {
|
||||
exit_status = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
pr_dbg("[%s] [%d] is processing, [min=%d, max=%d].\n",
|
||||
__func__, p->frequency, minafcfreq, maxafcfreq);
|
||||
|
||||
@@ -1250,6 +1275,9 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
p->soundsys = soundsys;
|
||||
std_bk = 0;
|
||||
audio = 0;
|
||||
} else {
|
||||
exit_status = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* sync param */
|
||||
@@ -1265,9 +1293,12 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
(uint32_t) p->std, p->frequency);
|
||||
|
||||
/* when manual search, just search current freq */
|
||||
if (p->flag == ANALOG_FLAG_MANUL_SCAN)
|
||||
if (p->flag == ANALOG_FLAG_MANUL_SCAN) {
|
||||
exit_status = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_CHECK_44_25MHZ
|
||||
if (p->frequency >= 44200000 &&
|
||||
p->frequency <= 44300000 &&
|
||||
double_check_cnt) {
|
||||
@@ -1278,10 +1309,22 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
|
||||
p->frequency += afc_step * ((search_count % 2) ?
|
||||
-search_count : search_count);
|
||||
}
|
||||
#else
|
||||
++search_count;
|
||||
p->frequency += afc_step * ((search_count % 2) ?
|
||||
-search_count : search_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
pr_dbg("[%s] [%d] over of range [min=%d, max=%d], search failed.\n",
|
||||
__func__, p->frequency, minafcfreq, maxafcfreq);
|
||||
if (!exit_status)
|
||||
exit_str = "over of range, search failed";
|
||||
else if (exit_status == 1)
|
||||
exit_str = "search exited";
|
||||
else
|
||||
exit_str = "search failed";
|
||||
|
||||
pr_dbg("[%s] [%d] %s.\n", __func__, p->frequency, exit_str);
|
||||
|
||||
p->frequency = set_freq;
|
||||
|
||||
priv_cfg = AML_ATVDEMOD_UNSCAN_MODE;
|
||||
|
||||
@@ -872,7 +872,7 @@ void set_mono_dk(void)
|
||||
{
|
||||
int aa;
|
||||
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_DK);
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_DK | (3 << 4));
|
||||
|
||||
set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65);
|
||||
set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65);
|
||||
@@ -889,7 +889,7 @@ void set_mono_i(void)
|
||||
{
|
||||
int aa;
|
||||
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_I);
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_I | (3 << 4));
|
||||
|
||||
set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65);
|
||||
set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65);
|
||||
@@ -906,7 +906,7 @@ void set_mono_bg(void)
|
||||
{
|
||||
int aa;
|
||||
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_BG);
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_BG | (3 << 4));
|
||||
|
||||
set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65);
|
||||
set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65);
|
||||
@@ -923,7 +923,7 @@ void set_mono_l(void)
|
||||
{
|
||||
int aa;
|
||||
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_L);
|
||||
adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_L | (3 << 4));
|
||||
|
||||
set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65);
|
||||
set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65);
|
||||
@@ -1586,7 +1586,7 @@ void set_outputmode(uint32_t standard, uint32_t outmode)
|
||||
case AUDIO_STANDARD_MONO_I:
|
||||
case AUDIO_STANDARD_MONO_L:
|
||||
/* for FM MONO system to detection nicam status */
|
||||
if (!aud_reinit && get_nicam_lock_status()) {
|
||||
if (!aud_mono_only && !aud_reinit && get_nicam_lock_status()) {
|
||||
if (standard == AUDIO_STANDARD_MONO_I)
|
||||
aud_std = AUDIO_STANDARD_NICAM_I;
|
||||
else if (standard == AUDIO_STANDARD_MONO_L)
|
||||
|
||||
@@ -260,7 +260,7 @@ void atv_dmd_misc(void)
|
||||
/* for audio non-standard signal, first set gain 0 to mute,
|
||||
* then unmute in detection.
|
||||
*/
|
||||
if (audio_atv_ov || atv_audio_overmodulated_en)
|
||||
if ((audio_atv_ov || atv_audio_overmodulated_en) && non_std_en == 0)
|
||||
aml_audio_valume_gain_set(0);
|
||||
else
|
||||
aml_audio_valume_gain_set(audio_gain_val);
|
||||
@@ -287,8 +287,8 @@ void atv_dmd_misc(void)
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc020901);
|
||||
} else {
|
||||
if (tuner_id == AM_TUNER_R840 || tuner_id == AM_TUNER_R842
|
||||
|| non_std_en == 4) {
|
||||
if ((tuner_id == AM_TUNER_R840 || tuner_id == AM_TUNER_R842) &&
|
||||
non_std_en == 4) {
|
||||
/* Reduce target amplitude and response speed */
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08,
|
||||
0x17070200);
|
||||
@@ -338,45 +338,67 @@ void atv_dmd_misc(void)
|
||||
pr_dbg("%s done.\n", __func__);
|
||||
}
|
||||
|
||||
void atv_dmd_ring_filter(bool on)
|
||||
void atv_dmd_ring_filter(bool on, int std)
|
||||
{
|
||||
unsigned long filter_status = 0;
|
||||
int i = 0;
|
||||
int filter = 0;
|
||||
unsigned long status = 0;
|
||||
unsigned long data = 0;
|
||||
const unsigned int reg_addr[10] = {
|
||||
0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34,
|
||||
};
|
||||
const unsigned int peak_filter[][10] = {
|
||||
/* default */
|
||||
{ 0x8423F6, 0xFF86A967, 0x37FE45, 0xFF86A967, 0x3C223B,
|
||||
0x8423F6, 0xFF86A967, 0x37FE45, 0xFF86A967, 0x3C223B },
|
||||
/* ntsc-m */
|
||||
{ 0x8274bf, 0x1d175c, 0x2aa526, 0x1d175c, 0x2d19e4,
|
||||
0x8274bf, 0x1d175c, 0x2aa526, 0x1d175c, 0x2d19e4 },
|
||||
/* pal-i */
|
||||
{ 0x94d888, 0x5a39fb, 0xd8ebb, 0x5a39fb, 0x226744,
|
||||
0x94d888, 0x5a39fb, 0xd8ebb, 0x5a39fb, 0x226744 }
|
||||
};
|
||||
|
||||
if (!is_meson_tl1_cpu() && !is_meson_tm2_cpu())
|
||||
return;
|
||||
|
||||
filter_status = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c);
|
||||
if (((filter_status & 0x01) && on) || (!(filter_status & 0x01) && !on))
|
||||
if (on) {
|
||||
if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) {
|
||||
filter = 2;
|
||||
} else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) {
|
||||
filter = 2;
|
||||
} else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) {
|
||||
filter = 2;
|
||||
} else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M ||
|
||||
std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) {
|
||||
filter = 1;
|
||||
} else {
|
||||
filter = 0;
|
||||
on = false;
|
||||
}
|
||||
} else {
|
||||
filter = 0;
|
||||
}
|
||||
|
||||
status = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c);
|
||||
data = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, reg_addr[0]);
|
||||
if ((data == peak_filter[filter][0]) && on && (status & 0x01))
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8274bf);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0x1d175c);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x2aa526);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0x1d175c);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x2d19e4);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8274bf);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0x1d175c);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x2aa526);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0x1d175c);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x2d19e4);
|
||||
if (!on && !(status & 0x01))
|
||||
return;
|
||||
|
||||
/* disable filter */
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0);
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL,
|
||||
reg_addr[i], peak_filter[filter][i]);
|
||||
}
|
||||
|
||||
if (on) {
|
||||
/* enable filter */
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x1);
|
||||
} else {
|
||||
/* default value */
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8423F6);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0xFF86A967);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x37FE45);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0xFF86A967);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x3C223B);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8423F6);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0xFF86A967);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x37FE45);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0xFF86A967);
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x3C223B);
|
||||
|
||||
/* disable filter */
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0);
|
||||
}
|
||||
|
||||
pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on);
|
||||
@@ -2021,12 +2043,10 @@ int atvdemod_init(struct atv_demod_priv *priv)
|
||||
if (!priv->scanning || non_std_en)
|
||||
atv_dmd_misc();
|
||||
|
||||
if (!priv->scanning &&
|
||||
(broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M ||
|
||||
broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC))
|
||||
atv_dmd_ring_filter(true);
|
||||
if (!priv->scanning)
|
||||
atv_dmd_ring_filter(true, broad_std);
|
||||
else
|
||||
atv_dmd_ring_filter(false);
|
||||
atv_dmd_ring_filter(false, broad_std);
|
||||
|
||||
atv_dmd_soft_reset();
|
||||
|
||||
@@ -2525,3 +2545,45 @@ void aml_audio_overmodulation(int enable)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void atvdemod_horiz_freq_detection(void)
|
||||
{
|
||||
unsigned long data = 0;
|
||||
int field_lock = 0;
|
||||
int line_lock = 0;
|
||||
int line = 0;
|
||||
int std_line = 0;
|
||||
unsigned long horiz_freq = 0;
|
||||
|
||||
data = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x4c);
|
||||
field_lock = data & 0x4; /* bit2 */
|
||||
line_lock = data & 0x10; /* bit4 */
|
||||
line = (data >> 6) & 0x3ff; /* bit[15-6] */
|
||||
|
||||
switch (broad_std) {
|
||||
case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC:
|
||||
case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M:
|
||||
std_line = 525;
|
||||
break;
|
||||
default:
|
||||
std_line = 625;
|
||||
break;
|
||||
}
|
||||
|
||||
if (field_lock == 0 && line_lock == 0) {
|
||||
/* bit[31-8] */
|
||||
data = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x10);
|
||||
|
||||
/* fh +/- (200 / 0.23841858) */
|
||||
if ((line - std_line) > 7)
|
||||
horiz_freq = freq_hz_cvrt + 0x347;
|
||||
else if ((line - std_line) < -7)
|
||||
horiz_freq = freq_hz_cvrt - 0x347;
|
||||
else
|
||||
horiz_freq = freq_hz_cvrt;
|
||||
|
||||
data = (horiz_freq << 8) | (data & 0xff);
|
||||
|
||||
atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x10, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ extern unsigned int aud_std;
|
||||
extern unsigned int aud_mode;
|
||||
extern bool audio_thd_en;
|
||||
extern bool aud_reinit;
|
||||
extern bool aud_mono_only;
|
||||
extern bool atv_audio_overmodulated_en;
|
||||
extern unsigned int non_std_en;
|
||||
|
||||
@@ -70,7 +71,7 @@ extern void read_version_register(void);
|
||||
extern void check_communication_interface(void);
|
||||
extern void power_on_receiver(void);
|
||||
extern void atv_dmd_misc(void);
|
||||
extern void atv_dmd_ring_filter(bool on);
|
||||
void atv_dmd_ring_filter(bool on, int std);
|
||||
extern void configure_receiver(int Broadcast_Standard,
|
||||
unsigned int Tuner_IF_Frequency,
|
||||
int Tuner_Input_IF_inverted, int GDE_Curve,
|
||||
@@ -214,6 +215,7 @@ extern void set_atvdemod_scan_mode(int val);
|
||||
extern int atvauddemod_init(void);
|
||||
extern int amlfmt_aud_standard(int broad_std);
|
||||
extern void atvauddemod_set_outputmode(void);
|
||||
void atvdemod_horiz_freq_detection(void);
|
||||
|
||||
/*from amldemod/amlfrontend.c*/
|
||||
extern int vdac_enable_check_dtv(void);
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
#include "meson_fb.h"
|
||||
#endif
|
||||
#include "meson_drv.h"
|
||||
#include "meson_vpu.h"
|
||||
#include "meson_vpu_pipeline.h"
|
||||
|
||||
|
||||
#define DRIVER_NAME "meson"
|
||||
#define DRIVER_DESC "Amlogic Meson DRM driver"
|
||||
|
||||
@@ -114,23 +114,313 @@ static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
|
||||
priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
|
||||
}
|
||||
|
||||
static void am_meson_load(struct drm_device *dev)
|
||||
{
|
||||
#if 0
|
||||
struct meson_drm *priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = priv->crtc;
|
||||
int pipe = drm_crtc_index(crtc);
|
||||
struct am_meson_logo logo;
|
||||
core_param(fb_width, logo.width, uint, 0644);
|
||||
core_param(fb_height, logo.height, uint, 0644);
|
||||
core_param(display_bpp, logo.bpp, uint, 0644);
|
||||
core_param(outputmode, logo.outputmode_t, charp, 0644);
|
||||
|
||||
if (priv->crtc_funcs[pipe] &&
|
||||
priv->crtc_funcs[pipe]->loader_protect)
|
||||
priv->crtc_funcs[pipe]->loader_protect(crtc, true);
|
||||
#endif
|
||||
static struct drm_framebuffer *am_meson_logo_init_fb(struct drm_device *dev)
|
||||
{
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct drm_framebuffer *fb;
|
||||
struct am_meson_fb *meson_fb;
|
||||
|
||||
DRM_INFO("width=%d,height=%d,start_addr=0x%pa,size=%d\n",
|
||||
logo.width, logo.height, &logo.start, logo.size);
|
||||
DRM_INFO("bpp=%d,alloc_flag=%d\n", logo.bpp, logo.alloc_flag);
|
||||
DRM_INFO("outputmode=%s\n", logo.outputmode);
|
||||
if (logo.bpp == 16)
|
||||
mode_cmd.pixel_format = DRM_FORMAT_RGB565;
|
||||
else
|
||||
mode_cmd.pixel_format = DRM_FORMAT_XRGB8888;
|
||||
mode_cmd.offsets[0] = 0;
|
||||
mode_cmd.width = logo.width;
|
||||
mode_cmd.height = logo.height;
|
||||
mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR;
|
||||
/*ToDo*/
|
||||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * logo.bpp, 32) / 8;
|
||||
fb = am_meson_fb_alloc(dev, &mode_cmd, NULL);
|
||||
if (IS_ERR_OR_NULL(fb))
|
||||
return NULL;
|
||||
meson_fb = to_am_meson_fb(fb);
|
||||
meson_fb->logo = &logo;
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
#define FPS_DELTA_LIMIT 1
|
||||
struct drm_display_mode *
|
||||
am_meson_drm_display_mode_init(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_device *dev;
|
||||
u32 found, num_modes;
|
||||
|
||||
if (!connector || !connector->dev)
|
||||
return NULL;
|
||||
dev = connector->dev;
|
||||
found = 0;
|
||||
drm_modeset_lock_all(dev);
|
||||
if (drm_modeset_is_locked(&dev->mode_config.connection_mutex))
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
num_modes = connector->funcs->fill_modes(connector,
|
||||
dev->mode_config.max_width,
|
||||
dev->mode_config.max_height);
|
||||
drm_modeset_unlock_all(dev);
|
||||
if (!num_modes) {
|
||||
DRM_INFO("%s:num_modes is zero\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry(mode, &connector->modes, head) {
|
||||
if (am_meson_crtc_check_mode(mode, logo.outputmode) == true) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
return mode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int am_meson_update_output_state(struct drm_atomic_state *state,
|
||||
struct drm_mode_set *set)
|
||||
{
|
||||
struct drm_device *dev = set->crtc->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret, i;
|
||||
|
||||
ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
|
||||
state->acquire_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* First disable all connectors on the target crtc. */
|
||||
ret = drm_atomic_add_affected_connectors(state, set->crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_connector_in_state(state, connector, conn_state, i) {
|
||||
if (conn_state->crtc == set->crtc) {
|
||||
ret = drm_atomic_set_crtc_for_connector(conn_state,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then set all connectors from set->connectors on the target crtc */
|
||||
for (i = 0; i < set->num_connectors; i++) {
|
||||
conn_state = drm_atomic_get_connector_state(state,
|
||||
set->connectors[i]);
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
|
||||
ret = drm_atomic_set_crtc_for_connector(conn_state,
|
||||
set->crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
/* Don't update ->enable for the CRTC in the set_config request,
|
||||
* since a mismatch would indicate a bug in the upper layers.
|
||||
* The actual modeset code later on will catch any
|
||||
* inconsistencies here.
|
||||
*/
|
||||
if (crtc == set->crtc)
|
||||
continue;
|
||||
|
||||
if (!crtc_state->connector_mask) {
|
||||
ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
crtc_state->active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __am_meson_drm_set_config(struct drm_mode_set *set,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_plane_state *primary_state;
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
int hdisplay, vdisplay;
|
||||
int ret;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
primary_state = drm_atomic_get_plane_state(state, crtc->primary);
|
||||
if (IS_ERR(primary_state))
|
||||
return PTR_ERR(primary_state);
|
||||
|
||||
if (!set->mode) {
|
||||
WARN_ON(set->fb);
|
||||
WARN_ON(set->num_connectors);
|
||||
|
||||
ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
crtc_state->active = false;
|
||||
|
||||
ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
drm_atomic_set_fb_for_plane(primary_state, NULL);
|
||||
|
||||
goto commit;
|
||||
}
|
||||
|
||||
WARN_ON(!set->fb);
|
||||
WARN_ON(!set->num_connectors);
|
||||
|
||||
ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
crtc_state->active = true;
|
||||
|
||||
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
|
||||
|
||||
drm_atomic_set_fb_for_plane(primary_state, set->fb);
|
||||
primary_state->crtc_x = 0;
|
||||
primary_state->crtc_y = 0;
|
||||
primary_state->crtc_w = hdisplay;
|
||||
primary_state->crtc_h = vdisplay;
|
||||
primary_state->src_x = set->x << 16;
|
||||
primary_state->src_y = set->y << 16;
|
||||
if (drm_rotation_90_or_270(primary_state->rotation)) {
|
||||
primary_state->src_w = set->fb->height << 16;
|
||||
primary_state->src_h = set->fb->width << 16;
|
||||
} else {
|
||||
primary_state->src_w = set->fb->width << 16;
|
||||
primary_state->src_h = set->fb->height << 16;
|
||||
}
|
||||
|
||||
commit:
|
||||
ret = am_meson_update_output_state(state, set);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am_meson_drm_set_config(struct drm_mode_set *set)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
int ret = 0;
|
||||
|
||||
state = drm_atomic_state_alloc(crtc->dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->legacy_set_config = true;
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
retry:
|
||||
ret = __am_meson_drm_set_config(set, state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
/* Driver takes ownership of state on successful commit. */
|
||||
return 0;
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_free(state);
|
||||
|
||||
return ret;
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
crtc->primary->old_fb = crtc->primary->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
static void am_meson_load_logo(struct drm_device *dev)
|
||||
{
|
||||
struct drm_mode_set set;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_connector **connector_set;
|
||||
struct meson_drm *private = dev->dev_private;
|
||||
|
||||
if (!logo.alloc_flag) {
|
||||
DRM_INFO("%s: logo memory is not cma alloc\n", __func__);
|
||||
return;
|
||||
}
|
||||
fb = am_meson_logo_init_fb(dev);
|
||||
if (!fb) {
|
||||
DRM_INFO("%s:framebuffer is NULL!\n", __func__);
|
||||
return;
|
||||
}
|
||||
connector_set = kmalloc_array(1, sizeof(struct drm_connector *),
|
||||
GFP_KERNEL);
|
||||
if (!connector_set)
|
||||
return;
|
||||
connector_set[0] = am_meson_hdmi_connector();
|
||||
if (!connector_set[0]) {
|
||||
DRM_INFO("%s:connector is NULL!\n", __func__);
|
||||
kfree(connector_set);
|
||||
return;
|
||||
}
|
||||
mode = am_meson_drm_display_mode_init(connector_set[0]);
|
||||
if (!mode) {
|
||||
DRM_INFO("%s:display mode is NULL!\n", __func__);
|
||||
kfree(connector_set);
|
||||
return;
|
||||
}
|
||||
DRM_INFO("find the match display mode:%s\n", mode->name);
|
||||
set.crtc = private->crtc;
|
||||
set.x = 0;
|
||||
set.y = 0;
|
||||
set.mode = mode;
|
||||
set.connectors = connector_set;
|
||||
set.num_connectors = 1;
|
||||
set.fb = fb;
|
||||
drm_modeset_lock_all(dev);
|
||||
if (am_meson_drm_set_config(&set))
|
||||
DRM_INFO("[%s]am_meson_drm_set_config fail\n", __func__);
|
||||
if (drm_framebuffer_read_refcount(fb) > 1)
|
||||
drm_framebuffer_unreference(fb);
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
kfree(connector_set);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_USE_ION
|
||||
static const struct drm_ioctl_desc meson_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -277,7 +567,7 @@ static int am_meson_drm_bind(struct device *dev)
|
||||
|
||||
drm_kms_helper_poll_init(drm);
|
||||
|
||||
am_meson_load(drm);
|
||||
am_meson_load_logo(drm);
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
|
||||
ret = am_meson_drm_fbdev_init(drm);
|
||||
@@ -290,7 +580,6 @@ static int am_meson_drm_bind(struct device *dev)
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
err_fbdev_fini:
|
||||
#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
|
||||
am_meson_drm_fbdev_fini(drm);
|
||||
@@ -384,10 +673,10 @@ static bool am_meson_drv_use_osd(void)
|
||||
|
||||
if (strcmp(str, "okay") && strcmp(str, "ok")) {
|
||||
DRM_INFO("device %s status is %s\n",
|
||||
node->name, str);
|
||||
node->name, str);
|
||||
} else {
|
||||
DRM_INFO("device %s status is %s\n",
|
||||
node->name, str);
|
||||
node->name, str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -466,6 +755,7 @@ static int am_meson_drv_probe(struct platform_device *pdev)
|
||||
struct component_match *match = NULL;
|
||||
int i;
|
||||
|
||||
pr_info("[%s] in\n", __func__);
|
||||
if (am_meson_drv_use_osd())
|
||||
return am_meson_drv_probe_prune(pdev);
|
||||
|
||||
@@ -518,7 +808,7 @@ static int am_meson_drv_probe(struct platform_device *pdev)
|
||||
am_meson_add_endpoints(dev, &match, port);
|
||||
of_node_put(port);
|
||||
}
|
||||
|
||||
pr_info("[%s] out\n", __func__);
|
||||
return component_master_add_with_match(dev, &am_meson_drm_ops, match);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ struct meson_drm {
|
||||
|
||||
struct meson_vpu_pipeline *pipeline;
|
||||
struct meson_vpu_funcs *funcs;
|
||||
struct am_meson_logo *logo;
|
||||
|
||||
u32 num_crtcs;
|
||||
struct am_meson_crtc *crtcs[MESON_MAX_CRTC];
|
||||
@@ -76,6 +77,7 @@ static inline int meson_vpu_is_compatible(struct meson_drm *priv,
|
||||
extern int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
|
||||
const struct meson_crtc_funcs *crtc_funcs);
|
||||
extern void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc);
|
||||
struct drm_connector *am_meson_hdmi_connector(void);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int meson_debugfs_init(struct drm_minor *minor);
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
|
||||
#include "meson_fb.h"
|
||||
|
||||
#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
|
||||
#include "meson_vpu.h"
|
||||
|
||||
void am_meson_fb_destroy(struct drm_framebuffer *fb)
|
||||
{
|
||||
@@ -27,6 +26,9 @@ void am_meson_fb_destroy(struct drm_framebuffer *fb)
|
||||
|
||||
drm_gem_object_unreference_unlocked(&meson_fb->bufp->base);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
if (meson_fb->logo && meson_fb->logo->alloc_flag)
|
||||
am_meson_free_logo_memory();
|
||||
DRM_DEBUG("meson_fb=0x%p,\n", meson_fb);
|
||||
kfree(meson_fb);
|
||||
}
|
||||
|
||||
@@ -58,9 +60,12 @@ am_meson_fb_alloc(struct drm_device *dev,
|
||||
if (!meson_fb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
meson_gem = container_of(obj, struct am_meson_gem_object, base);
|
||||
meson_fb->bufp = meson_gem;
|
||||
|
||||
if (obj) {
|
||||
meson_gem = container_of(obj, struct am_meson_gem_object, base);
|
||||
meson_fb->bufp = meson_gem;
|
||||
} else {
|
||||
meson_fb->bufp = NULL;
|
||||
}
|
||||
drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
|
||||
|
||||
ret = drm_framebuffer_init(dev, &meson_fb->base,
|
||||
@@ -70,6 +75,10 @@ am_meson_fb_alloc(struct drm_device *dev,
|
||||
ret);
|
||||
goto err_free_fb;
|
||||
}
|
||||
DRM_INFO("meson_fb[id:%d,ref:%d]=0x%p,meson_fb->bufp=0x%p\n",
|
||||
meson_fb->base.base.id,
|
||||
atomic_read(&meson_fb->base.base.refcount.refcount),
|
||||
meson_fb, meson_fb->bufp);
|
||||
|
||||
return &meson_fb->base;
|
||||
|
||||
@@ -113,6 +122,10 @@ struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
|
||||
kfree(meson_fb);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
DRM_DEBUG("meson_fb[in:%d,ref:%d]=0x%px,meson_fb->bufp=0x%p\n",
|
||||
meson_fb->base.base.id,
|
||||
atomic_read(&meson_fb->base.base.refcount.refcount),
|
||||
meson_fb, meson_fb->bufp);
|
||||
|
||||
return &meson_fb->base;
|
||||
}
|
||||
|
||||
@@ -24,16 +24,40 @@
|
||||
|
||||
#include "meson_gem.h"
|
||||
|
||||
#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
|
||||
|
||||
#define VMODE_NAME_LEN_MAX 64
|
||||
|
||||
struct am_meson_logo {
|
||||
struct page *logo_page;
|
||||
phys_addr_t start;
|
||||
u32 size;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 bpp;
|
||||
u32 alloc_flag;
|
||||
u32 info_loaded_mask;
|
||||
char *outputmode_t;
|
||||
char outputmode[VMODE_NAME_LEN_MAX];
|
||||
};
|
||||
|
||||
struct am_meson_fb {
|
||||
struct drm_framebuffer base;
|
||||
struct am_meson_gem_object *bufp;
|
||||
struct am_meson_logo *logo;
|
||||
};
|
||||
|
||||
struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
struct drm_framebuffer *am_meson_drm_framebuffer_init(
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
struct drm_framebuffer *
|
||||
am_meson_fb_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
struct drm_framebuffer *
|
||||
am_meson_drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
struct drm_framebuffer *
|
||||
am_meson_fb_alloc(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ static int am_meson_gem_alloc_ion_buff(
|
||||
bscatter = true;
|
||||
}
|
||||
|
||||
if (IS_ERR(handle)) {
|
||||
if (IS_ERR_OR_NULL(handle)) {
|
||||
DRM_ERROR("%s: FAILED, flags:0x%x.\n",
|
||||
__func__, flags);
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -35,17 +35,11 @@
|
||||
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
|
||||
#include "meson_hdmi.h"
|
||||
#include "meson_hdcp.h"
|
||||
#include "meson_vpu.h"
|
||||
|
||||
#define DEVICE_NAME "amhdmitx"
|
||||
struct am_hdmi_tx am_hdmi_info;
|
||||
|
||||
struct am_vout_mode {
|
||||
char name[DRM_DISPLAY_MODE_LEN];
|
||||
enum vmode_e mode;
|
||||
int width, height, vrefresh;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
static struct am_vout_mode am_vout_modes[] = {
|
||||
{ "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
|
||||
{ "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
|
||||
@@ -300,7 +294,6 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
|
||||
set_vout_vmode(vmode);
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
mdelay(1000);
|
||||
am_hdmi_hdcp_work_state_change(am_hdmi, 0);
|
||||
}
|
||||
@@ -584,6 +577,11 @@ static const struct of_device_id am_meson_hdmi_dt_ids[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(of, am_meson_hdmi_dt_ids);
|
||||
|
||||
struct drm_connector *am_meson_hdmi_connector(void)
|
||||
{
|
||||
return &am_hdmi_info.connector;
|
||||
}
|
||||
|
||||
static int am_meson_hdmi_bind(struct device *dev,
|
||||
struct device *master, void *data)
|
||||
{
|
||||
@@ -596,12 +594,9 @@ static int am_meson_hdmi_bind(struct device *dev,
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
am_hdmi = devm_kzalloc(priv->dev, sizeof(*am_hdmi),
|
||||
GFP_KERNEL);
|
||||
if (!am_hdmi)
|
||||
return -ENOMEM;
|
||||
memcpy(&am_hdmi_info, am_hdmi, sizeof(*am_hdmi));
|
||||
DRM_INFO("[%s] in\n", __func__);
|
||||
am_hdmi = &am_hdmi_info;
|
||||
memset(am_hdmi, 0, sizeof(*am_hdmi));
|
||||
|
||||
DRM_INFO("drm hdmitx init and version:%s\n", DRM_HDMITX_VER);
|
||||
am_hdmi->priv = priv;
|
||||
@@ -662,6 +657,7 @@ static int am_meson_hdmi_bind(struct device *dev,
|
||||
DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
|
||||
}
|
||||
}
|
||||
DRM_INFO("[%s] out\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -679,6 +675,7 @@ static const struct component_ops am_meson_hdmi_ops = {
|
||||
|
||||
static int am_meson_hdmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
DRM_INFO("[%s] in\n", __func__);
|
||||
return component_add(&pdev->dev, &am_meson_hdmi_ops);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,12 +42,18 @@ static u64 afbc_wb_modifier[] = {
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
};
|
||||
|
||||
static void meson_plane_position_calc(
|
||||
struct meson_vpu_osd_layer_info *plane_info,
|
||||
struct drm_plane_state *state,
|
||||
struct drm_display_mode *mode)
|
||||
static void
|
||||
meson_plane_position_calc(struct meson_vpu_osd_layer_info *plane_info,
|
||||
struct drm_plane_state *state,
|
||||
struct drm_display_mode *disp_mode)
|
||||
{
|
||||
u32 dst_w, dst_h, src_w, src_h, scan_mode_out;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
if (IS_ERR_OR_NULL(state->crtc))
|
||||
mode = disp_mode;
|
||||
else
|
||||
mode = &state->crtc->mode;
|
||||
|
||||
scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE;
|
||||
plane_info->src_x = state->src_x;
|
||||
@@ -147,7 +153,7 @@ static int meson_plane_fb_check(struct drm_plane *plane,
|
||||
#else
|
||||
struct drm_gem_cma_object *gem;
|
||||
#endif
|
||||
dma_addr_t phyaddr;
|
||||
phys_addr_t phyaddr;
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_USE_ION
|
||||
meson_fb = container_of(fb, struct am_meson_fb, base);
|
||||
@@ -155,9 +161,21 @@ static int meson_plane_fb_check(struct drm_plane *plane,
|
||||
DRM_INFO("meson_fb is NULL!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
|
||||
if (meson_fb->bufp->bscatter)
|
||||
DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n");
|
||||
DRM_DEBUG("meson_fb[id:%d,ref:%d]=0x%p\n",
|
||||
meson_fb->base.base.id,
|
||||
atomic_read(&meson_fb->base.base.refcount.refcount),
|
||||
meson_fb);
|
||||
if (meson_fb->logo && meson_fb->logo->alloc_flag &&
|
||||
meson_fb->logo->start) {
|
||||
phyaddr = meson_fb->logo->start;
|
||||
DRM_DEBUG("logo->phyaddr=0x%pa\n", &phyaddr);
|
||||
} else if (meson_fb->bufp) {
|
||||
phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
|
||||
} else {
|
||||
phyaddr = 0;
|
||||
DRM_INFO("don't find phyaddr!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#else
|
||||
if (!fb) {
|
||||
DRM_INFO("fb is NULL!\n");
|
||||
@@ -182,12 +200,6 @@ static int meson_plane_get_fb_info(struct drm_plane *plane,
|
||||
struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
|
||||
struct drm_framebuffer *fb = new_state->fb;
|
||||
struct meson_drm *drv = osd_plane->drv;
|
||||
#ifdef CONFIG_DRM_MESON_USE_ION
|
||||
struct am_meson_fb *meson_fb;
|
||||
#else
|
||||
struct drm_gem_cma_object *gem;
|
||||
#endif
|
||||
dma_addr_t phyaddr;
|
||||
|
||||
if (!drv) {
|
||||
DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__);
|
||||
@@ -197,29 +209,7 @@ static int meson_plane_get_fb_info(struct drm_plane *plane,
|
||||
DRM_INFO("%s invalid plane_index!\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_MESON_USE_ION
|
||||
meson_fb = container_of(fb, struct am_meson_fb, base);
|
||||
if (!meson_fb) {
|
||||
DRM_INFO("meson_fb is NULL!\n");
|
||||
return 0;
|
||||
}
|
||||
phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
|
||||
if (meson_fb->bufp->bscatter)
|
||||
DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n");
|
||||
plane_info->fb_size = meson_fb->bufp->base.size;
|
||||
#else
|
||||
if (!fb) {
|
||||
DRM_INFO("fb is NULL!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Update Canvas with buffer address */
|
||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
phyaddr = gem->paddr;
|
||||
#endif
|
||||
|
||||
plane_info->pixel_format = fb->pixel_format;
|
||||
plane_info->phy_addr = phyaddr;
|
||||
plane_info->byte_stride = fb->pitches[0];
|
||||
|
||||
/*setup afbc info*/
|
||||
@@ -261,6 +251,13 @@ static int meson_plane_atomic_get_property(struct drm_plane *plane,
|
||||
struct drm_property *property,
|
||||
uint64_t *val)
|
||||
{
|
||||
struct am_osd_plane *osd_plane;
|
||||
struct am_meson_plane_state *plane_state;
|
||||
|
||||
osd_plane = to_am_osd_plane(plane);
|
||||
plane_state = to_am_meson_plane_state(state);
|
||||
if (property == osd_plane->prop_premult_en)
|
||||
*val = plane_state->premult_en;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -269,6 +266,14 @@ static int meson_plane_atomic_set_property(struct drm_plane *plane,
|
||||
struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
struct am_osd_plane *osd_plane;
|
||||
struct am_meson_plane_state *plane_state;
|
||||
|
||||
osd_plane = to_am_osd_plane(plane);
|
||||
plane_state = to_am_meson_plane_state(state);
|
||||
if (property == osd_plane->prop_premult_en)
|
||||
plane_state->premult_en = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -355,7 +360,7 @@ static void meson_plane_cleanup_fb(struct drm_plane *plane,
|
||||
{
|
||||
struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
|
||||
|
||||
DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
|
||||
DRM_DEBUG("osd %d.\n", osd_plane->plane_index);
|
||||
}
|
||||
|
||||
static void meson_plane_atomic_update(struct drm_plane *plane,
|
||||
@@ -372,6 +377,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
|
||||
struct meson_vpu_pipeline_state *mvps;
|
||||
struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
|
||||
struct meson_drm *drv = osd_plane->drv;
|
||||
struct am_meson_plane_state *plane_state;
|
||||
int ret;
|
||||
|
||||
if (!state || !drv) {
|
||||
@@ -410,6 +416,8 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
|
||||
return ret;
|
||||
}
|
||||
|
||||
plane_state = to_am_meson_plane_state(state);
|
||||
plane_info->premult_en = plane_state->premult_en;
|
||||
plane_info->enable = 1;
|
||||
DRM_DEBUG("index=%d, zorder=%d\n",
|
||||
plane_info->plane_index, plane_info->zorder);
|
||||
@@ -438,6 +446,24 @@ static const struct drm_plane_helper_funcs am_osd_helper_funcs = {
|
||||
.atomic_disable = meson_plane_atomic_disable,
|
||||
};
|
||||
|
||||
int drm_plane_create_premult_en_property(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_property *prop;
|
||||
struct am_osd_plane *osd_plane;
|
||||
|
||||
osd_plane = to_am_osd_plane(plane);
|
||||
prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
|
||||
"PREMULT_EN");
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_object_attach_property(&plane->base, prop, 0);
|
||||
osd_plane->prop_premult_en = prop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
|
||||
{
|
||||
struct am_osd_plane *osd_plane;
|
||||
@@ -469,6 +495,7 @@ static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
|
||||
format_modifiers,
|
||||
type, plane_name);
|
||||
|
||||
drm_plane_create_premult_en_property(plane);
|
||||
drm_plane_helper_add(plane, &am_osd_helper_funcs);
|
||||
osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir,
|
||||
plane_name, osd_plane->plane_index);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
struct am_meson_plane_state {
|
||||
struct drm_plane_state base;
|
||||
u32 premult_en;
|
||||
};
|
||||
|
||||
struct am_osd_plane {
|
||||
@@ -38,6 +39,7 @@ struct am_osd_plane {
|
||||
struct meson_drm *drv; //point to struct parent.
|
||||
struct dentry *plane_debugfs_dir;
|
||||
int plane_index;
|
||||
struct drm_property *prop_premult_en;
|
||||
};
|
||||
|
||||
#define to_am_osd_plane(x) container_of(x, \
|
||||
|
||||
@@ -256,9 +256,6 @@ static struct osd_device_data_s osd_tm2 = {
|
||||
.osd0_sc_independ = 1,
|
||||
};
|
||||
struct osd_device_data_s osd_meson_dev;
|
||||
static u32 logo_memsize;
|
||||
static struct page *logo_page;
|
||||
static struct delayed_work osd_dwork;
|
||||
static struct platform_device *gp_dev;
|
||||
static unsigned long gem_mem_start, gem_mem_size;
|
||||
|
||||
@@ -350,6 +347,28 @@ char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mode || !outputmode)
|
||||
return false;
|
||||
if (!strcmp(mode->name, "panel"))
|
||||
return true;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
|
||||
if (!strcmp(am_vout_modes[i].name, outputmode) &&
|
||||
am_vout_modes[i].width == mode->hdisplay &&
|
||||
am_vout_modes[i].height == mode->vdisplay &&
|
||||
am_vout_modes[i].vrefresh == mode->vrefresh &&
|
||||
am_vout_modes[i].flags ==
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -390,18 +409,43 @@ static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mem_free_work(struct work_struct *work)
|
||||
void am_meson_free_logo_memory(void)
|
||||
{
|
||||
if (logo_memsize > 0) {
|
||||
phys_addr_t logo_addr = page_to_phys(logo.logo_page);
|
||||
|
||||
if (logo.size > 0) {
|
||||
#ifdef CONFIG_CMA
|
||||
pr_info("%s, free memory: addr:0x%x\n",
|
||||
__func__, logo_memsize);
|
||||
DRM_INFO("%s, free memory: addr:0x%pa,size:0x%x\n",
|
||||
__func__, &logo_addr, logo.size);
|
||||
|
||||
dma_release_from_contiguous(&gp_dev->dev,
|
||||
logo_page,
|
||||
logo_memsize >> PAGE_SHIFT);
|
||||
logo.logo_page,
|
||||
logo.size >> PAGE_SHIFT);
|
||||
#endif
|
||||
}
|
||||
logo.alloc_flag = 0;
|
||||
}
|
||||
|
||||
static int am_meson_logo_info_update(struct meson_drm *priv)
|
||||
{
|
||||
logo.start = page_to_phys(logo.logo_page);
|
||||
logo.alloc_flag = 1;
|
||||
/*config 1080p logo as default*/
|
||||
if (!logo.width || !logo.height) {
|
||||
logo.width = 1920;
|
||||
logo.height = 1080;
|
||||
}
|
||||
if (!logo.bpp)
|
||||
logo.bpp = 16;
|
||||
if (!logo.outputmode_t) {
|
||||
strcpy(logo.outputmode, "1080p60hz");
|
||||
} else {
|
||||
strncpy(logo.outputmode, logo.outputmode_t, VMODE_NAME_LEN_MAX);
|
||||
logo.outputmode[VMODE_NAME_LEN_MAX - 1] = '\0';
|
||||
}
|
||||
priv->logo = &logo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am_meson_vpu_bind(struct device *dev,
|
||||
@@ -418,7 +462,7 @@ static int am_meson_vpu_bind(struct device *dev,
|
||||
int ret, irq;
|
||||
|
||||
/* Allocate crtc struct */
|
||||
pr_info("[%s] in\n", __func__);
|
||||
DRM_INFO("[%s] in\n", __func__);
|
||||
amcrtc = devm_kzalloc(dev, sizeof(*amcrtc),
|
||||
GFP_KERNEL);
|
||||
if (!amcrtc)
|
||||
@@ -434,34 +478,40 @@ static int am_meson_vpu_bind(struct device *dev,
|
||||
ret = of_reserved_mem_device_init(&pdev->dev);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "failed to init reserved memory\n");
|
||||
} else {
|
||||
#ifdef CONFIG_CMA
|
||||
gp_dev = pdev;
|
||||
cma = dev_get_cma_area(&pdev->dev);
|
||||
if (cma) {
|
||||
logo_memsize = cma_get_size(cma);
|
||||
pr_info("reserved memory base:0x%x, size:0x%x\n",
|
||||
(u32)cma_get_base(cma), logo_memsize);
|
||||
if (logo_memsize > 0) {
|
||||
logo_page =
|
||||
logo.size = cma_get_size(cma);
|
||||
DRM_INFO("reserved memory base:0x%x, size:0x%x\n",
|
||||
(u32)cma_get_base(cma), logo.size);
|
||||
if (logo.size > 0) {
|
||||
logo.logo_page =
|
||||
dma_alloc_from_contiguous(&pdev->dev,
|
||||
logo_memsize >>
|
||||
logo.size >>
|
||||
PAGE_SHIFT,
|
||||
0);
|
||||
if (!logo_page) {
|
||||
pr_err("allocate buffer failed:%d\n",
|
||||
logo_memsize);
|
||||
}
|
||||
if (!logo.logo_page)
|
||||
DRM_INFO("allocate buffer failed\n");
|
||||
else
|
||||
am_meson_logo_info_update(private);
|
||||
}
|
||||
} else {
|
||||
pr_info("------ NO CMA\n");
|
||||
DRM_INFO("------ NO CMA\n");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
dma_declare_coherent_memory(drm_dev->dev, gem_mem_start,
|
||||
gem_mem_start, gem_mem_size,
|
||||
DMA_MEMORY_EXCLUSIVE);
|
||||
pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
|
||||
(u32)gem_mem_start, (u32)gem_mem_size);
|
||||
if (gem_mem_start) {
|
||||
dma_declare_coherent_memory(drm_dev->dev,
|
||||
gem_mem_start,
|
||||
gem_mem_start,
|
||||
gem_mem_size,
|
||||
DMA_MEMORY_EXCLUSIVE);
|
||||
pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
|
||||
(u32)gem_mem_start, (u32)gem_mem_size);
|
||||
} else {
|
||||
DRM_INFO("------ NO reserved dma\n");
|
||||
}
|
||||
}
|
||||
|
||||
ret = am_meson_plane_create(private);
|
||||
@@ -495,10 +545,7 @@ static int am_meson_vpu_bind(struct device *dev,
|
||||
return ret;
|
||||
|
||||
disable_irq(amcrtc->vblank_irq);
|
||||
|
||||
INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
|
||||
schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
|
||||
pr_info("[%s] out\n", __func__);
|
||||
DRM_INFO("[%s] out\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,10 @@ struct am_vout_mode {
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
extern struct am_meson_logo logo;
|
||||
extern struct osd_device_data_s osd_meson_dev;
|
||||
char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode);
|
||||
void am_meson_free_logo_memory(void);
|
||||
bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode);
|
||||
|
||||
#endif /* __AM_MESON_VPU_H */
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define MESON_BLOCK_MAX_NAME_LEN 32
|
||||
/*ratio base for scaler calc;maybe need bigger than 1000*/
|
||||
#define RATIO_BASE 1000
|
||||
#define MESON_OSD_INPUT_W_LIMIT 1920
|
||||
#define MESON_OSD_INPUT_W_LIMIT 3840
|
||||
|
||||
#define MAX_DIN_NUM 4
|
||||
#define MAX_DOUT_NUM 2
|
||||
@@ -169,6 +169,7 @@ struct meson_vpu_osd_layer_info {
|
||||
u32 afbc_inter_format;
|
||||
u32 afbc_en;
|
||||
u32 fb_size;
|
||||
u32 premult_en;
|
||||
};
|
||||
|
||||
struct meson_vpu_osd {
|
||||
@@ -205,6 +206,7 @@ struct meson_vpu_osd_state {
|
||||
int r_mode;
|
||||
u32 plane_index;
|
||||
u32 fb_size;
|
||||
u32 premult_en;
|
||||
};
|
||||
|
||||
struct meson_vpu_afbc {
|
||||
|
||||
@@ -80,6 +80,34 @@ static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic coef0 */
|
||||
0xf84d42f9, 0xf84a45f9, 0xf84848f8
|
||||
};
|
||||
|
||||
static unsigned int __osd_filter_coefs_2point_binilear[] = {
|
||||
/* 2 point bilinear, bank_length == 2 coef2 */
|
||||
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, 0x78080000, 0x760a0000,
|
||||
0x740c0000, 0x720e0000, 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
|
||||
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, 0x60200000, 0x5e220000,
|
||||
0x5c240000, 0x5a260000, 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
|
||||
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, 0x48380000, 0x463a0000,
|
||||
0x443c0000, 0x423e0000, 0x40400000
|
||||
};
|
||||
|
||||
static unsigned int __osd_filter_coefs_4point_triangle[] = {
|
||||
0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
|
||||
0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
|
||||
0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
|
||||
0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
|
||||
0x18382808, 0x18382808, 0x17372909, 0x17372909,
|
||||
0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
|
||||
0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
|
||||
0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
|
||||
0x10303010
|
||||
};
|
||||
|
||||
static unsigned int *osd_scaler_filter_table[] = {
|
||||
__osd_filter_coefs_bicubic,
|
||||
__osd_filter_coefs_2point_binilear,
|
||||
__osd_filter_coefs_4point_triangle
|
||||
};
|
||||
|
||||
/*********vsc config begin**********/
|
||||
/*vsc phase_step=(v_in << 20)/v_out */
|
||||
void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
|
||||
@@ -309,7 +337,7 @@ void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
|
||||
*1:config horizontal coef
|
||||
*0:config vertical coef
|
||||
*/
|
||||
void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
|
||||
void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag, u32 *coef)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
@@ -320,8 +348,7 @@ void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
|
||||
(flag << 8) |
|
||||
(0 << 0)/*coef index 7bits*/);
|
||||
for (i = 0; i < 33; i++)
|
||||
VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef,
|
||||
__osd_filter_coefs_bicubic[i]);
|
||||
VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef, coef[i]);
|
||||
}
|
||||
/*********sc top ctrl end************/
|
||||
static void f2v_get_vertical_phase(
|
||||
@@ -381,6 +408,8 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
|
||||
u32 width_out = scaler_state->output_width;
|
||||
u32 height_out = scaler_state->output_height;
|
||||
u32 scan_mode_out = scaler_state->scan_mode_out;
|
||||
u32 vsc_double_line_mode;
|
||||
u32 *coef_h, *coef_v;
|
||||
bool scaler_enable;
|
||||
|
||||
if (width_in == width_out && height_in == height_out &&
|
||||
@@ -389,10 +418,13 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
|
||||
else
|
||||
scaler_enable = true;
|
||||
|
||||
if (width_out > linebuffer)
|
||||
if (width_in > linebuffer) {
|
||||
vsc_bank_length = bank_length >> 1;
|
||||
else
|
||||
vsc_double_line_mode = 1;
|
||||
} else {
|
||||
vsc_bank_length = bank_length;
|
||||
vsc_double_line_mode = 0;
|
||||
}
|
||||
hsc_init_rec_num = bank_length;
|
||||
hsc_bank_length = bank_length;
|
||||
hsc_init_rpt_p0_num = bank_length / 2 - 1;
|
||||
@@ -432,6 +464,17 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
|
||||
phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS);
|
||||
phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out;
|
||||
phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS);
|
||||
/*check coef*/
|
||||
if (scan_mode_out && width_out <= 720) {
|
||||
coef_h = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE];
|
||||
coef_v = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE];
|
||||
} else if (vsc_double_line_mode == 1) {
|
||||
coef_h = osd_scaler_filter_table[COEFS_BICUBIC];
|
||||
coef_v = osd_scaler_filter_table[COEFS_2POINT_BINILEAR];
|
||||
} else {
|
||||
coef_h = osd_scaler_filter_table[COEFS_BICUBIC];
|
||||
coef_v = osd_scaler_filter_table[COEFS_BICUBIC];
|
||||
}
|
||||
|
||||
/*input size config*/
|
||||
osd_sc_in_h_set(reg, height_in);
|
||||
@@ -449,13 +492,14 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
|
||||
osd_sc_dummy_data_set(reg, 0x80808080);
|
||||
|
||||
/*h/v coef config*/
|
||||
osd_sc_coef_set(reg, 1);
|
||||
osd_sc_coef_set(reg, 0);
|
||||
osd_sc_coef_set(reg, OSD_SCALER_COEFF_H, coef_h);
|
||||
osd_sc_coef_set(reg, OSD_SCALER_COEFF_V, coef_v);
|
||||
|
||||
/*init recv line num*/
|
||||
osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num);
|
||||
osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num);
|
||||
osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num);
|
||||
osd_vsc_double_line_mode_set(reg, vsc_double_line_mode);
|
||||
|
||||
/*repeate line0 num*/
|
||||
osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num);
|
||||
@@ -650,9 +694,6 @@ static void scaler_hw_init(struct meson_vpu_block *vblk)
|
||||
scaler->reg = &osd_scaler_reg[vblk->index];
|
||||
scaler->linebuffer = OSD_SCALE_LINEBUFFER;
|
||||
scaler->bank_length = OSD_SCALE_BANK_LENGTH;
|
||||
/*disable sc*/
|
||||
osd_sc_en_set(scaler->reg, 0);
|
||||
osd_sc_path_en_set(scaler->reg, 0);
|
||||
DRM_DEBUG("%s hw_init called.\n", scaler->base.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,15 @@
|
||||
#define OSD_ZOOM_TOTAL_BITS 24
|
||||
#define OSD_PHASE_BITS 16
|
||||
|
||||
#define OSD_SCALER_COEFF_H 1
|
||||
#define OSD_SCALER_COEFF_V 0
|
||||
|
||||
enum scaler_coef_e {
|
||||
COEFS_BICUBIC = 0,
|
||||
COEFS_2POINT_BINILEAR,
|
||||
COEFS_4POINT_TRIANGLE
|
||||
};
|
||||
|
||||
enum f2v_vphase_type_e {
|
||||
F2V_IT2IT = 0,
|
||||
F2V_IB2IB,
|
||||
|
||||
@@ -227,6 +227,14 @@ void osd_block_enable(struct osd_mif_reg_s *reg, bool flag)
|
||||
VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1);
|
||||
}
|
||||
|
||||
/*osd alpha_div en
|
||||
*if input is premult,alpha_div=1,else alpha_div=0
|
||||
*/
|
||||
void osd_alpha_div_enable(struct osd_mif_reg_s *reg, bool flag)
|
||||
{
|
||||
VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_mali_unpack_ctrl, flag, 28, 1);
|
||||
}
|
||||
|
||||
/*osd ctrl config*/
|
||||
void osd_ctrl_set(struct osd_mif_reg_s *reg)
|
||||
{
|
||||
@@ -354,6 +362,7 @@ static int osd_check_state(struct meson_vpu_block *vblk,
|
||||
mvos->phy_addr = plane_info->phy_addr;
|
||||
mvos->pixel_format = plane_info->pixel_format;
|
||||
mvos->fb_size = plane_info->fb_size;
|
||||
mvos->premult_en = plane_info->premult_en;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -371,6 +380,7 @@ static void osd_set_state(struct meson_vpu_block *vblk,
|
||||
u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr;
|
||||
struct osd_scope_s scope_src = {0, 1919, 0, 1079};
|
||||
struct osd_mif_reg_s *reg = osd->reg;
|
||||
bool alpha_div_en;
|
||||
|
||||
crtc = vblk->pipeline->crtc;
|
||||
amc = to_am_meson_crtc(crtc);
|
||||
@@ -379,6 +389,7 @@ static void osd_set_state(struct meson_vpu_block *vblk,
|
||||
DRM_DEBUG("set_state break for NULL.\n");
|
||||
return;
|
||||
}
|
||||
alpha_div_en = mvos->premult_en ? 1 : 0;
|
||||
src_h = mvos->src_h;
|
||||
byte_stride = mvos->byte_stride;
|
||||
phy_addr = mvos->phy_addr;
|
||||
@@ -388,12 +399,15 @@ static void osd_set_state(struct meson_vpu_block *vblk,
|
||||
scope_src.v_end = mvos->src_y + mvos->src_h - 1;
|
||||
pixel_format = mvos->pixel_format;
|
||||
canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]];
|
||||
/*Toto: need to separate*/
|
||||
osd_ctrl_set(osd->reg);
|
||||
canvas_config(canvas_index, phy_addr, byte_stride, src_h,
|
||||
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
|
||||
osd_canvas_index[vblk->index] ^= 1;
|
||||
osd_canvas_config(reg, canvas_index);
|
||||
osd_input_size_config(reg, scope_src);
|
||||
osd_color_config(reg, pixel_format);
|
||||
osd_alpha_div_enable(reg, alpha_div_en);
|
||||
DRM_DEBUG("plane_index=%d,HW-OSD=%d\n",
|
||||
mvos->plane_index, vblk->index);
|
||||
DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n",
|
||||
@@ -519,7 +533,6 @@ static void osd_hw_init(struct meson_vpu_block *vblk)
|
||||
return;
|
||||
}
|
||||
osd->reg = &osd_mif_reg[vblk->index];
|
||||
osd_ctrl_set(osd->reg);
|
||||
DRM_DEBUG("%s hw_init done.\n", osd->base.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +256,10 @@ static int meson_gpio_kp_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
//get all gpio desc.
|
||||
desc = devm_gpiod_get_index(&pdev->dev, "key", i, GPIOD_IN);
|
||||
if (IS_ERR_OR_NULL(desc))
|
||||
return -EINVAL;
|
||||
keypad->key[i].desc = desc;
|
||||
//The gpio default is high level.
|
||||
keypad->key[i].current_status = 1;
|
||||
|
||||
@@ -492,8 +492,19 @@ static int fts_input_dev_report_b(struct ts_event *event, struct fts_ts_data *da
|
||||
}
|
||||
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]);
|
||||
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]);
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]);
|
||||
if (data->pdata->rotation) {
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_X,
|
||||
data->pdata->x_max - event->au16_y[i]);
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
|
||||
event->au16_x[i]);
|
||||
|
||||
} else {
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_X,
|
||||
event->au16_x[i]);
|
||||
input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
|
||||
event->au16_y[i]);
|
||||
}
|
||||
|
||||
touchs |= BIT(event->au8_finger_id[i]);
|
||||
data->touchs |= BIT(event->au8_finger_id[i]);
|
||||
|
||||
@@ -994,10 +1005,15 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
|
||||
rc = of_property_read_u32(np, "y_max", &temp_val);
|
||||
if (!rc)
|
||||
{
|
||||
pdata->x_max = temp_val;
|
||||
FTS_DEBUG("y_max=%d", pdata->x_max);
|
||||
pdata->y_max = temp_val;
|
||||
FTS_DEBUG("y_max=%d", pdata->y_max);
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "rotation", &temp_val);
|
||||
if (!rc) {
|
||||
pdata->rotation = temp_val;
|
||||
FTS_DEBUG("rotation = %d", pdata->rotation);
|
||||
}
|
||||
|
||||
FTS_FUNC_EXIT();
|
||||
return 0;
|
||||
|
||||
@@ -109,20 +109,21 @@
|
||||
|
||||
struct fts_ts_platform_data
|
||||
{
|
||||
s32 irq_gpio;
|
||||
u32 irq_gpio_flags;
|
||||
s32 reset_gpio;
|
||||
u32 reset_gpio_flags;
|
||||
bool have_key;
|
||||
u32 key_number;
|
||||
u32 keys[4];
|
||||
u32 key_y_coord;
|
||||
u32 key_x_coords[4];
|
||||
u32 x_max;
|
||||
u32 y_max;
|
||||
u32 x_min;
|
||||
u32 y_min;
|
||||
u32 max_touch_number;
|
||||
s32 irq_gpio;
|
||||
u32 irq_gpio_flags;
|
||||
s32 reset_gpio;
|
||||
u32 reset_gpio_flags;
|
||||
bool have_key;
|
||||
u32 key_number;
|
||||
u32 keys[4];
|
||||
u32 key_y_coord;
|
||||
u32 key_x_coords[4];
|
||||
u32 x_max;
|
||||
u32 y_max;
|
||||
u32 x_min;
|
||||
u32 y_min;
|
||||
u32 max_touch_number;
|
||||
u32 rotation;
|
||||
};
|
||||
|
||||
struct ts_event
|
||||
|
||||
@@ -89,6 +89,7 @@ source "drivers/amlogic/media/vout/Kconfig"
|
||||
source "drivers/amlogic/media/osd/Kconfig"
|
||||
source "drivers/amlogic/media/osd_ext/Kconfig"
|
||||
source "drivers/amlogic/media/deinterlace/Kconfig"
|
||||
source "drivers/amlogic/media/di_multi/Kconfig"
|
||||
source "drivers/amlogic/media/di_local/Kconfig"
|
||||
source "drivers/amlogic/media/vin/Kconfig"
|
||||
source "drivers/amlogic/media/video_processor/Kconfig"
|
||||
|
||||
@@ -5,6 +5,7 @@ obj-$(CONFIG_AMLOGIC_MEDIA_FB) += osd/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_FB_EXT) += osd_ext/
|
||||
obj-$(CONFIG_AMLOGIC_VOUT) += vout/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += deinterlace/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_multi/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_local/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR) += video_processor/
|
||||
|
||||
@@ -516,8 +516,8 @@ static void canvas_pool_config(void)
|
||||
canvas_pool_register_const_canvas(0, 0x25, "amvdec");
|
||||
canvas_pool_register_const_canvas(0x26, 0x39, "vdin");
|
||||
canvas_pool_register_const_canvas(0x78, 0xbf, "amvdec");
|
||||
canvas_pool_register_const_canvas(0x60, 0x65, "display");
|
||||
canvas_pool_register_const_canvas(0x66, 0x6b, "display2");
|
||||
canvas_pool_register_const_canvas(0x58, 0x6f, "display");
|
||||
/* canvas_pool_register_const_canvas(0x66, 0x6b, "display2"); */
|
||||
canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr");
|
||||
canvas_pool_register_const_canvas(0xe4, 0xef, "encoder");
|
||||
canvas_pool_register_const_canvas(0x40, 0x48, "osd");
|
||||
|
||||
@@ -800,6 +800,11 @@ void codec_mm_release(struct codec_mm_s *mem, const char *owner)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&mgt->lock, flags);
|
||||
if (!codec_mm_valid_mm_locked(mem)) {
|
||||
pr_err("codec mm not valied!\n");
|
||||
spin_unlock_irqrestore(&mgt->lock, flags);
|
||||
return;
|
||||
}
|
||||
index = atomic_dec_return(&mem->use_cnt);
|
||||
max_owner = mem->owner[index];
|
||||
for (i = 0; i < index; i++) {
|
||||
|
||||
@@ -54,6 +54,7 @@ static void _fillrect(struct ge2d_context_s *wq,
|
||||
ge2d_cmd_cfg->alpha_blend_mode = OPERATION_LOGIC;
|
||||
ge2d_cmd_cfg->alpha_logic_op = LOGIC_OPERATION_COPY;
|
||||
ge2d_cmd_cfg->wait_done_flag = 1;
|
||||
ge2dgen_disable_matrix(wq);
|
||||
|
||||
ge2d_wq_add_work(wq);
|
||||
}
|
||||
|
||||
@@ -102,9 +102,9 @@ static void aml_dma_put(void *buf_priv)
|
||||
buf->vaddr = NULL;
|
||||
clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index);
|
||||
put_device(buf->dev);
|
||||
kfree(buf);
|
||||
ge2d_log_dbg("ge2d free:aml_dma_buf=0x%p,buf->index=%d\n",
|
||||
buf, buf->index);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static void *aml_dma_alloc(struct device *dev, unsigned long attrs,
|
||||
@@ -129,6 +129,7 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs,
|
||||
if (cma_pages) {
|
||||
paddr = page_to_phys(cma_pages);
|
||||
} else {
|
||||
kfree(buf);
|
||||
pr_err("failed to alloc cma pages.\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -148,7 +149,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma)
|
||||
{
|
||||
struct aml_dma_buf *buf = buf_priv;
|
||||
unsigned long pfn = 0;
|
||||
unsigned long vsize = vma->vm_end - vma->vm_start;
|
||||
unsigned long vsize;
|
||||
int ret = -1;
|
||||
|
||||
if (!buf || !vma) {
|
||||
@@ -156,6 +157,8 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vsize = vma->vm_end - vma->vm_start;
|
||||
|
||||
pfn = buf->dma_addr >> PAGE_SHIFT;
|
||||
ret = remap_pfn_range(vma, vma->vm_start, pfn,
|
||||
vsize, vma->vm_page_prot);
|
||||
@@ -206,11 +209,6 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
|
||||
struct page *page = phys_to_page(phys);
|
||||
|
||||
if (!page) {
|
||||
sg_free_table(sgt);
|
||||
kfree(attach);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sg_set_page(sg, page, PAGE_SIZE, 0);
|
||||
phys += PAGE_SIZE;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ static int ge2d_ioctl_config_ex_mem(struct ge2d_context_s *context,
|
||||
ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype);
|
||||
|
||||
if (ge2d_para_config.para_config_memtype.ge2d_magic
|
||||
== sizeof(struct config_para_ex_memtype_s)) {
|
||||
== sizeof(struct compat_config_para_ex_memtype_s)) {
|
||||
struct config_para_ex_ion_s *pge2d_config_ex;
|
||||
|
||||
uf_ex_mem =
|
||||
|
||||
@@ -806,7 +806,7 @@ static int build_ge2d_config(struct ge2d_context_s *context,
|
||||
update_canvas_cfg(canvas_cfg,
|
||||
cfg->dst_planes[i].addr,
|
||||
cfg->dst_planes[i].w *
|
||||
src->bpp / 8,
|
||||
dst->bpp / 8,
|
||||
cfg->dst_planes[i].h);
|
||||
}
|
||||
}
|
||||
@@ -824,7 +824,8 @@ static int setup_display_property(struct src_dst_para_s *src_dst, int index)
|
||||
u32 cs_width = 0, cs_height = 0, cs_addr = 0;
|
||||
unsigned int data32;
|
||||
unsigned int bpp;
|
||||
unsigned int block_mode[] = {2, 4, 8, 16, 16, 32, 0, 24};
|
||||
unsigned int block_mode[] = {2, 4, 8, 16, 16, 32, 0, 24,
|
||||
0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
src_dst->canvas_index = index;
|
||||
if (ge2d_meson_dev.canvas_status == 0) {
|
||||
|
||||
@@ -430,3 +430,11 @@ void ge2dgen_const_color(struct ge2d_context_s *wq,
|
||||
wq->config.update_flag |= UPDATE_DP_GEN;
|
||||
}
|
||||
}
|
||||
|
||||
void ge2dgen_disable_matrix(struct ge2d_context_s *wq)
|
||||
{
|
||||
struct ge2d_dp_gen_s *dp_gen_cfg = ge2d_wq_get_dp_gen(wq);
|
||||
|
||||
dp_gen_cfg->conv_matrix_en = 0;
|
||||
wq->config.update_flag |= UPDATE_DP_GEN;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,6 @@ void ge2dgen_cb(struct ge2d_context_s *wq,
|
||||
|
||||
void ge2dgen_const_color(struct ge2d_context_s *wq,
|
||||
unsigned int color);
|
||||
|
||||
void ge2dgen_disable_matrix(struct ge2d_context_s *wq);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -254,8 +254,8 @@ static void line_n_int_rdma_irq(void *arg)
|
||||
force_rdma_config[LINE_N_INT_RDMA] = 1;
|
||||
else
|
||||
force_rdma_config[LINE_N_INT_RDMA] = 0;
|
||||
rdma_done[VSYNC_RDMA] = true;
|
||||
irq_count[VSYNC_RDMA]++;
|
||||
rdma_done[LINE_N_INT_RDMA] = true;
|
||||
irq_count[LINE_N_INT_RDMA]++;
|
||||
}
|
||||
|
||||
u32 VSYNC_RD_MPEG_REG(u32 adr)
|
||||
@@ -428,8 +428,10 @@ static int __init rdma_init(void)
|
||||
|
||||
{
|
||||
second_rdma_feature = 0;
|
||||
#if 0 /*def LINE_INT_WORK_AROUND */
|
||||
if (is_meson_g12b_revb())
|
||||
second_rdma_feature = 1;
|
||||
#endif
|
||||
|
||||
cur_enable[VSYNC_RDMA] = 0;
|
||||
enable[VSYNC_RDMA] = 1;
|
||||
|
||||
@@ -107,11 +107,18 @@ struct rdma_instance_s {
|
||||
int prev_trigger_type;
|
||||
};
|
||||
|
||||
#define MAX_CONFLICT 32
|
||||
struct rdma_conflict_regs_s {
|
||||
u32 adr[MAX_CONFLICT];
|
||||
u32 val[MAX_CONFLICT];
|
||||
};
|
||||
|
||||
struct rdma_device_info {
|
||||
const char *device_name;
|
||||
struct platform_device *rdma_dev;
|
||||
struct class *clsp;
|
||||
struct rdma_instance_s rdma_ins[RDMA_NUM];
|
||||
struct rdma_conflict_regs_s rdma_reg;
|
||||
};
|
||||
|
||||
static struct rdma_device_data_s rdma_meson_dev;
|
||||
@@ -360,6 +367,7 @@ irqreturn_t rdma_mgr_isr(int irq, void *dev_id)
|
||||
int retry_count = 0;
|
||||
u32 rdma_status;
|
||||
int i;
|
||||
u32 read_val;
|
||||
if (debug_flag & 0x10)
|
||||
return IRQ_HANDLED;
|
||||
rdma_isr_count++;
|
||||
@@ -399,6 +407,13 @@ QUERY:
|
||||
if ((rdma_status & 0xff000000) && (retry_count < 100))
|
||||
goto QUERY;
|
||||
#endif
|
||||
for (i = 0; i < MAX_CONFLICT; i++) {
|
||||
if (info->rdma_reg.adr[i]) {
|
||||
read_val = READ_VCBUS_REG(info->rdma_reg.adr[i]);
|
||||
if (read_val == info->rdma_reg.val[i])
|
||||
info->rdma_reg.adr[i] = 0;
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -622,19 +637,30 @@ u32 rdma_read_reg(int handle, u32 adr)
|
||||
int i, j = 0;
|
||||
u32 *write_table;
|
||||
int match = 0;
|
||||
int match_oth = 0;
|
||||
int read_from = 0;
|
||||
struct rdma_device_info *info = &rdma_info;
|
||||
struct rdma_instance_s *ins = &info->rdma_ins[handle];
|
||||
u32 read_val = READ_VCBUS_REG(adr);
|
||||
|
||||
for (i = (ins->rdma_item_count - 1); i >= 0; i--) {
|
||||
if (ins->reg_buf[i << 1] == adr) {
|
||||
read_val = ins->reg_buf[(i << 1) + 1];
|
||||
match = 1;
|
||||
read_from = 1;
|
||||
for (i = 0; i < MAX_CONFLICT; i++) {
|
||||
if (info->rdma_reg.adr[i] == adr) {
|
||||
read_val = info->rdma_reg.val[i];
|
||||
match_oth = 1;
|
||||
read_from = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match_oth) {
|
||||
for (i = (ins->rdma_item_count - 1); i >= 0; i--) {
|
||||
if (ins->reg_buf[i << 1] == adr) {
|
||||
read_val = ins->reg_buf[(i << 1) + 1];
|
||||
match = 1;
|
||||
read_from = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
write_table = ins->rdma_table_addr;
|
||||
for (i = (ins->rdma_write_count - 1);
|
||||
@@ -650,7 +676,13 @@ u32 rdma_read_reg(int handle, u32 adr)
|
||||
if (rdma_trace_enable) {
|
||||
for (j = 0; j < rdma_trace_num; j++) {
|
||||
if (adr == rdma_trace_reg[j]) {
|
||||
if (read_from == 2)
|
||||
if (read_from == 3)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x from conflict table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
ins->rdma_write_count);
|
||||
else if (read_from == 2)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x from write table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
@@ -704,6 +736,71 @@ int rdma_watchdog_setting(int flag)
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_watchdog_setting);
|
||||
|
||||
static bool rdma_check_conflict(int handle, u32 adr, u32 *read_val)
|
||||
{
|
||||
struct rdma_instance_s *oth_ins;
|
||||
int i, j, k, n;
|
||||
|
||||
for (i = 0; i < MAX_CONFLICT; i++) {
|
||||
if (rdma_info.rdma_reg.adr[i] == adr) {
|
||||
if (read_val != NULL)
|
||||
*read_val = rdma_info.rdma_reg.val[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < RDMA_NUM; i++) {
|
||||
oth_ins = &rdma_info.rdma_ins[i];
|
||||
if ((!oth_ins->rdma_table_size)
|
||||
|| (!oth_ins->rdma_item_count)
|
||||
|| (i == handle))
|
||||
continue;
|
||||
for (j = 0; j < oth_ins->rdma_item_count; j++) {
|
||||
if (oth_ins->reg_buf[j << 1] != adr)
|
||||
continue;
|
||||
for (n = 0; n < rdma_trace_num; n++) {
|
||||
if ((adr == rdma_trace_reg[n]) ||
|
||||
(debug_flag & 0x20))
|
||||
pr_info(
|
||||
"(%s) handle %d, conflict write %04x=0x%08x (oth handle %d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
oth_ins->reg_buf[(j << 1) + 1],
|
||||
i);
|
||||
}
|
||||
for (k = 0; k < MAX_CONFLICT; k++) {
|
||||
if (!rdma_info.rdma_reg.adr[i]) {
|
||||
rdma_info.rdma_reg.adr[k] = adr;
|
||||
rdma_info.rdma_reg.val[k] =
|
||||
oth_ins->reg_buf[(j << 1) + 1];
|
||||
if (read_val != NULL)
|
||||
*read_val = oth_ins->
|
||||
reg_buf[(j << 1) + 1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rdma_update_conflict(u32 adr, u32 val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CONFLICT; i++) {
|
||||
if (rdma_info.rdma_reg.adr[i] == adr) {
|
||||
rdma_info.rdma_reg.val[i] = val;
|
||||
if (debug_flag & 0x20)
|
||||
pr_info(
|
||||
"(%s) %04x=0x%08x\n",
|
||||
__func__,
|
||||
adr, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rdma_write_reg(int handle, u32 adr, u32 val)
|
||||
{
|
||||
struct rdma_device_info *info = &rdma_info;
|
||||
@@ -716,6 +813,9 @@ int rdma_write_reg(int handle, u32 adr, u32 val)
|
||||
if (debug_flag & 1)
|
||||
pr_info("rdma_write(%d) %d(%x)<=%x\n",
|
||||
handle, ins->rdma_item_count, adr, val);
|
||||
if (rdma_check_conflict(handle, adr, NULL))
|
||||
rdma_update_conflict(adr, val);
|
||||
|
||||
if (((ins->rdma_item_count << 1) + 1) <
|
||||
(ins->rdma_table_size / sizeof(u32))) {
|
||||
ins->reg_buf[ins->rdma_item_count << 1] = adr;
|
||||
@@ -755,20 +855,30 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len)
|
||||
int i, j = 0;
|
||||
u32 *write_table;
|
||||
int match = 0;
|
||||
int match_oth = 0;
|
||||
int read_from = 0;
|
||||
struct rdma_device_info *info = &rdma_info;
|
||||
struct rdma_instance_s *ins = &info->rdma_ins[handle];
|
||||
u32 read_val = READ_VCBUS_REG(adr);
|
||||
u32 oth_val = 0;
|
||||
u32 write_val;
|
||||
|
||||
if (ins->rdma_table_size == 0)
|
||||
return -1;
|
||||
|
||||
if (rdma_check_conflict(handle, adr, &oth_val)) {
|
||||
match_oth = 1;
|
||||
read_val = oth_val;
|
||||
read_from = 3;
|
||||
}
|
||||
|
||||
for (i = (ins->rdma_item_count - 1); i >= 0; i--) {
|
||||
if (ins->reg_buf[i << 1] == adr) {
|
||||
read_val = ins->reg_buf[(i << 1) + 1];
|
||||
match = 1;
|
||||
read_from = 1;
|
||||
if (!match_oth) {
|
||||
read_val = ins->reg_buf[(i << 1) + 1];
|
||||
read_from = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -777,40 +887,48 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len)
|
||||
for (i = (ins->rdma_write_count - 1);
|
||||
i >= 0; i--) {
|
||||
if (write_table[i << 1] == adr) {
|
||||
read_val =
|
||||
write_table[(i << 1) + 1];
|
||||
read_from = 2;
|
||||
if (!match_oth) {
|
||||
read_val =
|
||||
write_table[(i << 1) + 1];
|
||||
read_from = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
write_val = (read_val & ~(((1L<<(len))-1)<<(start)))
|
||||
|((unsigned int)(val) << (start));
|
||||
|
||||
if (rdma_trace_enable) {
|
||||
for (j = 0; j < rdma_trace_num; j++) {
|
||||
if (adr == rdma_trace_reg[j]) {
|
||||
if (read_from == 2)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from write table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val,
|
||||
ins->rdma_write_count);
|
||||
else if (read_from == 1)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from item table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val,
|
||||
ins->rdma_item_count);
|
||||
else
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from real reg\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val);
|
||||
}
|
||||
if (match_oth)
|
||||
rdma_update_conflict(adr, write_val);
|
||||
for (j = 0; j < rdma_trace_num; j++) {
|
||||
if (adr == rdma_trace_reg[j]) {
|
||||
if (read_from == 3)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from conflict table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val,
|
||||
ins->rdma_write_count);
|
||||
else if (read_from == 2)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from write table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val,
|
||||
ins->rdma_write_count);
|
||||
else if (read_from == 1)
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from item table(%d)\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val,
|
||||
ins->rdma_item_count);
|
||||
else
|
||||
pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from real reg\n",
|
||||
__func__,
|
||||
handle, adr,
|
||||
read_val,
|
||||
write_val);
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
@@ -1035,6 +1153,7 @@ static int rdma_probe(struct platform_device *pdev)
|
||||
|
||||
rdma_mgr_irq_request = 0;
|
||||
|
||||
memset((void *)&info->rdma_reg, 0, sizeof(struct rdma_conflict_regs_s));
|
||||
for (i = 0; i < RDMA_NUM; i++) {
|
||||
info->rdma_ins[i].rdma_table_size = 0;
|
||||
if (rdma_meson_dev.rdma_ver == RDMA_VER_1)
|
||||
@@ -1081,12 +1200,15 @@ static int rdma_probe(struct platform_device *pdev)
|
||||
NULL, RDMA_TABLE_SIZE);
|
||||
set_rdma_handle(VSYNC_RDMA, handle);
|
||||
|
||||
#if 0 /*def LINE_INT_WORK_AROUND */
|
||||
if (is_meson_g12b_revb()) {
|
||||
pr_info("g12b revb!!!!\n");
|
||||
handle = rdma_register(get_rdma_ops(LINE_N_INT_RDMA),
|
||||
NULL, RDMA_TABLE_SIZE);
|
||||
set_rdma_handle(LINE_N_INT_RDMA, handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
info->clsp = class_create(THIS_MODULE,
|
||||
RDMA_MGR_CLASS_NAME);
|
||||
if (IS_ERR(info->clsp)) {
|
||||
|
||||
@@ -139,6 +139,8 @@ int vfm_map_remove(char *id)
|
||||
int index;
|
||||
int ret = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(id))
|
||||
return -1;
|
||||
if (!strcmp(id, "all")) {
|
||||
for (i = 0; i < vfm_map_num; i++) {
|
||||
if (vfm_map[i])
|
||||
@@ -157,45 +159,56 @@ int vfm_map_add(char *id, char *name_chain)
|
||||
{
|
||||
int i, j;
|
||||
int ret = -1;
|
||||
char *ptr, *token = NULL;
|
||||
char *ptr = NULL, *token = NULL;
|
||||
struct vfm_map_s *p;
|
||||
int old_num = vfm_map_num;
|
||||
unsigned long flags;
|
||||
int add_ok = 0;
|
||||
int cnt = 10;
|
||||
ulong addr;
|
||||
|
||||
p = kmalloc(sizeof(struct vfm_map_s), GFP_KERNEL);
|
||||
|
||||
if (!p) {
|
||||
pr_err("%s: Error, map no mem!!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ptr = kstrdup(name_chain, GFP_KERNEL);
|
||||
addr = (ulong)ptr;
|
||||
if (!ptr) {
|
||||
kfree(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(struct vfm_map_s));
|
||||
if (strlen(id) >= sizeof(p->id)) {
|
||||
memcpy(p->id, id, sizeof(p->id));
|
||||
p->id[sizeof(p->id)-1] = '\0';
|
||||
} else
|
||||
if (strlen(id) >= VFM_NAME_LEN - 1) {
|
||||
memcpy(p->id, id, VFM_NAME_LEN - 1);
|
||||
p->id[VFM_NAME_LEN - 1] = '\0';
|
||||
} else {
|
||||
memcpy(p->id, id, strlen(id));
|
||||
}
|
||||
p->valid = 1;
|
||||
ptr = name_chain;
|
||||
|
||||
do {
|
||||
token = strsep(&ptr, "\n ");
|
||||
if (token == NULL)
|
||||
if (!token)
|
||||
break;
|
||||
if (*token == '\0')
|
||||
continue;
|
||||
if (strlen(token) >= sizeof(p->name[p->vfm_map_size])) {
|
||||
if (p->vfm_map_size >= VFM_MAP_SIZE)
|
||||
break;
|
||||
if (strlen(token) >= VFM_NAME_LEN - 1) {
|
||||
memcpy(p->name[p->vfm_map_size], token,
|
||||
sizeof(p->name[p->vfm_map_size]));
|
||||
p->name[p->vfm_map_size][
|
||||
sizeof(p->name[p->vfm_map_size])-1] = '\0';
|
||||
} else
|
||||
VFM_NAME_LEN - 1);
|
||||
p->name[p->vfm_map_size][VFM_NAME_LEN - 1] = '\0';
|
||||
} else {
|
||||
memcpy(p->name[p->vfm_map_size], token, strlen(token));
|
||||
}
|
||||
p->vfm_map_size++;
|
||||
} while (token && cnt--);
|
||||
|
||||
cnt = 10; /*limit the cnt of retry to avoid the infinite loop*/
|
||||
|
||||
kfree((void *)addr);
|
||||
retry:
|
||||
for (i = 0; i < vfm_map_num; i++) {
|
||||
struct vfm_map_s *pi = vfm_map[i];
|
||||
@@ -349,53 +362,53 @@ static void vfm_init(void)
|
||||
{
|
||||
#if ((defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER) && \
|
||||
(defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE))
|
||||
char def_id[] = "default";
|
||||
char def_id[VFM_NAME_LEN] = "default";
|
||||
#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
|
||||
char def_name_chain[] = "decoder ppmgr deinterlace amvideo";
|
||||
#else
|
||||
char def_name_chain[] = "decoder amvideo";
|
||||
#endif
|
||||
#elif (defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER)
|
||||
char def_id[] = "default";
|
||||
char def_id[VFM_NAME_LEN] = "default";
|
||||
char def_name_chain[] = "decoder ppmgr amvideo";
|
||||
#elif (defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE)
|
||||
char def_id[] = "default";
|
||||
char def_id[VFM_NAME_LEN] = "default";
|
||||
char def_name_chain[] = "decoder deinterlace amvideo";
|
||||
#else /**/
|
||||
char def_id[] = "default";
|
||||
char def_id[VFM_NAME_LEN] = "default";
|
||||
char def_name_chain[] = "decoder amvideo";
|
||||
#endif /**/
|
||||
#ifdef CONFIG_TVIN_VIUIN
|
||||
char def_ext_id[] = "default_ext";
|
||||
char def_ext_id[VFM_NAME_LEN] = "default_ext";
|
||||
char def_ext_name_chain[] = "vdin amvideo2";
|
||||
#endif /**/
|
||||
#ifdef CONFIG_VDIN_MIPI
|
||||
char def_mipi_id[] = "default_mipi";
|
||||
char def_mipi_id[VFM_NAME_LEN] = "default_mipi";
|
||||
char def_mipi_name_chain[] = "vdin mipi";
|
||||
#endif /**/
|
||||
#ifdef CONFIG_AMLOGIC_V4L_VIDEO2
|
||||
char def_amlvideo2_id[] = "default_amlvideo2";
|
||||
char def_amlvideo2_id[VFM_NAME_LEN] = "default_amlvideo2";
|
||||
char def_amlvideo2_chain[] = "vdin1 amlvideo2.1";
|
||||
#endif /**/
|
||||
#if (defined CONFIG_TVIN_AFE) || (defined CONFIG_TVIN_HDMI)
|
||||
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
|
||||
char tvpath_id[] = "tvpath";
|
||||
char tvpath_id[VFM_NAME_LEN] = "tvpath";
|
||||
char tvpath_chain[] = "vdin0 ppmgr deinterlace amvideo";
|
||||
#else
|
||||
char tvpath_id[] = "tvpath";
|
||||
char tvpath_id[VFM_NAME_LEN] = "tvpath";
|
||||
char tvpath_chain[] = "vdin0 deinterlace amvideo";
|
||||
#endif
|
||||
#endif /**/
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
|
||||
char def_dvbl_id[] = "dvblpath";
|
||||
char def_dvbl_id[VFM_NAME_LEN] = "dvblpath";
|
||||
/* char def_dvbl_chain[] = "dvbldec dvbl amvideo";*/
|
||||
char def_dvbl_chain[] = "dvbldec amvideo";
|
||||
|
||||
char def_dvel_id[] = "dvelpath";
|
||||
char def_dvel_id[VFM_NAME_LEN] = "dvelpath";
|
||||
char def_dvel_chain[] = "dveldec dvel";
|
||||
#endif
|
||||
#if 1/*def CONFIG_AM_HDMIIN_DV*/
|
||||
char def_dvhdmiin_id[] = "dvhdmiin";
|
||||
char def_dvhdmiin_id[VFM_NAME_LEN] = "dvhdmiin";
|
||||
char def_dvhdmiin_chain[] = "dv_vdin amvideo";
|
||||
#endif
|
||||
int i;
|
||||
@@ -476,17 +489,20 @@ static inline struct vframe_s *vfm_vf_peek(
|
||||
|
||||
static void vfm_dump_provider(const char *name)
|
||||
{
|
||||
struct vframe_provider_s *prov = vf_get_provider_by_name(name);
|
||||
struct vframe_provider_s *prov;
|
||||
struct vframe_states states;
|
||||
unsigned long flags;
|
||||
struct vframe_s *vf;
|
||||
char *buf, *pbuf;
|
||||
|
||||
if (!prov)
|
||||
if (IS_ERR_OR_NULL(name))
|
||||
return;
|
||||
prov = vf_get_provider_by_name(name);
|
||||
if (IS_ERR_OR_NULL(prov))
|
||||
return;
|
||||
|
||||
buf = kzalloc(0x400, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
pbuf = buf;
|
||||
@@ -738,19 +754,23 @@ static long vfm_ioctl(struct file *file, unsigned int cmd, ulong arg)
|
||||
struct vfmctl *user_argp = (void __user *)arg;
|
||||
struct vfmctl argp;
|
||||
|
||||
if (IS_ERR_OR_NULL(user_argp))
|
||||
return -EINVAL;
|
||||
memset(&argp, 0, sizeof(struct vfmctl));
|
||||
|
||||
switch (cmd) {
|
||||
case VFM_IOCTL_CMD_SET:{
|
||||
ret =
|
||||
copy_from_user(argp.name, user_argp->name, sizeof(argp.name)-1);
|
||||
ret |=
|
||||
copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1);
|
||||
ret = copy_from_user(argp.name, user_argp->name,
|
||||
sizeof(argp.name) - 1);
|
||||
argp.name[sizeof(argp.name) - 1] = '\0';
|
||||
ret |= copy_from_user(argp.val, user_argp->val,
|
||||
sizeof(argp.val) - 1);
|
||||
argp.val[sizeof(argp.val) - 1] = '\0';
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret =
|
||||
vfm_map_store(NULL, NULL, argp.val, sizeof(argp.val) - 1);
|
||||
ret = vfm_map_store(NULL, NULL, argp.val,
|
||||
sizeof(argp.val) - 1);
|
||||
}
|
||||
break;
|
||||
case VFM_IOCTL_CMD_GET:{
|
||||
@@ -766,39 +786,46 @@ static long vfm_ioctl(struct file *file, unsigned int cmd, ulong arg)
|
||||
}
|
||||
break;
|
||||
case VFM_IOCTL_CMD_ADD:{
|
||||
ret =
|
||||
copy_from_user(argp.name, user_argp->name, sizeof(argp.name)-1);
|
||||
ret |=
|
||||
copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1);
|
||||
ret = copy_from_user(argp.name, user_argp->name,
|
||||
sizeof(argp.name) - 1);
|
||||
argp.name[sizeof(argp.name) - 1] = '\0';
|
||||
ret |= copy_from_user(argp.val, user_argp->val,
|
||||
sizeof(argp.val) - 1);
|
||||
argp.val[sizeof(argp.val) - 1] = '\0';
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = vfm_map_add(argp.name, argp.val);
|
||||
ret = vfm_map_add(argp.name, argp.val);
|
||||
}
|
||||
break;
|
||||
case VFM_IOCTL_CMD_RM:{
|
||||
ret =
|
||||
copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1);
|
||||
ret = copy_from_user(argp.val, user_argp->val,
|
||||
sizeof(argp.val) - 1);
|
||||
argp.val[sizeof(argp.val) - 1] = '\0';
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = vfm_map_remove(argp.val);
|
||||
ret = vfm_map_remove(argp.val);
|
||||
}
|
||||
break;
|
||||
case VFM_IOCTL_CMD_DUMP:{
|
||||
ret =
|
||||
copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1);
|
||||
ret = copy_from_user(argp.val, user_argp->val,
|
||||
sizeof(argp.val) - 1);
|
||||
argp.val[sizeof(argp.val) - 1] = '\0';
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
vfm_dump_provider(argp.val);
|
||||
else
|
||||
vfm_dump_provider(argp.val);
|
||||
}
|
||||
break;
|
||||
case VFM_IOCTL_CMD_ADDDUMMY:{
|
||||
ret =
|
||||
copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1);
|
||||
ret = copy_from_user(argp.val, user_argp->val,
|
||||
sizeof(argp.val) - 1);
|
||||
argp.val[sizeof(argp.val) - 1] = '\0';
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
add_dummy_receiver(argp.val);
|
||||
else
|
||||
add_dummy_receiver(argp.val);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -510,7 +510,9 @@ static struct vpu_ctrl_s vpu_mem_pd_tm2[] = {
|
||||
{VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16},
|
||||
{VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2},
|
||||
{VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2},
|
||||
{VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 4, 4},
|
||||
{VPU_AFBCE, HHI_VPU_MEM_PD_REG4, 0x3, 4, 2},
|
||||
{VPU_VDIN_WR_MIF2, HHI_VPU_MEM_PD_REG4, 0x3, 6, 2},
|
||||
{VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 8, 4},
|
||||
{VPU_MOD_MAX, VPU_REG_END, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@ static char *vpu_mod_table[] = {
|
||||
"axi_wr1",
|
||||
"axi_wr0",
|
||||
"afbce",
|
||||
"dma"
|
||||
"vdin_wr_mif2",
|
||||
"dma",
|
||||
|
||||
"vpu_mod_max",
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ static bool mc_mem_alloc;
|
||||
static unsigned int di_pre_rdma_enable;
|
||||
static struct mutex di_event_mutex;
|
||||
static atomic_t di_flag_unreg; //ary 2019-05-27
|
||||
static atomic_t di_trig_free_mem;
|
||||
|
||||
static unsigned int di_force_bit_mode = 10;
|
||||
module_param(di_force_bit_mode, uint, 0664);
|
||||
@@ -319,7 +320,8 @@ void trigger_pre_di_process(unsigned char idx)
|
||||
{
|
||||
if (di_sema_init_flag == 0)
|
||||
return;
|
||||
|
||||
if (!active_flag)
|
||||
return;
|
||||
log_buffer_state((idx == 'i') ? "irq" : ((idx == 'p') ?
|
||||
"put" : ((idx == 'r') ? "rdy" : "oth")));
|
||||
|
||||
@@ -461,6 +463,7 @@ static int lDI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len)
|
||||
static const struct di_ext_ops di_ext = {
|
||||
.di_post_reg_rd = lDI_POST_REG_RD,
|
||||
.di_post_wr_reg_bits = lDI_POST_WR_REG_BITS,
|
||||
.post_update_mc = di_patch_post_update_mc,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -561,6 +564,42 @@ int get_di_dump_state_flag(void)
|
||||
{
|
||||
return dump_state_flag;
|
||||
}
|
||||
/********************************************
|
||||
* function: for releas mirror mem
|
||||
* need call this after unreg di
|
||||
********************************************/
|
||||
void di_trig_free_mirror_mem(void)
|
||||
{
|
||||
if (atomic_read(&di_flag_unreg)
|
||||
&& de_devp->flag_cma != 2
|
||||
&& de_devp->flag_cma != 0
|
||||
&& active_flag) {
|
||||
atomic_set(&di_trig_free_mem, 1);
|
||||
up(&di_sema);
|
||||
di_pr_info("%s\n", __func__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(di_trig_free_mirror_mem);
|
||||
static bool di_free_mem_pre(void)
|
||||
{
|
||||
|
||||
if (!atomic_read(&di_trig_free_mem))
|
||||
return false;
|
||||
if (di_pre_stru.cma_alloc_done)
|
||||
return false;
|
||||
|
||||
if (!di_post_stru.keep_buf
|
||||
|| !atomic_read(&di_flag_unreg)) {
|
||||
atomic_set(&di_trig_free_mem, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*free mirror memory*/
|
||||
di_post_stru.keep_buf = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
static void parse_param_di(char *buf_orig, char **parm)
|
||||
@@ -656,6 +695,8 @@ store_dbg(struct device *dev,
|
||||
dump_post_mif_reg();
|
||||
} else if (strncmp(buf, "recycle_buf", 11) == 0) {
|
||||
recycle_keep_buffer();
|
||||
} else if (strncmp(buf, "free_mirror", 11) == 0) {
|
||||
di_trig_free_mirror_mem();
|
||||
} else if (strncmp(buf, "recycle_post", 12) == 0) {
|
||||
if (di_vf_peek(NULL))
|
||||
di_vf_put(di_vf_get(NULL), NULL);
|
||||
@@ -1055,10 +1096,10 @@ struct di_buf_s *get_di_buf(int queue_idx, int *start_pos)
|
||||
|
||||
if (di_log_flag & DI_LOG_QUEUE) {
|
||||
if (di_buf)
|
||||
di_print("%s: %x(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
di_print("%s: 0x%p(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
else
|
||||
di_print("%s: %x\n", __func__, di_buf);
|
||||
di_print("%s: 0x%p\n", __func__, di_buf);
|
||||
}
|
||||
|
||||
return di_buf;
|
||||
@@ -1113,10 +1154,10 @@ static struct di_buf_s *get_di_buf_head(int queue_idx)
|
||||
|
||||
if (di_log_flag & DI_LOG_QUEUE) {
|
||||
if (di_buf)
|
||||
di_print("%s: %x(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
di_print("%s: 0x%p(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
else
|
||||
di_print("%s: %x\n", __func__, di_buf);
|
||||
di_print("%s: 0x%p\n", __func__, di_buf);
|
||||
}
|
||||
|
||||
return di_buf;
|
||||
@@ -1141,9 +1182,9 @@ static void queue_out(struct di_buf_s *di_buf)
|
||||
q = &(queue[di_buf->queue_index]);
|
||||
|
||||
if (di_log_flag & DI_LOG_QUEUE)
|
||||
di_print("%s:<%d:%d,%d,%d> %x\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
di_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
@@ -1264,8 +1305,8 @@ static void queue_in(struct di_buf_s *di_buf, int queue_idx)
|
||||
}
|
||||
q = &(queue[queue_idx]);
|
||||
if (di_log_flag & DI_LOG_QUEUE)
|
||||
di_print("%s:<%d:%d,%d,%d> %x\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx, di_buf);
|
||||
di_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx, di_buf);
|
||||
|
||||
if (q->type == 0) {
|
||||
q->pool[q->in_idx] = (di_buf->type << 8) | (di_buf->index);
|
||||
@@ -1702,6 +1743,10 @@ unsigned char is_bypass(vframe_t *vf_in)
|
||||
return 1;
|
||||
if (vf_in && (vf_in->type & VIDTYPE_PIC))
|
||||
return 1;
|
||||
if ((is_meson_gxl_package_805X() || is_meson_gxl_package_805Y()) &&
|
||||
vf_in && is_progressive(vf_in))
|
||||
return 1;
|
||||
|
||||
#if 0
|
||||
if (vf_in && (vf_in->type & VIDTYPE_COMPRESS))
|
||||
return 1;
|
||||
@@ -2407,6 +2452,173 @@ static void di_cma_release(struct di_dev_s *devp)
|
||||
__func__, rels_cnt, delta_time, start_time, end_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void di_patch_mov_ini(void)
|
||||
{
|
||||
struct di_patch_mov_s *pmov;
|
||||
|
||||
if (!de_devp)
|
||||
return;
|
||||
|
||||
pmov = &de_devp->mov;
|
||||
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
|
||||
pmov->en_support = false;
|
||||
return;
|
||||
}
|
||||
pmov->en_support = true;
|
||||
pmov->mode = -1;
|
||||
pmov->nub = 0;
|
||||
}
|
||||
|
||||
bool di_patch_mov_db(unsigned int addr, unsigned int val)
|
||||
{
|
||||
bool ret = false;
|
||||
int i;
|
||||
struct di_patch_mov_s *pmov;
|
||||
struct di_patch_mov_d_s *pmv;
|
||||
|
||||
if (!de_devp)
|
||||
return ret;
|
||||
|
||||
pmov = &de_devp->mov;
|
||||
|
||||
if (!pmov->en_support || !pmov->nub)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < pmov->nub; i++) {
|
||||
if (addr == pmov->reg_addr[i]) {
|
||||
pmv = &pmov->val_db[i];
|
||||
pmv->val = val;
|
||||
pmv->en = true;
|
||||
pmv->mask = 0xffffffff;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void di_patch_mov_setreg(unsigned int nub, unsigned int *preg)
|
||||
{
|
||||
struct di_patch_mov_s *pmov;
|
||||
unsigned int i;
|
||||
|
||||
if (!de_devp)
|
||||
return;
|
||||
|
||||
pmov = &de_devp->mov;
|
||||
|
||||
if (!pmov->en_support)
|
||||
return;
|
||||
|
||||
pmov->nub = nub;
|
||||
if (nub > DI_PATCH_MOV_MAX_NUB) {
|
||||
pr_error("err: %s:nub is overflow %d\n",
|
||||
__func__, nub);
|
||||
pmov->nub = DI_PATCH_MOV_MAX_NUB;
|
||||
}
|
||||
|
||||
pmov->mode = -1;
|
||||
for (i = 0; i < pmov->nub; i++) {
|
||||
pmov->reg_addr[i] = preg[i];
|
||||
di_pr_info("reg:0x%x\n", preg[i]);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(di_patch_mov_setreg);
|
||||
|
||||
/**************************************************
|
||||
* pdate:
|
||||
* value / mask
|
||||
* value / mask
|
||||
* need keep same order with di_patch_mov_setreg
|
||||
**************************************************/
|
||||
bool di_api_mov_sel(unsigned int mode, unsigned int *pdate)
|
||||
{
|
||||
struct di_patch_mov_s *pmov;
|
||||
int i;
|
||||
struct di_patch_mov_d_s *pmv;
|
||||
bool ret = true;
|
||||
|
||||
if (!de_devp)
|
||||
return false;
|
||||
|
||||
pmov = &de_devp->mov;
|
||||
|
||||
if (!pmov ||
|
||||
!pmov->en_support ||
|
||||
!init_flag)
|
||||
return false;
|
||||
|
||||
switch (mode) {
|
||||
case 0:/*setting from db*/
|
||||
pmov->mode = 0;
|
||||
pmov->update = 1;
|
||||
break;
|
||||
case 1:/*setting from pq*/
|
||||
pmov->update = 0;
|
||||
for (i = 0; i < pmov->nub; i++) {
|
||||
pmv = &pmov->val_pq[i];
|
||||
pmv->val = pdate[i * 2];
|
||||
pmv->mask = pdate[i * 2 + 1];
|
||||
pmv->en = true;
|
||||
}
|
||||
pmov->mode = 1;
|
||||
pmov->update = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(di_api_mov_sel);
|
||||
|
||||
static void di_patch_mov_setting(void)
|
||||
{
|
||||
struct di_patch_mov_s *pmov;
|
||||
int i;
|
||||
struct di_patch_mov_d_s *pmv;
|
||||
unsigned int val;
|
||||
|
||||
if (!de_devp)
|
||||
return;
|
||||
|
||||
pmov = &de_devp->mov;
|
||||
|
||||
if (!pmov ||
|
||||
!pmov->en_support ||
|
||||
pmov->mode < 0 ||
|
||||
pmov->mode > 1 ||
|
||||
!pmov->update)
|
||||
return;
|
||||
|
||||
if (pmov->mode == 0)
|
||||
pmv = &pmov->val_db[0];
|
||||
else
|
||||
pmv = &pmov->val_pq[0];
|
||||
|
||||
for (i = 0; i < pmov->nub; i++) {
|
||||
if (pmv->en) {
|
||||
if (pmv->mask != 0xffffffff) {
|
||||
val = ((RDMA_RD(pmov->reg_addr[i]) &
|
||||
(~(pmv->mask))) |
|
||||
(pmv->val & pmv->mask));
|
||||
} else {
|
||||
val = pmv->val;
|
||||
}
|
||||
DI_Wr(pmov->reg_addr[i], val);
|
||||
}
|
||||
pmv++;
|
||||
}
|
||||
pmov->update = 0;
|
||||
}
|
||||
|
||||
void di_set_comb_mode(unsigned int mode)
|
||||
{
|
||||
di_pre_stru.comb_mode = mode;
|
||||
}
|
||||
EXPORT_SYMBOL(di_set_comb_mode);
|
||||
|
||||
static int di_init_buf(int width, int height, unsigned char prog_flag)
|
||||
{
|
||||
int i;
|
||||
@@ -2997,7 +3209,7 @@ config_di_pre_mc_mif(struct DI_MC_MIF_s *di_mcinfo_mif,
|
||||
if (di_buf) {
|
||||
pre_size_w = di_buf->vframe->width;
|
||||
pre_size_h = (di_buf->vframe->height + 1) / 2;
|
||||
di_mcinfo_mif->size_x = (pre_size_h + 1) / 2 - 1;
|
||||
di_mcinfo_mif->size_x = pre_size_h / 2 - 1;
|
||||
di_mcinfo_mif->size_y = 1;
|
||||
di_mcinfo_mif->canvas_num = di_buf->mcinfo_canvas_idx;
|
||||
|
||||
@@ -3127,7 +3339,7 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf)
|
||||
di_buf->vframe->width / 2 - 1;
|
||||
di_mif->chroma_y_start0 = 0;
|
||||
di_mif->chroma_y_end0 =
|
||||
di_buf->vframe->height / 2 - 1;
|
||||
(di_buf->vframe->height + 1) / 2 - 1;
|
||||
} else {
|
||||
if (di_pre_stru.cur_inp_type & VIDTYPE_INTERLACE)
|
||||
di_mif->src_prog = 0;
|
||||
@@ -3143,14 +3355,13 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf)
|
||||
di_buf->vframe->width - 1;
|
||||
di_mif->luma_y_start0 = 0;
|
||||
di_mif->luma_y_end0 =
|
||||
di_buf->vframe->height - 2;
|
||||
di_buf->vframe->height - 1;
|
||||
di_mif->chroma_x_start0 = 0;
|
||||
di_mif->chroma_x_end0 =
|
||||
di_buf->vframe->width / 2 - 1;
|
||||
di_mif->chroma_y_start0 = 0;
|
||||
di_mif->chroma_y_end0 =
|
||||
di_buf->vframe->height / 2
|
||||
- (di_mif->src_prog?1:2);
|
||||
(di_buf->vframe->height + 1) / 2 - 1;
|
||||
} else {
|
||||
di_mif->output_field_num = 1;
|
||||
/* bottom */
|
||||
@@ -3166,7 +3377,7 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf)
|
||||
di_mif->chroma_y_start0 =
|
||||
(di_mif->src_prog?0:1);
|
||||
di_mif->chroma_y_end0 =
|
||||
di_buf->vframe->height / 2 - 1;
|
||||
(di_buf->vframe->height + 1) / 2 - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3350,6 +3561,7 @@ static void pre_de_process(void)
|
||||
di_pre_stru.input_size_change_flag = false;
|
||||
}
|
||||
|
||||
di_patch_mov_setting();
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
if (de_devp->nrds_enable) {
|
||||
nr_ds_mif_config();
|
||||
@@ -3407,6 +3619,9 @@ static void pre_de_process(void)
|
||||
}
|
||||
|
||||
di_pre_stru.field_count_for_cont++;
|
||||
if (di_pre_stru.field_count_for_cont >= 5)
|
||||
DI_Wr_reg_bits(DI_MTN_CTRL, 0, 30, 1);
|
||||
|
||||
di_txl_patch_prog(di_pre_stru.cur_prog_flag,
|
||||
di_pre_stru.field_count_for_cont, mcpre_en);
|
||||
|
||||
@@ -3424,14 +3639,16 @@ static void pre_de_process(void)
|
||||
* otherwise may cause watch dog reboot
|
||||
*/
|
||||
di_lock_irqfiq_save(irq_flag2);
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
/* enable mc pre mif*/
|
||||
enable_di_pre_mif(true, mcpre_en);
|
||||
pre_frame_reset_g12(di_pre_stru.madi_enable,
|
||||
di_pre_stru.mcdi_enable);
|
||||
else
|
||||
} else {
|
||||
pre_frame_reset();
|
||||
|
||||
/* enable mc pre mif*/
|
||||
enable_di_pre_mif(true, mcpre_en);
|
||||
/* enable mc pre mif*/
|
||||
enable_di_pre_mif(true, mcpre_en);
|
||||
}
|
||||
di_unlock_irqfiq_restore(irq_flag2);
|
||||
/*reinit pre busy flag*/
|
||||
di_pre_stru.pre_de_busy_timer_count = 0;
|
||||
@@ -3536,8 +3753,10 @@ static void pre_de_done_buf_config(void)
|
||||
di_pre_stru.di_post_wr_buf = di_pre_stru.di_wr_buf;
|
||||
post_wr_buf = di_pre_stru.di_post_wr_buf;
|
||||
|
||||
if (post_wr_buf)
|
||||
if (post_wr_buf) {
|
||||
post_wr_buf->vframe->di_pulldown = 0;
|
||||
post_wr_buf->vframe->di_gmv = 0;
|
||||
}
|
||||
|
||||
if (post_wr_buf && !di_pre_stru.cur_prog_flag) {
|
||||
read_pulldown_info(&glb_frame_mot_num,
|
||||
@@ -3552,7 +3771,8 @@ static void pre_de_done_buf_config(void)
|
||||
|
||||
}
|
||||
post_wr_buf->vframe->di_pulldown |= 0x08;
|
||||
if (combing_fix_en)
|
||||
post_wr_buf->vframe->di_gmv = glb_frame_mot_num;
|
||||
if (di_pre_stru.combing_fix_en)
|
||||
cur_lev = adaptive_combing_fixing(
|
||||
di_pre_stru.mtn_status,
|
||||
glb_field_mot_num,
|
||||
@@ -3890,7 +4110,9 @@ static unsigned char pre_de_buf_config(void)
|
||||
unsigned int width_roundup = 2;
|
||||
u32 rls_timeout;
|
||||
u32 afbc_busy;
|
||||
u32 is_afbc_mode;
|
||||
u32 is_afbc_mode = 0;
|
||||
bool flg_1080i = false;
|
||||
bool flg_480i = false;
|
||||
|
||||
if (di_blocking || !atomic_read(&de_devp->mem_flag))
|
||||
return 0;
|
||||
@@ -3960,7 +4182,8 @@ static unsigned char pre_de_buf_config(void)
|
||||
|
||||
/*for support compress from dec*/
|
||||
if (IS_COMP_MODE(vframe->type) &&
|
||||
!is_bypass(vframe)) {
|
||||
!is_bypass(vframe) &&
|
||||
afbc_is_supported()) {
|
||||
is_afbc_mode = true;
|
||||
if (IS_VDIN_SRC(vframe->source_type)
|
||||
&& IS_I_SRC(vframe->type)) {
|
||||
@@ -4395,14 +4618,11 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
|
||||
} else {
|
||||
/*********************************/
|
||||
if ((di_buf->vframe->width >= 1920) &&
|
||||
(di_buf->vframe->height >= 1080) &&
|
||||
is_meson_tl1_cpu()) {
|
||||
if (combing_fix_en) {
|
||||
combing_fix_en = false;
|
||||
fix_tl1_1080i_sawtooth_patch();
|
||||
}
|
||||
} else
|
||||
combing_fix_en = true;
|
||||
(di_buf->vframe->height >= 1080))
|
||||
flg_1080i = true;
|
||||
else if ((di_buf->vframe->width == 720) &&
|
||||
(di_buf->vframe->height == 480))
|
||||
flg_480i = true;
|
||||
|
||||
/*********************************/
|
||||
if (
|
||||
@@ -4586,6 +4806,23 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
|
||||
recovery_flag++;
|
||||
return 0;
|
||||
}
|
||||
if (is_meson_tl1_cpu() &&
|
||||
di_pre_stru.comb_mode &&
|
||||
flg_1080i) {
|
||||
di_pre_stru.combing_fix_en = false;
|
||||
fix_tl1_1080i_patch_sel(di_pre_stru.comb_mode);
|
||||
} else {
|
||||
di_pre_stru.combing_fix_en = combing_fix_en;
|
||||
}
|
||||
|
||||
if (di_pre_stru.combing_fix_en) {
|
||||
if (flg_1080i)
|
||||
com_patch_pre_sw_set(1);
|
||||
else if (flg_480i)
|
||||
com_patch_pre_sw_set(2);
|
||||
else
|
||||
com_patch_pre_sw_set(0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4594,10 +4831,16 @@ static int check_recycle_buf(void)
|
||||
struct di_buf_s *di_buf = NULL;/* , *ptmp; */
|
||||
int itmp;
|
||||
int ret = 0;
|
||||
bool blk_flg = 0;
|
||||
|
||||
#ifdef DI_KEEP_HIS
|
||||
if (di_blocking)
|
||||
return ret;
|
||||
#endif
|
||||
queue_for_each_entry(di_buf, ptmp, QUEUE_RECYCLE, list) {
|
||||
if (di_blocking)
|
||||
blk_flg = 1;
|
||||
|
||||
if ((di_buf->pre_ref_count == 0) &&
|
||||
(di_buf->post_ref_count == 0)) {
|
||||
if (di_buf->type == VFRAME_TYPE_IN) {
|
||||
@@ -4610,7 +4853,7 @@ static int check_recycle_buf(void)
|
||||
VFRAME_EVENT_RECEIVER_PUT,
|
||||
NULL);
|
||||
di_print(
|
||||
"%s: vf_put(%d) %x, %u ms\n",
|
||||
"%s: vf_put(%d) 0x%p, %u ms\n",
|
||||
__func__,
|
||||
di_pre_stru.recycle_seq,
|
||||
vframe_in[di_buf->index],
|
||||
@@ -4649,6 +4892,10 @@ static int check_recycle_buf(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (blk_flg)
|
||||
pr_info("di:blk:recycle\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4890,8 +5137,10 @@ static irqreturn_t de_irq(int irq, void *dev_instance)
|
||||
DI_Wr(DI_INTR_CTRL, data32);
|
||||
}
|
||||
#else
|
||||
if (flag)
|
||||
if (flag) {
|
||||
di_hpre_gl_sw(false);
|
||||
DI_Wr(DI_INTR_CTRL, (data32&0xfffffffb)|(intr_mode<<30));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (di_pre_stru.pre_de_busy == 0) {
|
||||
@@ -6737,9 +6986,10 @@ static void di_pre_size_change(unsigned short width,
|
||||
}
|
||||
|
||||
di_load_pq_table();
|
||||
|
||||
#ifdef OLD_PRE_GL
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
|
||||
RDMA_WR(DI_PRE_GL_CTRL, 0x80000005);
|
||||
#endif
|
||||
if (de_devp->nrds_enable)
|
||||
nr_ds_init(width, height);
|
||||
if (de_devp->pps_enable && pps_position) {
|
||||
@@ -6766,6 +7016,10 @@ static void di_pre_size_change(unsigned short width,
|
||||
static bool need_bypass(struct vframe_s *vf)
|
||||
{
|
||||
needbypass_flag = true;
|
||||
if ((is_meson_gxl_package_805X() || is_meson_gxl_package_805Y()) &&
|
||||
is_progressive(vf))
|
||||
return true;
|
||||
|
||||
if (vf->type & VIDTYPE_MVC)
|
||||
return true;
|
||||
|
||||
@@ -6881,6 +7135,7 @@ static void di_reg_process_irq(void)
|
||||
DI_Wr(DI_CLKG_CTRL, 0xfef60001);
|
||||
/* nr/blend0/ei0/mtn0 clock gate */
|
||||
}
|
||||
di_hdr2_hist_init();
|
||||
if (di_printk_flag & 2)
|
||||
di_printk_flag = 1;
|
||||
|
||||
@@ -6955,7 +7210,7 @@ static void di_reg_process_irq(void)
|
||||
di_pre_stru.retry_index = 0;
|
||||
|
||||
init_flag = 1;
|
||||
di_pre_stru.reg_req_flag_irq = 1;
|
||||
/*di_pre_stru.reg_req_flag_irq = 1;*/
|
||||
}
|
||||
di_pre_stru.reg_irq_busy = false;
|
||||
}
|
||||
@@ -7149,66 +7404,79 @@ static int di_task_handle(void *data)
|
||||
ret = down_interruptible(&di_sema);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
if (active_flag) {
|
||||
if ((di_pre_stru.unreg_req_flag ||
|
||||
di_pre_stru.force_unreg_req_flag ||
|
||||
di_pre_stru.disable_req_flag) &&
|
||||
(di_pre_stru.pre_de_busy == 0)) {
|
||||
di_unreg_process();
|
||||
|
||||
if (!de_devp)
|
||||
continue;
|
||||
|
||||
if (!active_flag)
|
||||
continue;
|
||||
|
||||
if ((di_pre_stru.unreg_req_flag ||
|
||||
di_pre_stru.force_unreg_req_flag ||
|
||||
di_pre_stru.disable_req_flag) &&
|
||||
(di_pre_stru.pre_de_busy == 0)) {
|
||||
di_unreg_process();
|
||||
#if 0
|
||||
/* if mirror mode, can't speed down the clk*/
|
||||
/* set min rate for power saving */
|
||||
if (de_devp->vpu_clkb) {
|
||||
clk_set_rate(de_devp->vpu_clkb,
|
||||
de_devp->clkb_min_rate);
|
||||
}
|
||||
/* if mirror mode, can't speed down the clk*/
|
||||
/* set min rate for power saving */
|
||||
if (de_devp->vpu_clkb) {
|
||||
clk_set_rate(de_devp->vpu_clkb,
|
||||
de_devp->clkb_min_rate);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (di_pre_stru.reg_req_flag_irq ||
|
||||
di_pre_stru.reg_req_flag) {
|
||||
di_reg_process();
|
||||
di_pre_stru.reg_req_flag = 0;
|
||||
di_pre_stru.reg_req_flag_irq = 0;
|
||||
}
|
||||
#ifdef CONFIG_CMA
|
||||
/* mutex_lock(&de_devp->cma_mutex);*/
|
||||
if (di_pre_stru.cma_release_req) {
|
||||
atomic_set(&devp->mem_flag, 0);
|
||||
di_cma_release(devp);
|
||||
di_pre_stru.cma_release_req = 0;
|
||||
di_pre_stru.cma_alloc_done = 0;
|
||||
}
|
||||
if (di_pre_stru.cma_alloc_req) {
|
||||
if (di_cma_alloc(devp))
|
||||
atomic_set(&devp->mem_flag, 1);
|
||||
else
|
||||
atomic_set(&devp->mem_flag, 0);
|
||||
di_pre_stru.cma_alloc_req = 0;
|
||||
di_pre_stru.cma_alloc_done = 1;
|
||||
}
|
||||
/* mutex_unlock(&de_devp->cma_mutex); */
|
||||
#endif
|
||||
}
|
||||
if (/*di_pre_stru.reg_req_flag_irq ||*/
|
||||
di_pre_stru.reg_req_flag) {
|
||||
di_reg_process();
|
||||
di_pre_stru.reg_req_flag = 0;
|
||||
/*di_pre_stru.reg_req_flag_irq = 0;*/
|
||||
}
|
||||
#ifdef CONFIG_CMA
|
||||
/* mutex_lock(&de_devp->cma_mutex);*/
|
||||
if (di_pre_stru.cma_release_req) {
|
||||
atomic_set(&devp->mem_flag, 0);
|
||||
di_cma_release(devp);
|
||||
di_pre_stru.cma_release_req = 0;
|
||||
di_pre_stru.cma_alloc_done = 0;
|
||||
}
|
||||
if (di_pre_stru.cma_alloc_req) {
|
||||
if (di_cma_alloc(devp))
|
||||
atomic_set(&devp->mem_flag, 1);
|
||||
else
|
||||
atomic_set(&devp->mem_flag, 0);
|
||||
di_pre_stru.cma_alloc_req = 0;
|
||||
di_pre_stru.cma_alloc_done = 1;
|
||||
}
|
||||
if (di_free_mem_pre()) {
|
||||
di_cma_release(devp);
|
||||
di_pr_info("release mirror\n");
|
||||
atomic_set(&di_trig_free_mem, 0);
|
||||
}
|
||||
/* mutex_unlock(&de_devp->cma_mutex); */
|
||||
#endif
|
||||
|
||||
if (de_devp->flags & DI_VPU_CLKB_SET) {
|
||||
if (is_meson_txlx_cpu()) {
|
||||
if (!use_2_interlace_buff) {
|
||||
#ifdef CLK_TREE_SUPPORT
|
||||
clk_set_rate(de_devp->vpu_clkb,
|
||||
de_devp->clkb_min_rate);
|
||||
de_devp->clkb_min_rate);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef CLK_TREE_SUPPORT
|
||||
clk_set_rate(de_devp->vpu_clkb,
|
||||
de_devp->clkb_max_rate);
|
||||
de_devp->clkb_max_rate);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (is_meson_g12a_cpu() || is_meson_g12b_cpu()
|
||||
|| is_meson_tl1_cpu() || is_meson_tm2_cpu() ||
|
||||
is_meson_sm1_cpu()) {
|
||||
if (is_meson_g12a_cpu() ||
|
||||
is_meson_g12b_cpu() ||
|
||||
is_meson_tl1_cpu() ||
|
||||
is_meson_tm2_cpu() ||
|
||||
is_meson_sm1_cpu()) {
|
||||
#ifdef CLK_TREE_SUPPORT
|
||||
clk_set_rate(de_devp->vpu_clkb,
|
||||
de_devp->clkb_max_rate);
|
||||
de_devp->clkb_max_rate);
|
||||
#endif
|
||||
}
|
||||
de_devp->flags &= (~DI_VPU_CLKB_SET);
|
||||
@@ -7230,7 +7498,7 @@ static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p)
|
||||
if (pre_stru_p->unreg_req_flag_irq &&
|
||||
(di_pre_stru.pre_de_busy == 0))
|
||||
di_unreg_process_irq();
|
||||
if (init_flag == 0 && pre_stru_p->reg_req_flag_irq == 0
|
||||
if (init_flag == 0 /*&& pre_stru_p->reg_req_flag_irq == 0*/
|
||||
&& (!atomic_read(&di_flag_unreg)))
|
||||
di_reg_process_irq();
|
||||
}
|
||||
@@ -7258,9 +7526,38 @@ static enum hrtimer_restart di_pre_hrtimer_func(struct hrtimer *timer)
|
||||
if (!di_pre_stru.bypass_flag)
|
||||
di_pre_trigger_work(&di_pre_stru);
|
||||
hrtimer_forward_now(&di_pre_hrtimer, ms_to_ktime(10));
|
||||
di_patch_post_update_mc();
|
||||
/*di_patch_post_update_mc();*/
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static void post_display_buf_clear(void)
|
||||
{
|
||||
struct di_buf_s *p = NULL;
|
||||
int itmp;
|
||||
|
||||
pr_info("%s:\n", __func__);
|
||||
queue_for_each_entry(p, ptmp, QUEUE_DISPLAY, list) {
|
||||
pr_info("\t%s,%d\n", vframe_type_name[p->type], p->index);
|
||||
if (p->type == VFRAME_TYPE_POST) {
|
||||
if (!atomic_dec_and_test(&p->di_cnt))
|
||||
di_print("%s,di_cnt > 0\n", __func__);
|
||||
recycle_vframe_type_post(p);
|
||||
} else {
|
||||
queue_in(p, QUEUE_RECYCLE);
|
||||
di_print("%s: %s[%d] =>recycle_list\n", __func__,
|
||||
vframe_type_name[p->type], p->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dbg_check_list(void)
|
||||
{
|
||||
unsigned int post_display;
|
||||
|
||||
post_display = list_count(QUEUE_DISPLAY);
|
||||
di_pr_info("display:%d\n", post_display);
|
||||
}
|
||||
|
||||
/*
|
||||
* provider/receiver interface
|
||||
*/
|
||||
@@ -7330,40 +7627,64 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
|
||||
mutex_unlock(&di_event_mutex);
|
||||
pr_info("DI: unreg f\n");
|
||||
} else if (type == VFRAME_EVENT_PROVIDER_RESET) {
|
||||
di_blocking = 1;
|
||||
|
||||
/*di_blocking = 1;*/
|
||||
mutex_lock(&di_event_mutex);
|
||||
pr_info("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__);
|
||||
if (is_bypass(NULL)
|
||||
|| bypass_state
|
||||
|| di_pre_stru.bypass_flag) {
|
||||
/* only if di is bypassed, then we send the message of
|
||||
* VFRAME_EVENT_PROVIDER_RESET to video and notify
|
||||
* it to keep the last canvas buffer which was
|
||||
* alloced by codec not by di.
|
||||
*/
|
||||
vf_notify_receiver(VFM_NAME,
|
||||
VFRAME_EVENT_PROVIDER_RESET,
|
||||
NULL);
|
||||
di_blocking = 1;
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
post_display_buf_clear();
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
}
|
||||
|
||||
goto light_unreg;
|
||||
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
|
||||
di_blocking = 1;
|
||||
|
||||
pr_info("%s: vf_notify_receiver ligth unreg\n", __func__);
|
||||
|
||||
light_unreg:
|
||||
/*-----------------------------------*/
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
for (i = 0; i < MAX_IN_BUF_NUM; i++) {
|
||||
|
||||
if (vframe_in[i])
|
||||
pr_dbg("DI:clear vframe_in[%d]\n", i);
|
||||
pr_info("DI:clear vframe_in[%d]\n", i);
|
||||
|
||||
vframe_in[i] = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
di_blocking = 0;
|
||||
mutex_unlock(&di_event_mutex);
|
||||
pr_info("\treset:end\n");
|
||||
/*goto light_unreg;*/
|
||||
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
|
||||
mutex_lock(&di_event_mutex);
|
||||
di_blocking = 1;
|
||||
|
||||
pr_info("%s: LIGHT_UNREG\n", __func__);
|
||||
|
||||
/*light_unreg:*/
|
||||
#if 1
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
for (i = 0; i < MAX_IN_BUF_NUM; i++) {
|
||||
|
||||
if (vframe_in[i])
|
||||
pr_info("DI:clear vframe_in[%d]\n", i);
|
||||
|
||||
vframe_in[i] = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
#endif
|
||||
di_blocking = 0;
|
||||
mutex_unlock(&di_event_mutex);
|
||||
pr_info("\tlight unreg:end\n");
|
||||
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) {
|
||||
unsigned char vf_put_flag = 0;
|
||||
|
||||
pr_dbg(
|
||||
"%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n",
|
||||
__func__);
|
||||
pr_info("%s:LIGHT_UNREG_RETURN_VFRAME\n", __func__);
|
||||
/*
|
||||
* do not display garbage when 2d->3d or 3d->2d
|
||||
*/
|
||||
@@ -7500,6 +7821,7 @@ light_unreg:
|
||||
if (reg_flag) {
|
||||
pr_err("[DI] no muti instance.\n");
|
||||
mutex_unlock(&di_event_mutex);
|
||||
dbg_check_list();
|
||||
return -1;
|
||||
}
|
||||
pr_info("%s: vframe provider reg %s\n", __func__,
|
||||
@@ -7785,9 +8107,11 @@ get_vframe:
|
||||
log_buffer_state("get");
|
||||
}
|
||||
if (vframe_ret) {
|
||||
di_print("%s: %s[%d]:%x %u ms\n", __func__,
|
||||
vframe_type_name[di_buf->type], di_buf->index, vframe_ret,
|
||||
jiffies_to_msecs(jiffies_64 - vframe_ret->ready_jiffies64));
|
||||
di_print("%s: %s[%d]:0x%p %u ms\n", __func__,
|
||||
vframe_type_name[di_buf->type],
|
||||
di_buf->index, vframe_ret,
|
||||
jiffies_to_msecs
|
||||
(jiffies_64 - vframe_ret->ready_jiffies64));
|
||||
}
|
||||
|
||||
if (!post_wr_en && di_post_stru.run_early_proc_fun_flag && vframe_ret) {
|
||||
@@ -7821,8 +8145,10 @@ static void di_vf_put(vframe_t *vf, void *arg)
|
||||
di_print("%s: 0x%p\n", __func__, vf);
|
||||
return;
|
||||
}
|
||||
#ifdef DI_KEEP_HIS
|
||||
if (di_blocking)
|
||||
return;
|
||||
#endif
|
||||
log_buffer_state("pu_");
|
||||
di_buf = (struct di_buf_s *)vf->private_data;
|
||||
if (IS_ERR_OR_NULL(di_buf)) {
|
||||
@@ -8496,7 +8822,7 @@ static int di_probe(struct platform_device *pdev)
|
||||
vf_receiver_init(&di_vf_recv, VFM_NAME, &di_vf_receiver, NULL);
|
||||
vf_reg_receiver(&di_vf_recv);
|
||||
vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL);
|
||||
active_flag = 1;
|
||||
/*active_flag = 1;*/
|
||||
sema_init(&di_sema, 1);
|
||||
ret = request_irq(di_devp->pre_irq, &de_irq, IRQF_SHARED,
|
||||
"pre_di", (void *)"pre_di");
|
||||
@@ -8523,10 +8849,12 @@ static int di_probe(struct platform_device *pdev)
|
||||
di_devp->task = kthread_run(di_task_handle, di_devp, "kthread_di");
|
||||
if (IS_ERR(di_devp->task))
|
||||
pr_err("%s create kthread error.\n", __func__);
|
||||
active_flag = 1;
|
||||
di_debugfs_init(); /*2018-07-18 add debugfs*/
|
||||
di_patch_post_update_mc_sw(DI_MC_SW_IC, true);
|
||||
|
||||
dil_attach_ext_api(&di_ext);
|
||||
di_patch_mov_ini();
|
||||
|
||||
di_pr_info("%s:ok\n", __func__);
|
||||
return ret;
|
||||
@@ -8619,6 +8947,8 @@ static void di_shutdown(struct platform_device *pdev)
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
int ret = 0;
|
||||
|
||||
active_flag = 0;
|
||||
|
||||
di_devp = platform_get_drvdata(pdev);
|
||||
ret = hrtimer_cancel(&di_pre_hrtimer);
|
||||
pr_info("di pre hrtimer canel %d.\n", ret);
|
||||
@@ -8635,6 +8965,7 @@ static void di_shutdown(struct platform_device *pdev)
|
||||
switch_vpu_clk_gate_vmod(VPU_VPU_CLKB,
|
||||
VPU_CLK_GATE_OFF);
|
||||
kfree(di_devp);
|
||||
di_devp = NULL;
|
||||
pr_info("[DI] shutdown done.\n");
|
||||
|
||||
}
|
||||
@@ -8658,9 +8989,11 @@ static void di_clear_for_suspend(struct di_dev_s *di_devp)
|
||||
di_pre_stru.cma_alloc_done = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef DI_KEEP_HIS
|
||||
hrtimer_cancel(&di_pre_hrtimer);
|
||||
tasklet_kill(&di_pre_tasklet); //ary.sui
|
||||
tasklet_disable(&di_pre_tasklet);
|
||||
#endif
|
||||
pr_info("%s end\n", __func__);
|
||||
}
|
||||
static int save_init_flag;
|
||||
@@ -8674,10 +9007,16 @@ static int di_suspend(struct device *dev)
|
||||
di_devp->flags |= DI_SUSPEND_FLAG;
|
||||
|
||||
di_clear_for_suspend(di_devp);//add
|
||||
active_flag = 0;
|
||||
|
||||
/* fix suspend/resume crash problem */
|
||||
save_init_flag = init_flag;
|
||||
init_flag = 0;
|
||||
|
||||
hrtimer_cancel(&di_pre_hrtimer);
|
||||
tasklet_kill(&di_pre_tasklet);
|
||||
tasklet_disable(&di_pre_tasklet);
|
||||
|
||||
#if 0 /*2019-01-18*/
|
||||
if (di_pre_stru.di_inp_buf) {
|
||||
if (vframe_in[di_pre_stru.di_inp_buf->index]) {
|
||||
@@ -8718,6 +9057,7 @@ static int di_resume(struct device *dev)
|
||||
di_pre_hrtimer.function = di_pre_hrtimer_func;
|
||||
hrtimer_start(&di_pre_hrtimer, ms_to_ktime(10), HRTIMER_MODE_REL);
|
||||
tasklet_enable(&di_pre_tasklet);
|
||||
active_flag = 1;
|
||||
/************/
|
||||
pr_info("di: resume module\n");
|
||||
return 0;
|
||||
|
||||
@@ -220,6 +220,29 @@ extern bool is_vsync_rdma_enable(void);
|
||||
#define TABLE_LEN_MAX 10000
|
||||
#define TABLE_FLG_END (0xfffffffe)
|
||||
|
||||
/******************************************
|
||||
* patch for TV-10258 multiwave group issue
|
||||
*****************************************/
|
||||
#define DI_PATCH_MOV_MAX_NUB 5
|
||||
|
||||
struct di_patch_mov_d_s {
|
||||
unsigned int val;
|
||||
unsigned int mask;
|
||||
bool en;
|
||||
};
|
||||
|
||||
struct di_patch_mov_s {
|
||||
unsigned int reg_addr[DI_PATCH_MOV_MAX_NUB];
|
||||
struct di_patch_mov_d_s val_db[DI_PATCH_MOV_MAX_NUB];
|
||||
struct di_patch_mov_d_s val_pq[DI_PATCH_MOV_MAX_NUB];
|
||||
int mode;/*-1 : not set; 0: set from db, 1: set from pq*/
|
||||
bool en_support;
|
||||
bool update;
|
||||
unsigned int nub;
|
||||
};
|
||||
|
||||
bool di_patch_mov_db(unsigned int addr, unsigned int val);
|
||||
|
||||
struct di_dev_s {
|
||||
dev_t devt;
|
||||
struct cdev cdev; /* The cdev structure */
|
||||
@@ -254,6 +277,7 @@ struct di_dev_s {
|
||||
struct page *total_pages;
|
||||
atomic_t mem_flag;
|
||||
struct dentry *dbg_root; /*dbg_fs*/
|
||||
struct di_patch_mov_s mov;
|
||||
};
|
||||
|
||||
struct di_pre_stru_s {
|
||||
@@ -299,7 +323,7 @@ struct di_pre_stru_s {
|
||||
int unreg_req_flag_irq;
|
||||
int unreg_req_flag_cnt;
|
||||
int reg_req_flag;
|
||||
int reg_req_flag_irq;
|
||||
/*int reg_req_flag_irq;*/
|
||||
int reg_req_flag_cnt;
|
||||
int reg_irq_busy;
|
||||
int force_unreg_req_flag;
|
||||
@@ -376,6 +400,10 @@ struct di_pre_stru_s {
|
||||
bool retry_en;
|
||||
unsigned int retry_index;
|
||||
unsigned int retry_cnt;
|
||||
/*****************/
|
||||
bool combing_fix_en;
|
||||
unsigned int comb_mode;
|
||||
/*struct di_patch_mov_s mov;*/
|
||||
};
|
||||
|
||||
struct di_post_stru_s {
|
||||
@@ -473,4 +501,6 @@ struct di_buf_s *get_di_buf(int queue_idx, int *start_pos);
|
||||
|
||||
#define pr_error(fmt, args ...) pr_err("DI: " fmt, ## args)
|
||||
|
||||
/******************************************/
|
||||
/*#define DI_KEEP_HIS 0*/
|
||||
#endif
|
||||
|
||||
@@ -475,8 +475,10 @@ void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p)
|
||||
di_pre_stru_p->unreg_req_flag_irq);
|
||||
pr_info("reg_req_flag = %d\n",
|
||||
di_pre_stru_p->reg_req_flag);
|
||||
#ifdef DI_KEEP_HIS
|
||||
pr_info("reg_req_flag_irq = %d\n",
|
||||
di_pre_stru_p->reg_req_flag_irq);
|
||||
#endif
|
||||
pr_info("cur_width = %d\n",
|
||||
di_pre_stru_p->cur_width);
|
||||
pr_info("cur_height = %d\n",
|
||||
@@ -547,8 +549,10 @@ static int dump_di_pre_stru_seq(struct seq_file *seq, void *v)
|
||||
di_pre_stru_p->unreg_req_flag_irq);
|
||||
seq_printf(seq, "%-25s = %d\n", "reg_req_flag",
|
||||
di_pre_stru_p->reg_req_flag);
|
||||
#ifdef DI_KEEP_HIS
|
||||
seq_printf(seq, "%-25s = %d\n", "reg_req_flag_irq",
|
||||
di_pre_stru_p->reg_req_flag_irq);
|
||||
#endif
|
||||
seq_printf(seq, "%-25s = %d\n", "cur_width",
|
||||
di_pre_stru_p->cur_width);
|
||||
seq_printf(seq, "%-25s = %d\n", "cur_height",
|
||||
@@ -583,6 +587,10 @@ static int dump_di_pre_stru_seq(struct seq_file *seq, void *v)
|
||||
di_pre_stru_p->bypass_pre ? "true" : "false");
|
||||
seq_printf(seq, "%-25s = %s\n", "invert_flag",
|
||||
di_pre_stru_p->invert_flag ? "true" : "false");
|
||||
seq_printf(seq, "%-25s = %s\n", "combing_fix_en",
|
||||
di_pre_stru_p->combing_fix_en ? "true" : "false");
|
||||
seq_printf(seq, "%-25s = %d\n", "comb_mode",
|
||||
di_pre_stru_p->comb_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -875,6 +883,7 @@ void dump_vframe(struct vframe_s *vf)
|
||||
pr_info("pixel_ratio %d list %p\n",
|
||||
vf->pixel_ratio, &vf->list);
|
||||
pr_info("di_pulldown 0x%x\n", vf->di_pulldown);
|
||||
pr_info("di_gmv 0x%x\n", vf->di_gmv);
|
||||
}
|
||||
|
||||
void print_di_buf(struct di_buf_s *di_buf, int format)
|
||||
@@ -1071,6 +1080,30 @@ void dump_afbcd_reg(void)
|
||||
VD2_AFBCD1_MISC_CTRL, RDMA_RD(VD2_AFBCD1_MISC_CTRL));
|
||||
}
|
||||
|
||||
static int dbg_patch_mov_data_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct di_dev_s *de_devp = get_di_de_devp();
|
||||
struct di_patch_mov_s *pmov = &de_devp->mov;
|
||||
int i;
|
||||
|
||||
seq_printf(seq, "mode:%d\n", pmov->mode);
|
||||
seq_printf(seq, "en_support:%d\n", pmov->en_support);
|
||||
seq_printf(seq, "number:%d\n", pmov->nub);
|
||||
seq_printf(seq, "update:%d\n", pmov->update);
|
||||
for (i = 0; i < DI_PATCH_MOV_MAX_NUB; i++) {
|
||||
seq_printf(seq, "index:[%d]\n", i);
|
||||
seq_printf(seq, "\treg:0x%x\n", pmov->reg_addr[i]);
|
||||
if (i < pmov->nub)
|
||||
seq_printf(seq, "\t\t= 0x%x\n",
|
||||
RDMA_RD(pmov->reg_addr[i]));
|
||||
seq_printf(seq, "\tdb_val:0x%x\n", pmov->val_db[i].val);
|
||||
seq_printf(seq, "\tdb_en :0x%x\n", pmov->val_db[i].en);
|
||||
seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].val);
|
||||
seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].en);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*2018-08-17 add debugfs*/
|
||||
/*same as dump_state*/
|
||||
static int seq_file_di_state_show(struct seq_file *seq, void *v)
|
||||
@@ -1250,6 +1283,7 @@ DEFINE_SHOW_DI(seq_file_dump_di_reg);
|
||||
DEFINE_SHOW_DI(seq_file_dump_mif_size_state);
|
||||
DEFINE_SHOW_DI(seq_file_afbc);
|
||||
DEFINE_SHOW_DI(reg_cue_int);
|
||||
DEFINE_SHOW_DI(dbg_patch_mov_data);
|
||||
|
||||
struct di_debugfs_files_t {
|
||||
const char *name;
|
||||
@@ -1263,6 +1297,7 @@ static struct di_debugfs_files_t di_debugfs_files[] = {
|
||||
{"dumpmif", S_IFREG | 0644, &seq_file_dump_mif_size_state_fops},
|
||||
{"dumpafbc", S_IFREG | 0644, &seq_file_afbc_fops},
|
||||
{"reg_cue", S_IFREG | 0644, ®_cue_int_fops},
|
||||
{"dumpmov", S_IFREG | 0644, &dbg_patch_mov_data_fops},
|
||||
};
|
||||
|
||||
void di_debugfs_init(void)
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "deinterlace.h"
|
||||
#include "register.h"
|
||||
#include "register_nr4.h"
|
||||
#include "nr_drv.h"
|
||||
|
||||
#ifdef DET3D
|
||||
#include "detect3d.h"
|
||||
#endif
|
||||
@@ -139,6 +141,8 @@ static void ma_di_init(void)
|
||||
/* mtn setting */
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) {
|
||||
DI_Wr_reg_bits(DI_MTN_CTRL, 1, 0, 1);
|
||||
DI_Wr_reg_bits(DI_MTN_CTRL, 1, 30, 1);
|
||||
DI_Wr_reg_bits(DI_MTN_CTRL, 0xf, 24, 4);
|
||||
DI_Wr(DI_MTN_1_CTRL1, 0x202015);
|
||||
} else
|
||||
DI_Wr(DI_MTN_1_CTRL1, 0xa0202015);
|
||||
@@ -331,7 +335,7 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr)
|
||||
if (!lmv_lock_win_en)
|
||||
return;
|
||||
|
||||
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
pr_debug("%s: only support G12A and after chips.\n", __func__);
|
||||
return;
|
||||
}
|
||||
@@ -431,7 +435,11 @@ static void pre_hold_block_mode_config(void)
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
DI_Wr(DI_PRE_HOLD, 0);
|
||||
/* go field after 2 lines */
|
||||
#ifdef OLD_PRE_GL
|
||||
DI_Wr(DI_PRE_GL_CTRL, (0x80000000|line_num_pre_frst));
|
||||
#else
|
||||
di_hpre_gl_sw(false);
|
||||
#endif
|
||||
} else if (is_meson_txlx_cpu()) {
|
||||
/* setup pre process ratio to 66.6%*/
|
||||
DI_Wr(DI_PRE_HOLD, (1 << 31) | (1 << 16) | 3);
|
||||
@@ -754,9 +762,10 @@ void enable_di_pre_aml(
|
||||
/*
|
||||
* enable&disable contwr txt
|
||||
*/
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B))
|
||||
RDMA_WR_BITS(DI_MTN_CTRL, madi_en?5:0, 29, 3);
|
||||
else
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) {
|
||||
RDMA_WR_BITS(DI_MTN_CTRL, madi_en, 29, 1);
|
||||
RDMA_WR_BITS(DI_MTN_CTRL, madi_en, 31, 1);
|
||||
} else
|
||||
RDMA_WR_BITS(DI_MTN_1_CTRL1, madi_en?5:0, 29, 3);
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
|
||||
@@ -3227,11 +3236,28 @@ void pre_frame_reset_g12(unsigned char madi_en,
|
||||
RDMA_WR_BITS(MCVECWR_CAN_SIZE, 0, 14, 1);
|
||||
RDMA_WR_BITS(MCINFWR_CAN_SIZE, 0, 14, 1);
|
||||
|
||||
#ifdef OLD_PRE_GL
|
||||
reg_val = 0xc3200000 | line_num_pre_frst;
|
||||
RDMA_WR(DI_PRE_GL_CTRL, reg_val);
|
||||
reg_val = 0x83200000 | line_num_pre_frst;
|
||||
RDMA_WR(DI_PRE_GL_CTRL, reg_val);
|
||||
#else
|
||||
di_hpre_gl_sw(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*2019-12-25 by feijun*/
|
||||
void di_hpre_gl_sw(bool on)
|
||||
{
|
||||
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
|
||||
return;
|
||||
if (on)
|
||||
RDMA_WR(DI_PRE_GL_CTRL,
|
||||
0x80200000 | line_num_pre_frst);
|
||||
else
|
||||
RDMA_WR(DI_PRE_GL_CTRL, 0xc0000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* frame + soft reset for the pre modules
|
||||
*/
|
||||
@@ -3362,6 +3388,15 @@ void diwr_set_power_control(unsigned char enable)
|
||||
enable?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN);
|
||||
}
|
||||
|
||||
void di_hdr2_hist_init(void)
|
||||
{
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) {
|
||||
RDMA_WR(DI_HDR2_HIST_CTRL, 0x5510);
|
||||
RDMA_WR(DI_HDR2_HIST_H_START_END, 0x10000);
|
||||
RDMA_WR(DI_HDR2_HIST_V_START_END, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
void di_top_gate_control(bool top_en, bool mc_en)
|
||||
{
|
||||
if (top_en) {
|
||||
@@ -3835,30 +3870,35 @@ void pulldown_vof_win_config(struct pulldown_detected_s *wins)
|
||||
wins->regs[3].win_vs, 17, 12);
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y,
|
||||
wins->regs[3].win_ve, 1, 12);
|
||||
|
||||
/* revert the setting of top two lines do weave for */
|
||||
/* interlace video, suggest by vlsi-feijun */
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
(wins->regs[0].win_ve > wins->regs[0].win_vs)
|
||||
? 1 : 0, 16, 1);
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
wins->regs[0].blend_mode, 8, 2);
|
||||
/*wins->regs[0].blend_mode*/
|
||||
0x03, 8, 2);
|
||||
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
(wins->regs[1].win_ve > wins->regs[1].win_vs)
|
||||
? 1 : 0, 17, 1);
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
wins->regs[1].blend_mode, 10, 2);
|
||||
/*wins->regs[1].blend_mode*/
|
||||
0x03, 10, 2);
|
||||
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
(wins->regs[2].win_ve > wins->regs[2].win_vs)
|
||||
? 1 : 0, 18, 1);
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
wins->regs[2].blend_mode, 12, 2);
|
||||
/*wins->regs[2].blend_mode*/
|
||||
0x03, 12, 2);
|
||||
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
(wins->regs[3].win_ve > wins->regs[3].win_vs)
|
||||
? 1 : 0, 19, 1);
|
||||
DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL,
|
||||
wins->regs[3].blend_mode, 14, 2);
|
||||
/*wins->regs[3].blend_mode*/
|
||||
0x03, 14, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -3868,6 +3908,7 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr)
|
||||
unsigned int table_name = 0, nr_table = 0;
|
||||
bool ctrl_reg_flag = false;
|
||||
struct am_reg_s *regs_p = NULL;
|
||||
bool mov_flg = false;
|
||||
|
||||
if (pq_load_dbg == 1)
|
||||
return;
|
||||
@@ -3889,6 +3930,11 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr)
|
||||
addr = regs_p->addr;
|
||||
value = regs_p->val;
|
||||
mask = regs_p->mask;
|
||||
if (nr_demo_flag) {
|
||||
if (addr == NR4_TOP_CTRL)
|
||||
mask &= ~(0x7 << 6);
|
||||
}
|
||||
|
||||
if (pq_load_dbg == 2)
|
||||
pr_info("[%u][0x%x] = [0x%x]&[0x%x]\n",
|
||||
i, addr, value, mask);
|
||||
@@ -3911,7 +3957,9 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr)
|
||||
}
|
||||
if (table_name & nr_table)
|
||||
ctrl_reg_flag = set_nr_ctrl_reg_table(addr, value);
|
||||
if (!ctrl_reg_flag)
|
||||
if (table_name & TABLE_NAME_DI)
|
||||
mov_flg = di_patch_mov_db(addr, value);
|
||||
if (!ctrl_reg_flag && !mov_flg)
|
||||
DI_Wr(addr, value);
|
||||
if (pq_load_dbg == 2)
|
||||
pr_info("[%u][0x%x] = [0x%x] %s\n", i, addr,
|
||||
|
||||
@@ -184,6 +184,7 @@ void di_post_switch_buffer(
|
||||
);
|
||||
void di_post_read_reverse_irq(bool reverse,
|
||||
unsigned char mc_pre_flag, bool mc_enable);
|
||||
void di_hdr2_hist_init(void);
|
||||
void di_top_gate_control(bool top_en, bool mc_en);
|
||||
void di_pre_gate_control(bool enable, bool mc_enable);
|
||||
void di_post_gate_control(bool gate);
|
||||
@@ -201,6 +202,7 @@ void pulldown_vof_win_config(struct pulldown_detected_s *wins);
|
||||
void di_load_regs(struct di_pq_parm_s *di_pq_ptr);
|
||||
void pre_frame_reset_g12(unsigned char madi_en, unsigned char mcdi_en);
|
||||
void pre_frame_reset(void);
|
||||
void di_hpre_gl_sw(bool on);
|
||||
void di_interrupt_ctrl(unsigned char ma_en,
|
||||
unsigned char det3d_en, unsigned char nrds_en,
|
||||
unsigned char post_wr, unsigned char mc_en);
|
||||
|
||||
@@ -161,7 +161,6 @@ static unsigned int combing_bias_static_setting[MAX_NUM_DI_REG] = {
|
||||
0x00000166
|
||||
};
|
||||
|
||||
|
||||
static unsigned int combing_normal_setting[MAX_NUM_DI_REG] = {
|
||||
0x00202015,
|
||||
0x1A1A3A62,
|
||||
@@ -182,18 +181,18 @@ static unsigned int combing_normal_setting[MAX_NUM_DI_REG] = {
|
||||
};
|
||||
|
||||
static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = {
|
||||
0x00202015,
|
||||
0x1A1A3A62,
|
||||
0x15200101,
|
||||
0x01200440,
|
||||
0x74200D0D,
|
||||
0x0D5A1520,
|
||||
0x0A0A0201,
|
||||
0x1A1A2662,
|
||||
0x0D200302,
|
||||
0x02020606,
|
||||
0x05080344,
|
||||
0x40020a04,
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
0x40020a04, /* 11 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
0x00200204, /* 0x00400204 */
|
||||
@@ -203,17 +202,17 @@ static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = {
|
||||
};
|
||||
|
||||
static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = {
|
||||
0x00202015,
|
||||
0x1A1A3A62,
|
||||
0x15200101,
|
||||
0x01200440,
|
||||
0x74200D0D,
|
||||
0x0D5A1520,
|
||||
0x0A0A0201,
|
||||
0x1A1A2662,
|
||||
0x0D200302,
|
||||
0x02020606,
|
||||
0x05080344,
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x60000404, /* 0x40020a04*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
@@ -222,6 +221,177 @@ static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = {
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000131
|
||||
};
|
||||
|
||||
/**************************************************
|
||||
*
|
||||
**************************************************/
|
||||
/*same as: combing_bias_motion_setting*/
|
||||
static const unsigned int combing_bias_p_ori[] = {
|
||||
/**/
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
0x40020a04, /* 11 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
0x00200204, /* 0x00400204 */
|
||||
0x00012002, /* 0x00016404 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000142
|
||||
};
|
||||
|
||||
static const unsigned int combing_very_p_ori[] = {
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x60000404, /* 0x40020a04*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
0x00200204, /* 0x00400204 */
|
||||
0x00012002, /* 0x00016404 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000131
|
||||
};
|
||||
|
||||
static const unsigned int combing_bias_p_1080i[] = {
|
||||
/**/
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
0x40020a04, /* 11 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x0001ff0c,
|
||||
0x00400204,
|
||||
0x00016404,
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000142
|
||||
};
|
||||
|
||||
static const unsigned int combing_very_p_1080i[] = {
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200101, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x40020a04,
|
||||
0x0001ff0c,
|
||||
0x00400204,
|
||||
0x00016404,
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000131
|
||||
};
|
||||
|
||||
/*same as combing_bias_motion_setting ex:*/
|
||||
/* 3nd : from 0x15200101 to 0x15200301*/
|
||||
static unsigned int combing_bias_p_480i[] = {
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200301, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
0x40020a04, /* 11 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
0x00200204, /* 0x00400204 */
|
||||
0x00012002, /* 0x00016404 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000142
|
||||
};
|
||||
|
||||
/*same as combing_very_motion_setting ex:*/
|
||||
/* 3nd : from 0x15200101 to 0x15200301*/
|
||||
static unsigned int combing_very_p_480i[] = {
|
||||
0x00202015, /* 0 */
|
||||
0x1A1A3A62, /* 1 */
|
||||
0x15200301, /* 2 */
|
||||
0x01200440, /* 3 */
|
||||
0x74200D0D, /* 4 */
|
||||
0x0D5A1520, /* 5 */
|
||||
0x0A0A0201, /* 6 */
|
||||
0x1A1A2662, /* 7 */
|
||||
0x0D200302, /* 8 */
|
||||
0x02020606, /* 9 */
|
||||
0x05080344, /* 10 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao begin*/
|
||||
0x60000404, /* 0x40020a04*/
|
||||
0x0001FF12, /* 0x0001ff0c */
|
||||
0x00200204, /* 0x00400204 */
|
||||
0x00012002, /* 0x00016404 */
|
||||
/*idea from mingliang.dong & vlsi zheng.bao end*/
|
||||
0x00000131
|
||||
};
|
||||
|
||||
static unsigned int di_mtn_p_mode;
|
||||
|
||||
void com_patch_pre_sw_set(unsigned int mode)
|
||||
{
|
||||
unsigned int *p1, *p2;
|
||||
/* mode is 0: ori */
|
||||
/* mode is 1: 1080i */
|
||||
/* mode is 2: 480i */
|
||||
if (mode == di_mtn_p_mode)
|
||||
return;
|
||||
|
||||
p1 = &combing_bias_motion_setting[0];
|
||||
p2 = &combing_very_motion_setting[0];
|
||||
if (mode == 0) {
|
||||
memcpy(p1, &combing_bias_p_ori[0],
|
||||
sizeof(combing_bias_p_ori));
|
||||
memcpy(p2, &combing_very_p_ori[0],
|
||||
sizeof(combing_very_p_ori));
|
||||
di_mtn_p_mode = 0;
|
||||
} else if (mode == 1) {
|
||||
memcpy(p1, &combing_bias_p_1080i[0],
|
||||
sizeof(combing_bias_p_1080i));
|
||||
memcpy(p2, &combing_very_p_1080i[0],
|
||||
sizeof(combing_very_p_1080i));
|
||||
di_mtn_p_mode = 1;
|
||||
} else if (mode == 2) {
|
||||
memcpy(p1, &combing_bias_p_480i[0],
|
||||
sizeof(combing_bias_p_480i));
|
||||
memcpy(p2, &combing_very_p_480i[0],
|
||||
sizeof(combing_very_p_480i));
|
||||
di_mtn_p_mode = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*special for resolution test file*/
|
||||
static unsigned int combing_resolution_setting[MAX_NUM_DI_REG] = {
|
||||
0x00202015,
|
||||
@@ -301,6 +471,7 @@ void mtn_int_combing_glbmot(void)
|
||||
if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) {/*from VLSI yanling.liu*/
|
||||
combing_glbmot_radprat[0] = 30;
|
||||
}
|
||||
di_mtn_p_mode = 0;
|
||||
}
|
||||
void adpative_combing_exit(void)
|
||||
{
|
||||
@@ -495,13 +666,19 @@ static unsigned int small_local_mtn = 70;
|
||||
module_param(small_local_mtn, uint, 0644);
|
||||
MODULE_PARM_DESC(small_local_mtn, "small_local_mtn");
|
||||
|
||||
static unsigned int small_local_mtn1 = 30;
|
||||
module_param(small_local_mtn1, uint, 0644);
|
||||
MODULE_PARM_DESC(small_local_mtn1, "small_local_mtn1");
|
||||
|
||||
unsigned int adp_set_mtn_ctrl10(unsigned int diff, unsigned int dlvel,
|
||||
unsigned int frame_diff_avg)
|
||||
{
|
||||
int istp = 0, idats = 0, idatm = 0, idatr = 0;
|
||||
unsigned int rst = 0;
|
||||
|
||||
if (frame_diff_avg < small_local_mtn)
|
||||
if (
|
||||
(frame_diff_avg < small_local_mtn) &&
|
||||
(frame_diff_avg > small_local_mtn1))
|
||||
rst = combing_very_motion_setting[9];
|
||||
else if (dlvel == 0) {
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
|
||||
@@ -636,7 +813,7 @@ MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg");
|
||||
/*from VLSI yanling.liu, the patch fix TL1 1080I in some dark */
|
||||
/*scenes and roller coasters have small sawtooth, when turn off*/
|
||||
/*combing_fix_en, set the registers*/
|
||||
void fix_tl1_1080i_sawtooth_patch(void)
|
||||
static void fix_tl1_1080i_sawtooth_patch(void)
|
||||
{
|
||||
DI_Wr(0x1741, 0x0A0A1A22);
|
||||
DI_Wr(0x1742, 0x0a100101);
|
||||
@@ -651,6 +828,35 @@ void fix_tl1_1080i_sawtooth_patch(void)
|
||||
DI_Wr(0x17af, 0x60020a60);
|
||||
}
|
||||
|
||||
static void fix_tl1_1080i_patch2(void)
|
||||
{
|
||||
DI_Wr(0x1741, 0x010a010a);
|
||||
DI_Wr(0x1742, 0x01010101);
|
||||
DI_Wr(0x1743, 0x00000101);
|
||||
DI_Wr(0x1744, 0x00000101);
|
||||
DI_Wr(0x17a9, 0x01010102);
|
||||
DI_Wr(0x17aa, 0x02020101);
|
||||
DI_Wr(0x17ab, 0x010a010a);
|
||||
DI_Wr(0x17ac, 0x010a0102);
|
||||
DI_Wr(0x17ad, 0x08080808);
|
||||
DI_Wr(0x17ae, 0x01010101);
|
||||
DI_Wr(0x17af, 0xff00031f);
|
||||
}
|
||||
|
||||
void fix_tl1_1080i_patch_sel(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0:/*not set*/
|
||||
break;
|
||||
case 1:
|
||||
fix_tl1_1080i_sawtooth_patch();
|
||||
break;
|
||||
case 2:
|
||||
fix_tl1_1080i_patch2();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int combing_cnt;
|
||||
int combing_diff_min = 2000;
|
||||
int combing_diff_max = 2000;
|
||||
@@ -714,9 +920,16 @@ int adaptive_combing_fixing(
|
||||
combing_cnt = combing_cnt + 1;
|
||||
else
|
||||
combing_cnt = 0;
|
||||
if (glb_mot[0] < combing_diff_min && glb_mot[1] > combing_diff_max &&
|
||||
combing_cnt <= combing_cnt_thd)
|
||||
glb_mot[0] = glb_mot[1];
|
||||
if (
|
||||
is_meson_txhd_cpu() ||
|
||||
is_meson_tl1_cpu() ||
|
||||
is_meson_tm2_cpu()) {
|
||||
if (
|
||||
glb_mot[0] < combing_diff_min &&
|
||||
glb_mot[1] > combing_diff_max &&
|
||||
combing_cnt <= combing_cnt_thd)
|
||||
glb_mot[0] = glb_mot[1];
|
||||
}
|
||||
glb_mot_avg5 =
|
||||
(glb_mot[0] + glb_mot[1] + glb_mot[2] + glb_mot[3] +
|
||||
glb_mot[4]) / 5;
|
||||
@@ -816,9 +1029,10 @@ module_param_named(cmb_adpset_cnt, cmb_adpset_cnt, int, 0644);
|
||||
static const struct mtn_op_s di_ops_mtn = {
|
||||
.mtn_int_combing_glbmot = mtn_int_combing_glbmot,
|
||||
.adpative_combing_exit = adpative_combing_exit,
|
||||
.fix_tl1_1080i_sawtooth_patch = fix_tl1_1080i_sawtooth_patch,
|
||||
.fix_tl1_1080i_patch_sel = fix_tl1_1080i_patch_sel,
|
||||
.adaptive_combing_fixing = adaptive_combing_fixing,
|
||||
.adpative_combing_config = adpative_combing_config,
|
||||
.com_patch_pre_sw_set = com_patch_pre_sw_set,
|
||||
/*.module_para = dim_seq_file_module_para_mtn,*/
|
||||
};
|
||||
|
||||
|
||||
@@ -39,12 +39,13 @@ struct combing_status_s *adpative_combing_config(unsigned int width,
|
||||
unsigned int height,
|
||||
enum vframe_source_type_e src_type, bool prog,
|
||||
enum tvin_sig_fmt_e fmt);
|
||||
extern void fix_tl1_1080i_sawtooth_patch(void);
|
||||
void fix_tl1_1080i_patch_sel(unsigned int mode);
|
||||
int adaptive_combing_fixing(
|
||||
struct combing_status_s *cmb_status,
|
||||
unsigned int field_diff, unsigned int frame_diff,
|
||||
int bit_mode);
|
||||
void adpative_combing_exit(void);
|
||||
extern void mtn_int_combing_glbmot(void);
|
||||
void com_patch_pre_sw_set(unsigned int mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -111,7 +111,7 @@ bool di_attach_ops_nr(const struct nr_op_s **ops);
|
||||
struct mtn_op_s {
|
||||
void (*mtn_int_combing_glbmot)(void);
|
||||
void (*adpative_combing_exit)(void);
|
||||
void (*fix_tl1_1080i_sawtooth_patch)(void);
|
||||
void (*fix_tl1_1080i_patch_sel)(unsigned int mode);
|
||||
int (*adaptive_combing_fixing)(
|
||||
struct combing_status_s *cmb_status,
|
||||
unsigned int field_diff, unsigned int frame_diff,
|
||||
@@ -123,6 +123,7 @@ struct mtn_op_s {
|
||||
enum vframe_source_type_e src_type,
|
||||
bool prog,
|
||||
enum tvin_sig_fmt_e fmt);
|
||||
void (*com_patch_pre_sw_set)(unsigned int mode);
|
||||
int (*module_para)(struct seq_file *seq);
|
||||
};
|
||||
|
||||
|
||||
@@ -235,6 +235,29 @@ static int dif01_ratio = 10;
|
||||
module_param(dif01_ratio, int, 0644);
|
||||
MODULE_PARM_DESC(dif01_ratio, "dif01_ratio");
|
||||
|
||||
static int nflagch4_ratio = 1;
|
||||
module_param(nflagch4_ratio, int, 0644);
|
||||
MODULE_PARM_DESC(nflagch4_ratio, "nflagch4_ratio");
|
||||
|
||||
static int nflagch5_ratio = 2;
|
||||
module_param(nflagch5_ratio, int, 0644);
|
||||
MODULE_PARM_DESC(nflagch5_ratio, "nflagch5_ratio");
|
||||
|
||||
static int nflagch4_th = 0;
|
||||
module_param(nflagch4_th, int, 0644);
|
||||
MODULE_PARM_DESC(nflagch4_th, "nflagch4_th");
|
||||
|
||||
static int nflagch5_th = 0;
|
||||
module_param(nflagch5_th, int, 0644);
|
||||
MODULE_PARM_DESC(nflagch5_th, "nflagch5_th");
|
||||
|
||||
static int dif02_flag = 1;
|
||||
module_param(dif02_flag, int, 0644);
|
||||
MODULE_PARM_DESC(dif02_flag, "dif02_flag");
|
||||
|
||||
static int dif02_ratio = 20;
|
||||
module_param(dif02_ratio, int, 0644);
|
||||
MODULE_PARM_DESC(dif02_ratio, "dif02_ratio");
|
||||
|
||||
static int flm22_force;
|
||||
|
||||
@@ -697,6 +720,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
int nFlgChk1 = 0;
|
||||
int nFlgChk2 = 0;
|
||||
int nFlgChk3 = 0; /* for Mit32VHLine */
|
||||
int nFlgChk4 = 0;
|
||||
int nFlgChk5 = 0;
|
||||
int nMean = 0;
|
||||
|
||||
int luma_avg = 0;
|
||||
int flm32_dif02_gap = 0;
|
||||
@@ -749,7 +775,11 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
nSM += nT1;
|
||||
}
|
||||
}
|
||||
nAV11 = (nSM - nMx + nT2 / 2) / (nT2 - 1);
|
||||
/* for coverity error,"nT2 - 1" which may be zero */
|
||||
if (nT2 != 1)
|
||||
nAV11 = (nSM - nMx + nT2 / 2) / (nT2 - 1);
|
||||
else
|
||||
pr_info("%s: Error nT2 is one\n", __func__);
|
||||
|
||||
nAV1 = (sFrmDifAvgRat * nAV11 + (32 - sFrmDifAvgRat) * nAV12);
|
||||
nAV1 = ((nAV1 + 16) >> 5);
|
||||
@@ -819,6 +849,35 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
nFlgChk1 = 0;
|
||||
nFlgChk2 = 0;
|
||||
}
|
||||
//nFlgChk4/5 large dif change quit mode
|
||||
if (
|
||||
pFlg32[HISDETNUM - 1] > 1 && (dif02_flag ||
|
||||
nDif02[HISDIFNUM - 1] > (1 << dif02_ratio))) {
|
||||
nFlgChk4 = nDif02[HISDIFNUM - 1] - nDif02[HISDIFNUM - 6];
|
||||
if (nFlgChk4 < 0)
|
||||
nFlgChk4 = -nFlgChk4;
|
||||
nFlgChk4 = nFlgChk4;
|
||||
nMean = (nDif02[HISDIFNUM - 1] + nDif01[HISDIFNUM - 6]) / 2;
|
||||
nFlgChk4 = nflagch4_ratio * nFlgChk4 / nMean;
|
||||
} else {
|
||||
nFlgChk4 = 0;
|
||||
}
|
||||
if (
|
||||
pFlg32[HISDETNUM - 1] == 1 ||
|
||||
pFlg32[HISDETNUM - 1] == 2 ||
|
||||
pFlg32[HISDETNUM - 1] == 4) {
|
||||
nFlgChk5 = nDif01[HISDIFNUM - 1] - nDif01[HISDIFNUM - 6];
|
||||
if (nFlgChk5 < 0)
|
||||
nFlgChk5 = -nFlgChk5;
|
||||
nMean = (nDif01[HISDIFNUM - 1] + nDif01[HISDIFNUM - 6]) / 2;
|
||||
nFlgChk5 = nflagch5_ratio * nFlgChk5 / nMean;
|
||||
} else {
|
||||
nFlgChk5 = 0;
|
||||
}
|
||||
if (prt_flg)
|
||||
sprintf(debug_str + strlen(debug_str),
|
||||
"nFlgChk4/5=(%2d,%2d)\n",
|
||||
nFlgChk4, nFlgChk5);
|
||||
|
||||
nT2 = 5 * nDif02[HISDIFNUM - 1] / (nMn + sFrmDifLgTDif + 1);
|
||||
nT2 = nT2>>1;
|
||||
@@ -839,7 +898,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
if (nSTP > 16)
|
||||
nSTP = 16;
|
||||
/*patch for dark scenes don't into pulldown32 by vlsi yanling*/
|
||||
if (((nMx + nMn/2) / (nMn + 1)) < flm32_dif02_gap)
|
||||
if (
|
||||
((nMx + nMn / 2) / (nMn + 1)) < flm32_dif02_gap &&
|
||||
pFlg32[HISDETNUM - 1] > 1)
|
||||
nSTP = 0;
|
||||
/*---------------*/
|
||||
for (nT0 = 1; nT0 < HISDETNUM; nT0++) {
|
||||
@@ -913,6 +974,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
}
|
||||
|
||||
nFlg12[nT0] = ((nSTP + 8) >> 4);
|
||||
|
||||
if (nT0 == 5 && nMIX == 1 && nFlg01[nT0] == 0)
|
||||
nFlg12[nT0] = 0;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@@ -964,7 +1028,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
(nFlgChk3 > flm32_ck13_rtn))
|
||||
|| (nFlgChk2 > flm32_chk2_rtn)
|
||||
|| ((pFlg32[HISDETNUM-1] == 4) &&
|
||||
(nFlgChk3 > flm32_chk3_rtn))) {
|
||||
(nFlgChk3 > flm32_chk3_rtn)) ||
|
||||
(nFlgChk4 > nflagch4_th ||
|
||||
nFlgChk5 > nflagch5_th)) {
|
||||
pRDat->pMod32[HISDETNUM - 1] = 0;
|
||||
pRDat->pFlg32[HISDETNUM - 1] = 0;
|
||||
|
||||
@@ -1376,8 +1442,17 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02,
|
||||
}
|
||||
nFlgChk6 = nFlgChk6 / 6;
|
||||
|
||||
nAV21 = (nSM21 + nL21 / 2) / nL21; /* High average */
|
||||
nAV22 = (nSM22 + nL22 / 2) / nL22; /* Low average */
|
||||
/* for coverity error,"nL21/nL22" which may be zero */
|
||||
if (nL21)
|
||||
nAV21 = (nSM21 + nL21 / 2) / nL21; /* High average */
|
||||
else
|
||||
pr_info("%s: Error nL21 is zero\n", __func__);
|
||||
|
||||
if (nL22)
|
||||
nAV22 = (nSM22 + nL22 / 2) / nL22; /* Low average */
|
||||
else
|
||||
pr_info("%s: Error nL22 is zero\n", __func__);
|
||||
|
||||
nOfst = nAV21 - nAV22;
|
||||
|
||||
if (prt_flg)
|
||||
|
||||
@@ -47,6 +47,8 @@ module_param_named(nr2_en, nr2_en, uint, 0644);
|
||||
|
||||
static bool nr_ctrl_reg;
|
||||
|
||||
bool nr_demo_flag;
|
||||
|
||||
int global_bs_calc_sw(int *pGbsVldCnt,
|
||||
int *pGbsVldFlg,
|
||||
int *pGbs,
|
||||
@@ -1196,6 +1198,18 @@ static void nr_all_ctrl(bool enable)
|
||||
DI_Wr_reg_bits(DNR_CTRL, value, 16, 1);
|
||||
|
||||
}
|
||||
|
||||
static void nr_demo_mode(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 6, 3);
|
||||
nr_demo_flag = 1;
|
||||
} else {
|
||||
DI_Wr_reg_bits(NR4_TOP_CTRL, 7, 6, 3);
|
||||
nr_demo_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t nr_dbg_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buff, size_t count)
|
||||
@@ -1208,6 +1222,15 @@ static ssize_t nr_dbg_store(struct device *dev,
|
||||
nr_all_ctrl(false);
|
||||
else if (!strcmp(parm[0], "enable"))
|
||||
nr_all_ctrl(true);
|
||||
else if (!strcmp(parm[0], "demo")) {
|
||||
if (!strcmp(parm[1], "enable")) {
|
||||
nr_demo_mode(true);
|
||||
pr_info("nr demo enable\n");
|
||||
} else if (!strcmp(parm[1], "disable")) {
|
||||
nr_demo_mode(false);
|
||||
pr_info("nr demo disable\n");
|
||||
}
|
||||
}
|
||||
|
||||
kfree(buf_orig);
|
||||
return count;
|
||||
|
||||
@@ -186,5 +186,6 @@ bool set_nr_ctrl_reg_table(unsigned int addr, unsigned int value);
|
||||
|
||||
extern void cue_int(struct vframe_s *vf);
|
||||
|
||||
extern bool nr_demo_flag;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -180,6 +180,13 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr,
|
||||
#define MCINFWR_Y 0x37f6
|
||||
#define MCINFWR_CTRL 0x37f7
|
||||
#define MCINFWR_CAN_SIZE 0x37f8
|
||||
|
||||
/* from TM2 new added */
|
||||
/* DI HDR2 */
|
||||
#define DI_HDR2_HIST_CTRL 0x37ad
|
||||
#define DI_HDR2_HIST_H_START_END 0x37ae
|
||||
#define DI_HDR2_HIST_V_START_END 0x37af
|
||||
|
||||
/* DI SCALE */
|
||||
#define DI_SCO_FIFO_CTRL 0x374e
|
||||
#define DI_SC_TOP_CTRL 0x374f
|
||||
|
||||
@@ -127,6 +127,13 @@ int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len)
|
||||
}
|
||||
EXPORT_SYMBOL(DI_POST_WR_REG_BITS);
|
||||
|
||||
void DI_POST_UPDATE_MC(void)
|
||||
{
|
||||
if (dil_api && dil_api->post_update_mc)
|
||||
dil_api->post_update_mc();
|
||||
}
|
||||
EXPORT_SYMBOL(DI_POST_UPDATE_MC);
|
||||
|
||||
/***************************************
|
||||
* reserved mem for di *
|
||||
**************************************/
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
struct di_ext_ops {
|
||||
unsigned int (*di_post_reg_rd)(unsigned int addr);
|
||||
int (*di_post_wr_reg_bits)(u32 adr, u32 val, u32 start, u32 len);
|
||||
void (*post_update_mc)(void);
|
||||
};
|
||||
|
||||
#endif /*__DI_LOCAL_H__*/
|
||||
|
||||
15
drivers/amlogic/media/di_multi/Kconfig
Normal file
15
drivers/amlogic/media/di_multi/Kconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Deinterlace driver configuration
|
||||
#
|
||||
|
||||
menu "DI_MULTI driver"
|
||||
|
||||
config AMLOGIC_MEDIA_DEINTERLACE
|
||||
tristate "DI_MULTI driver"
|
||||
default n
|
||||
help
|
||||
Select to enable AMLOGIC DEINTERLACE driver
|
||||
process interlace source need three continueed fields,
|
||||
wave progressive source with two interlace fields from
|
||||
one progreesive fields
|
||||
endmenu
|
||||
34
drivers/amlogic/media/di_multi/Makefile
Normal file
34
drivers/amlogic/media/di_multi/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
# # Makefile for the Post Process Manager device #
|
||||
ifeq ($(TARGET_BUILD_VARIANT),userdebug)
|
||||
ccflags-y := -D DEBUG_SUPPORT
|
||||
ccflags-y := -DDEBUG
|
||||
else
|
||||
ccflags-y := -DDEBUG
|
||||
endif
|
||||
ccflags-y += -I.
|
||||
CFLAGS_dim.o := -I$(src)
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += dim.o
|
||||
dim-objs += deinterlace.o
|
||||
dim-objs += deinterlace_hw.o
|
||||
#dim-objs += deinterlace_mtn.o
|
||||
dim-objs += deinterlace_dbg.o
|
||||
#dim-objs += nr_drv.o
|
||||
#dim-objs += pulldown_drv.o
|
||||
#dim-objs += detect3d.o
|
||||
dim-objs += nr_downscale.o
|
||||
dim-objs += di_pps.o
|
||||
dim-objs += di_vframe.o
|
||||
dim-objs += di_prc.o
|
||||
dim-objs += di_pre.o
|
||||
dim-objs += di_post.o
|
||||
dim-objs += di_reg_tab.o
|
||||
dim-objs += di_dbg.o
|
||||
dim-objs += di_que.o
|
||||
dim-objs += di_sys.o
|
||||
dim-objs += di_task.o
|
||||
dim-objs += di_api.o
|
||||
#dim-objs += film_mode_fmw/vof_soft_top.o
|
||||
#dim-objs += film_mode_fmw/flm_mod_xx.o
|
||||
#dim-objs += film_mode_fmw/film_fw1.o
|
||||
ccflags-y += -Idrivers/amlogic/media/common/rdma/
|
||||
ccflags-y += -I$(src)
|
||||
8417
drivers/amlogic/media/di_multi/deinterlace.c
Normal file
8417
drivers/amlogic/media/di_multi/deinterlace.c
Normal file
File diff suppressed because it is too large
Load Diff
658
drivers/amlogic/media/di_multi/deinterlace.h
Normal file
658
drivers/amlogic/media/di_multi/deinterlace.h
Normal file
@@ -0,0 +1,658 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/deinterlace.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DI_H
|
||||
#define _DI_H
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_provider.h>
|
||||
|
||||
#include "../di_local/di_local.h"
|
||||
#include <linux/clk.h>
|
||||
#include <linux/atomic.h>
|
||||
#include "deinterlace_hw.h"
|
||||
#include "../deinterlace/di_pqa.h"
|
||||
|
||||
/*trigger_pre_di_process param*/
|
||||
#define TRIGGER_PRE_BY_PUT 'p'
|
||||
#define TRIGGER_PRE_BY_DE_IRQ 'i'
|
||||
#define TRIGGER_PRE_BY_UNREG 'u'
|
||||
/*di_timer_handle*/
|
||||
#define TRIGGER_PRE_BY_TIMER 't'
|
||||
#define TRIGGER_PRE_BY_FORCE_UNREG 'f'
|
||||
#define TRIGGER_PRE_BY_VFRAME_READY 'r'
|
||||
#define TRIGGER_PRE_BY_PROVERDER_UNREG 'n'
|
||||
#define TRIGGER_PRE_BY_DEBUG_DISABLE 'd'
|
||||
#define TRIGGER_PRE_BY_PROVERDER_REG 'R'
|
||||
|
||||
#define DI_RUN_FLAG_RUN 0
|
||||
#define DI_RUN_FLAG_PAUSE 1
|
||||
#define DI_RUN_FLAG_STEP 2
|
||||
#define DI_RUN_FLAG_STEP_DONE 3
|
||||
|
||||
#define USED_LOCAL_BUF_MAX 3
|
||||
#define BYPASS_GET_MAX_BUF_NUM 4
|
||||
|
||||
/* buffer management related */
|
||||
#define MAX_IN_BUF_NUM (4)
|
||||
#define MAX_LOCAL_BUF_NUM (7)
|
||||
#define MAX_POST_BUF_NUM (7) /*(5)*/ /* 16 */
|
||||
|
||||
#define VFRAME_TYPE_IN 1
|
||||
#define VFRAME_TYPE_LOCAL 2
|
||||
#define VFRAME_TYPE_POST 3
|
||||
#define VFRAME_TYPE_NUM 3
|
||||
|
||||
#define DI_POST_GET_LIMIT 4
|
||||
#define DI_PRE_READY_LIMIT 4
|
||||
/*vframe define*/
|
||||
#define vframe_t struct vframe_s
|
||||
|
||||
#define is_from_vdin(vframe) ((vframe)->type & VIDTYPE_VIU_422)
|
||||
|
||||
/* canvas defination */
|
||||
#define DI_USE_FIXED_CANVAS_IDX
|
||||
/*#define DET3D */
|
||||
#undef SUPPORT_MPEG_TO_VDIN
|
||||
#define CLK_TREE_SUPPORT
|
||||
#ifndef CONFIG_AMLOGIC_MEDIA_RDMA
|
||||
#ifndef VSYNC_WR_MPEG_REG
|
||||
#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val)
|
||||
#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \
|
||||
aml_vcbus_update_bits((adr), \
|
||||
((1 << (len)) - 1) << (start), (val) << (start))
|
||||
|
||||
#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IS_VDIN_SRC(src) ( \
|
||||
((src) == VFRAME_SOURCE_TYPE_TUNER) || \
|
||||
((src) == VFRAME_SOURCE_TYPE_CVBS) || \
|
||||
((src) == VFRAME_SOURCE_TYPE_COMP) || \
|
||||
((src) == VFRAME_SOURCE_TYPE_HDMI))
|
||||
|
||||
#define IS_I_SRC(vftype) ((vftype) & VIDTYPE_INTERLACE_BOTTOM)
|
||||
|
||||
#define IS_COMP_MODE(vftype) ((vftype) & VIDTYPE_COMPRESS)
|
||||
|
||||
enum process_fun_index_e {
|
||||
PROCESS_FUN_NULL = 0,
|
||||
PROCESS_FUN_DI,
|
||||
PROCESS_FUN_PD,
|
||||
PROCESS_FUN_PROG,
|
||||
PROCESS_FUN_BOB
|
||||
};
|
||||
|
||||
#define process_fun_index_t enum process_fun_index_e
|
||||
|
||||
enum canvas_idx_e {
|
||||
NR_CANVAS,
|
||||
MTN_CANVAS,
|
||||
MV_CANVAS,
|
||||
};
|
||||
|
||||
#define pulldown_mode_t enum pulldown_mode_e
|
||||
struct di_buf_s {
|
||||
struct vframe_s *vframe;
|
||||
int index; /* index in vframe_in_dup[] or vframe_in[],
|
||||
* only for type of VFRAME_TYPE_IN
|
||||
*/
|
||||
int post_proc_flag; /* 0,no post di; 1, normal post di;
|
||||
* 2, edge only; 3, dummy
|
||||
*/
|
||||
int new_format_flag;
|
||||
int type;
|
||||
int throw_flag;
|
||||
int invert_top_bot_flag;
|
||||
int seq;
|
||||
int pre_ref_count; /* none zero, is used by mem_mif,
|
||||
* chan2_mif, or wr_buf
|
||||
*/
|
||||
int post_ref_count; /* none zero, is used by post process */
|
||||
int queue_index;
|
||||
/*below for type of VFRAME_TYPE_LOCAL */
|
||||
unsigned long nr_adr;
|
||||
int nr_canvas_idx;
|
||||
unsigned long mtn_adr;
|
||||
int mtn_canvas_idx;
|
||||
unsigned long cnt_adr;
|
||||
int cnt_canvas_idx;
|
||||
unsigned long mcinfo_adr;
|
||||
int mcinfo_canvas_idx;
|
||||
unsigned long mcvec_adr;
|
||||
int mcvec_canvas_idx;
|
||||
struct mcinfo_pre_s {
|
||||
unsigned int highvertfrqflg;
|
||||
unsigned int motionparadoxflg;
|
||||
unsigned int regs[26];/* reg 0x2fb0~0x2fc9 */
|
||||
} curr_field_mcinfo;
|
||||
/* blend window */
|
||||
struct pulldown_detected_s
|
||||
pd_config;
|
||||
/* tff bff check result bit[1:0]*/
|
||||
unsigned int privated;
|
||||
unsigned int canvas_config_flag;
|
||||
/* 0,configed; 1,config type 1 (prog);
|
||||
* 2, config type 2 (interlace)
|
||||
*/
|
||||
unsigned int canvas_height;
|
||||
unsigned int canvas_height_mc; /*ary add for mc h is diff*/
|
||||
unsigned int canvas_width[3];/* nr/mtn/mv */
|
||||
process_fun_index_t process_fun_index;
|
||||
int early_process_fun_index;
|
||||
int left_right;/*1,left eye; 0,right eye in field alternative*/
|
||||
/*below for type of VFRAME_TYPE_POST*/
|
||||
struct di_buf_s *di_buf[2];
|
||||
struct di_buf_s *di_buf_dup_p[5];
|
||||
/* 0~4: n-2, n-1, n, n+1, n+2; n is the field to display*/
|
||||
/*0: n-2*/
|
||||
/*1: n-1*/
|
||||
/*2: n*/
|
||||
/*3: n+1*/
|
||||
/*4: n+2*/
|
||||
struct di_buf_s *di_wr_linked_buf;
|
||||
/* debug for di-vf-get/put
|
||||
* 1: after get
|
||||
* 0: after put
|
||||
*/
|
||||
atomic_t di_cnt;
|
||||
struct page *pages;
|
||||
/*ary add */
|
||||
unsigned int channel;
|
||||
unsigned int width_bk; /*move from ppre*/
|
||||
};
|
||||
|
||||
#define RDMA_DET3D_IRQ 0x20
|
||||
/* vdin0 rdma irq */
|
||||
#define RDMA_DEINT_IRQ 0x2
|
||||
#define RDMA_TABLE_SIZE ((PAGE_SIZE) << 1)
|
||||
|
||||
#define MAX_CANVAS_WIDTH 1920
|
||||
#define MAX_CANVAS_HEIGHT 1088
|
||||
|
||||
/* #define DI_BUFFER_DEBUG */
|
||||
|
||||
#define DI_LOG_MTNINFO 0x02
|
||||
#define DI_LOG_PULLDOWN 0x10
|
||||
#define DI_LOG_BUFFER_STATE 0x20
|
||||
#define DI_LOG_TIMESTAMP 0x100
|
||||
#define DI_LOG_PRECISE_TIMESTAMP 0x200
|
||||
#define DI_LOG_QUEUE 0x40
|
||||
#define DI_LOG_VFRAME 0x80
|
||||
|
||||
#if 0
|
||||
#define QUEUE_LOCAL_FREE 0
|
||||
#define QUEUE_IN_FREE 1
|
||||
#define QUEUE_PRE_READY 2
|
||||
#define QUEUE_POST_FREE 3
|
||||
#define QUEUE_POST_READY 4
|
||||
#define QUEUE_RECYCLE 5
|
||||
#define QUEUE_DISPLAY 6
|
||||
#define QUEUE_TMP 7
|
||||
#define QUEUE_POST_DOING 8
|
||||
#define QUEUE_NUM 9
|
||||
#else
|
||||
#define QUEUE_LOCAL_FREE 0
|
||||
#define QUEUE_RECYCLE 1 /* 5 */
|
||||
#define QUEUE_DISPLAY 2 /* 6 */
|
||||
#define QUEUE_TMP 3 /* 7 */
|
||||
#define QUEUE_POST_DOING 4 /* 8 */
|
||||
|
||||
#define QUEUE_IN_FREE 5 /* 1 */
|
||||
#define QUEUE_PRE_READY 6 /* 2 */
|
||||
#define QUEUE_POST_FREE 7 /* 3 */
|
||||
#define QUEUE_POST_READY 8 /* 4 QUE_POST_READY */
|
||||
|
||||
/*new use this for put back control*/
|
||||
#define QUEUE_POST_PUT_BACK (9)
|
||||
|
||||
#define QUEUE_NUM 5 /* 9 */
|
||||
#define QUEUE_NEW_THD_MIN (QUEUE_IN_FREE - 1)
|
||||
#define QUEUE_NEW_THD_MAX (QUEUE_POST_READY + 1)
|
||||
|
||||
#endif
|
||||
|
||||
#define queue_t struct queue_s
|
||||
|
||||
#define VFM_NAME "deinterlace"
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
|
||||
void enable_rdma(int enable_flag);
|
||||
int VSYNC_WR_MPEG_REG(u32 adr, u32 val);
|
||||
int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len);
|
||||
u32 VSYNC_RD_MPEG_REG(u32 adr);
|
||||
bool is_vsync_rdma_enable(void);
|
||||
#else
|
||||
#ifndef VSYNC_WR_MPEG_REG
|
||||
#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val)
|
||||
#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \
|
||||
aml_vcbus_update_bits((adr), \
|
||||
((1 << (len)) - 1) << (start), (val) << (start))
|
||||
|
||||
#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DI_COUNT 1
|
||||
#define DI_MAP_FLAG 0x1
|
||||
#define DI_SUSPEND_FLAG 0x2
|
||||
#define DI_LOAD_REG_FLAG 0x4
|
||||
#define DI_VPU_CLKB_SET 0x8
|
||||
|
||||
struct di_dev_s {
|
||||
dev_t devt;
|
||||
struct cdev cdev; /* The cdev structure */
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
dev_t devno;
|
||||
struct class *pclss;
|
||||
|
||||
bool sema_flg; /*di_sema_init_flag*/
|
||||
|
||||
struct task_struct *task;
|
||||
struct clk *vpu_clkb;
|
||||
unsigned long clkb_max_rate;
|
||||
unsigned long clkb_min_rate;
|
||||
struct list_head pq_table_list;
|
||||
atomic_t pq_flag;
|
||||
unsigned char di_event;
|
||||
unsigned int pre_irq;
|
||||
unsigned int post_irq;
|
||||
unsigned int flags;
|
||||
unsigned long jiffy;
|
||||
unsigned long mem_start;
|
||||
unsigned int mem_size;
|
||||
bool mem_flg; /*ary add for make sure mem is ok*/
|
||||
unsigned int buffer_size;
|
||||
unsigned int post_buffer_size;
|
||||
unsigned int buf_num_avail;
|
||||
int rdma_handle;
|
||||
/* is support nr10bit */
|
||||
unsigned int nr10bit_support;
|
||||
/* is DI support post wr to mem for OMX */
|
||||
unsigned int post_wr_support;
|
||||
unsigned int nrds_enable;
|
||||
unsigned int pps_enable;
|
||||
unsigned int h_sc_down_en;/*sm1, tm2 ...*/
|
||||
/*struct mutex cma_mutex;*/
|
||||
unsigned int flag_cma;
|
||||
struct page *total_pages;
|
||||
struct dentry *dbg_root; /*dbg_fs*/
|
||||
/***************************/
|
||||
/*struct di_data_l_s data_l;*/
|
||||
void *data_l;
|
||||
|
||||
};
|
||||
|
||||
struct di_pre_stru_s {
|
||||
/* pre input */
|
||||
struct DI_MIF_s di_inp_mif;
|
||||
struct DI_MIF_s di_mem_mif;
|
||||
struct DI_MIF_s di_chan2_mif;
|
||||
struct di_buf_s *di_inp_buf;
|
||||
struct di_buf_s *di_post_inp_buf;
|
||||
struct di_buf_s *di_inp_buf_next;
|
||||
/* p_asi_next: ary:add for p */
|
||||
struct di_buf_s *p_asi_next;
|
||||
struct di_buf_s *di_mem_buf_dup_p;
|
||||
struct di_buf_s *di_chan2_buf_dup_p;
|
||||
/* pre output */
|
||||
struct DI_SIM_MIF_s di_nrwr_mif;
|
||||
struct DI_SIM_MIF_s di_mtnwr_mif;
|
||||
struct di_buf_s *di_wr_buf;
|
||||
struct di_buf_s *di_post_wr_buf;
|
||||
struct DI_SIM_MIF_s di_contp2rd_mif;
|
||||
struct DI_SIM_MIF_s di_contprd_mif;
|
||||
struct DI_SIM_MIF_s di_contwr_mif;
|
||||
int field_count_for_cont;
|
||||
/*
|
||||
* 0 (f0,null,f0)->nr0,
|
||||
* 1 (f1,nr0,f1)->nr1_cnt,
|
||||
* 2 (f2,nr1_cnt,nr0)->nr2_cnt
|
||||
* 3 (f3,nr2_cnt,nr1_cnt)->nr3_cnt
|
||||
*/
|
||||
struct DI_MC_MIF_s di_mcinford_mif;
|
||||
struct DI_MC_MIF_s di_mcvecwr_mif;
|
||||
struct DI_MC_MIF_s di_mcinfowr_mif;
|
||||
/* pre state */
|
||||
int in_seq;
|
||||
int recycle_seq;
|
||||
int pre_ready_seq;
|
||||
|
||||
int pre_de_busy; /* 1 if pre_de is not done */
|
||||
int pre_de_process_flag; /* flag when dim_pre_de_process done */
|
||||
int pre_de_clear_flag;
|
||||
/* flag is set when VFRAME_EVENT_PROVIDER_UNREG*/
|
||||
int unreg_req_flag_cnt;
|
||||
|
||||
int reg_req_flag_cnt;
|
||||
int force_unreg_req_flag;
|
||||
int disable_req_flag;
|
||||
/* current source info */
|
||||
int cur_width;
|
||||
int cur_height;
|
||||
int cur_inp_type;
|
||||
int cur_source_type;
|
||||
int cur_sig_fmt;
|
||||
unsigned int orientation;
|
||||
int cur_prog_flag; /* 1 for progressive source */
|
||||
/* valid only when prog_proc_type is 0, for
|
||||
* progressive source: top field 1, bot field 0
|
||||
*/
|
||||
int source_change_flag;
|
||||
/* input size change flag, 1: need reconfig pre/nr/dnr size */
|
||||
/* 0: not need config pre/nr/dnr size*/
|
||||
bool input_size_change_flag;
|
||||
/* true: bypass di all logic, false: not bypass */
|
||||
bool bypass_flag;
|
||||
unsigned char prog_proc_type;
|
||||
/* set by prog_proc_config when source is vdin,0:use 2 i
|
||||
* serial buffer,1:use 1 p buffer,3:use 2 i paralleling buffer
|
||||
*/
|
||||
/* ary: loacal play p mode is 0
|
||||
* local play i mode is 0
|
||||
*/
|
||||
|
||||
unsigned char buf_alloc_mode;
|
||||
/* alloc di buf as p or i;0: alloc buf as i;
|
||||
* 1: alloc buf as p;
|
||||
*/
|
||||
unsigned char madi_enable;
|
||||
unsigned char mcdi_enable;
|
||||
unsigned int pps_dstw; /*no use ?*/
|
||||
unsigned int pps_dsth; /*no use ?*/
|
||||
int left_right;/*1,left eye; 0,right eye in field alternative*/
|
||||
/*input2pre*/
|
||||
int bypass_start_count;
|
||||
/* need discard some vframe when input2pre => bypass */
|
||||
unsigned char vdin2nr;
|
||||
enum tvin_trans_fmt source_trans_fmt;
|
||||
enum tvin_trans_fmt det3d_trans_fmt;
|
||||
unsigned int det_lr;
|
||||
unsigned int det_tp;
|
||||
unsigned int det_la;
|
||||
unsigned int det_null;
|
||||
unsigned int width_bk;
|
||||
#ifdef DET3D
|
||||
int vframe_interleave_flag;
|
||||
#endif
|
||||
/**/
|
||||
int pre_de_irq_timeout_count;
|
||||
int pre_throw_flag;
|
||||
int bad_frame_throw_count;
|
||||
/*for static pic*/
|
||||
int static_frame_count;
|
||||
bool force_interlace;
|
||||
bool bypass_pre;
|
||||
bool invert_flag;
|
||||
bool vdin_source;
|
||||
int nr_size;
|
||||
int count_size;
|
||||
int mcinfo_size;
|
||||
int mv_size;
|
||||
int mtn_size;
|
||||
|
||||
int cma_release_req;
|
||||
/* for performance debug */
|
||||
unsigned long irq_time[2];
|
||||
/* combing adaptive */
|
||||
struct combing_status_s *mtn_status;
|
||||
bool combing_fix_en;
|
||||
unsigned int comb_mode;
|
||||
};
|
||||
|
||||
struct di_post_stru_s {
|
||||
struct DI_MIF_s di_buf0_mif;
|
||||
struct DI_MIF_s di_buf1_mif;
|
||||
struct DI_MIF_s di_buf2_mif;
|
||||
struct DI_SIM_MIF_s di_diwr_mif;
|
||||
struct DI_SIM_MIF_s di_mtnprd_mif;
|
||||
struct DI_MC_MIF_s di_mcvecrd_mif;
|
||||
/*post doing buf and write buf to post ready*/
|
||||
struct di_buf_s *cur_post_buf;
|
||||
struct di_buf_s *keep_buf;
|
||||
struct di_buf_s *keep_buf_post; /*ary add for keep post buf*/
|
||||
int update_post_reg_flag;
|
||||
int run_early_proc_fun_flag;
|
||||
int cur_disp_index;
|
||||
int canvas_id;
|
||||
int next_canvas_id;
|
||||
bool toggle_flag;
|
||||
bool vscale_skip_flag;
|
||||
uint start_pts;
|
||||
int buf_type;
|
||||
int de_post_process_done;
|
||||
int post_de_busy;
|
||||
int di_post_num;
|
||||
unsigned int post_peek_underflow;
|
||||
unsigned int di_post_process_cnt;
|
||||
unsigned int check_recycle_buf_cnt;/*cp to di_hpre_s*/
|
||||
/* performance debug */
|
||||
unsigned int post_wr_cnt;
|
||||
unsigned long irq_time;
|
||||
|
||||
/*frame cnt*/
|
||||
unsigned int frame_cnt; /*cnt for post process*/
|
||||
};
|
||||
|
||||
#define MAX_QUEUE_POOL_SIZE 256
|
||||
struct queue_s {
|
||||
unsigned int num;
|
||||
unsigned int in_idx;
|
||||
unsigned int out_idx;
|
||||
unsigned int type;
|
||||
/* 0, first in first out;
|
||||
* 1, general;2, fix position for di buf
|
||||
*/
|
||||
unsigned int pool[MAX_QUEUE_POOL_SIZE];
|
||||
};
|
||||
|
||||
struct di_buf_pool_s {
|
||||
struct di_buf_s *di_buf_ptr;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct dim_mm_s {
|
||||
struct page *ppage;
|
||||
unsigned long addr;
|
||||
};
|
||||
|
||||
bool dim_mm_alloc(int cma_mode, size_t count, struct dim_mm_s *o);
|
||||
bool dim_mm_release(int cma_mode,
|
||||
struct page *pages,
|
||||
int count,
|
||||
unsigned long addr);
|
||||
|
||||
unsigned char dim_is_bypass(vframe_t *vf_in, unsigned int channel);
|
||||
bool dim_bypass_first_frame(unsigned int ch);
|
||||
|
||||
int di_cnt_buf(int width, int height, int prog_flag, int mc_mm,
|
||||
int bit10_support, int pack422);
|
||||
|
||||
/*---get di state parameter---*/
|
||||
struct di_dev_s *get_dim_de_devp(void);
|
||||
|
||||
const char *dim_get_version_s(void);
|
||||
int dim_get_dump_state_flag(void);
|
||||
|
||||
int dim_get_blocking(void);
|
||||
|
||||
struct di_buf_s *dim_get_recovery_log_di_buf(void);
|
||||
|
||||
unsigned long dim_get_reg_unreg_timeout_cnt(void);
|
||||
struct vframe_s **dim_get_vframe_in(unsigned int ch);
|
||||
int dim_check_recycle_buf(unsigned int channel);
|
||||
|
||||
int dim_seq_file_module_para_di(struct seq_file *seq);
|
||||
int dim_seq_file_module_para_hw(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_film_fw1(struct seq_file *seq);
|
||||
int dim_seq_file_module_para_mtn(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_pps(struct seq_file *seq);
|
||||
|
||||
int dim_seq_file_module_para_(struct seq_file *seq);
|
||||
|
||||
/***********************/
|
||||
|
||||
unsigned int di_get_dts_nrds_en(void);
|
||||
int di_get_disp_cnt(void);
|
||||
|
||||
/*---------------------*/
|
||||
long dim_pq_load_io(unsigned long arg);
|
||||
int dim_get_canvas(void);
|
||||
unsigned int dim_cma_alloc_total(struct di_dev_s *de_devp);
|
||||
irqreturn_t dim_irq(int irq, void *dev_instance);
|
||||
irqreturn_t dim_post_irq(int irq, void *dev_instance);
|
||||
|
||||
void dim_rdma_init(void);
|
||||
void dim_rdma_exit(void);
|
||||
|
||||
void dim_set_di_flag(void);
|
||||
void dim_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev);
|
||||
|
||||
void dim_log_buffer_state(unsigned char *tag, unsigned int channel);
|
||||
|
||||
unsigned char dim_pre_de_buf_config(unsigned int channel);
|
||||
void dim_pre_de_process(unsigned int channel);
|
||||
void dim_pre_de_done_buf_config(unsigned int channel, bool flg_timeout);
|
||||
void dim_pre_de_done_buf_clear(unsigned int channel);
|
||||
|
||||
void di_reg_setting(unsigned int channel, struct vframe_s *vframe);
|
||||
void di_reg_variable(unsigned int channel, struct vframe_s *vframe);
|
||||
|
||||
void dim_unreg_process_irq(unsigned int channel);
|
||||
void di_unreg_variable(unsigned int channel);
|
||||
void di_unreg_setting(void);
|
||||
|
||||
void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel);
|
||||
void dim_unreg_process(unsigned int channel);
|
||||
|
||||
int dim_process_post_vframe(unsigned int channel);
|
||||
unsigned char dim_check_di_buf(struct di_buf_s *di_buf, int reason,
|
||||
unsigned int channel);
|
||||
int dim_do_post_wr_fun(void *arg, vframe_t *disp_vf);
|
||||
int dim_post_process(void *arg, unsigned int zoom_start_x_lines,
|
||||
unsigned int zoom_end_x_lines,
|
||||
unsigned int zoom_start_y_lines,
|
||||
unsigned int zoom_end_y_lines, vframe_t *disp_vf);
|
||||
void dim_post_de_done_buf_config(unsigned int channel);
|
||||
void dim_recycle_post_back(unsigned int channel);
|
||||
void recycle_post_ready_local(struct di_buf_s *di_buf,
|
||||
unsigned int channel);
|
||||
|
||||
/*--------------------------*/
|
||||
unsigned char dim_vcry_get_flg(void);
|
||||
void dim_vcry_flg_inc(void);
|
||||
void dim_vcry_set_flg(unsigned char val);
|
||||
/*--------------------------*/
|
||||
unsigned int dim_vcry_get_log_reason(void);
|
||||
void dim_vcry_set_log_reason(unsigned int val);
|
||||
/*--------------------------*/
|
||||
unsigned char dim_vcry_get_log_q_idx(void);
|
||||
void dim_vcry_set_log_q_idx(unsigned int val);
|
||||
/*--------------------------*/
|
||||
struct di_buf_s **dim_vcry_get_log_di_buf(void);
|
||||
void dim_vcry_set_log_di_buf(struct di_buf_s *di_bufp);
|
||||
void dim_vcry_set(unsigned int reason, unsigned int idx,
|
||||
struct di_buf_s *di_bufp);
|
||||
|
||||
const char *dim_get_vfm_type_name(unsigned int nub);
|
||||
|
||||
bool dim_cma_top_alloc(unsigned int ch);
|
||||
bool dim_cma_top_release(unsigned int ch);
|
||||
|
||||
int dim_get_reg_unreg_cnt(void);
|
||||
void dim_reg_timeout_inc(void);
|
||||
|
||||
void dim_reg_process(unsigned int channel);
|
||||
bool is_bypass2(struct vframe_s *vf_in, unsigned int ch);
|
||||
|
||||
/*--------------------------*/
|
||||
int di_ori_event_unreg(unsigned int channel);
|
||||
int di_ori_event_reg(void *data, unsigned int channel);
|
||||
int di_ori_event_qurey_vdin2nr(unsigned int channel);
|
||||
int di_ori_event_reset(unsigned int channel);
|
||||
int di_ori_event_light_unreg(unsigned int channel);
|
||||
int di_ori_event_light_unreg_revframe(unsigned int channel);
|
||||
int di_ori_event_ready(unsigned int channel);
|
||||
int di_ori_event_qurey_state(unsigned int channel);
|
||||
void di_ori_event_set_3D(int type, void *data, unsigned int channel);
|
||||
|
||||
/*--------------------------*/
|
||||
extern int pre_run_flag;
|
||||
extern unsigned int dbg_first_cnt_pre;
|
||||
extern spinlock_t plist_lock;
|
||||
|
||||
void dim_dbg_pre_cnt(unsigned int channel, char *item);
|
||||
|
||||
void diext_clk_b_sw(bool on);
|
||||
|
||||
int di_vf_l_states(struct vframe_states *states, unsigned int channel);
|
||||
struct vframe_s *di_vf_l_peek(unsigned int channel);
|
||||
void di_vf_l_put(struct vframe_s *vf, unsigned char channel);
|
||||
struct vframe_s *di_vf_l_get(unsigned int channel);
|
||||
|
||||
unsigned char pre_p_asi_de_buf_config(unsigned int ch);
|
||||
|
||||
/*---------------------*/
|
||||
|
||||
ssize_t
|
||||
store_config(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
store_dbg(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
store_dump_mem(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t len);
|
||||
ssize_t
|
||||
store_log(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t
|
||||
show_vframe_status(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf);
|
||||
|
||||
ssize_t dim_read_log(char *buf);
|
||||
|
||||
/*---------------------*/
|
||||
|
||||
struct di_buf_s *dim_get_buf(unsigned int channel,
|
||||
int queue_idx, int *start_pos);
|
||||
|
||||
#define queue_for_each_entry(di_buf, channel, queue_idx, list) \
|
||||
for (itmp = 0; \
|
||||
((di_buf = dim_get_buf(channel, queue_idx, &itmp)) != NULL);)
|
||||
|
||||
#define di_dev_t struct di_dev_s
|
||||
|
||||
#define di_pr_info(fmt, args ...) pr_info("DI: " fmt, ## args)
|
||||
|
||||
#define pr_dbg(fmt, args ...) pr_debug("DI: " fmt, ## args)
|
||||
|
||||
#define pr_error(fmt, args ...) pr_err("DI: " fmt, ## args)
|
||||
|
||||
/*this is debug for buf*/
|
||||
/*#define DI_DEBUG_POST_BUF_FLOW (1)*/
|
||||
|
||||
#endif
|
||||
1214
drivers/amlogic/media/di_multi/deinterlace_dbg.c
Normal file
1214
drivers/amlogic/media/di_multi/deinterlace_dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
43
drivers/amlogic/media/di_multi/deinterlace_dbg.h
Normal file
43
drivers/amlogic/media/di_multi/deinterlace_dbg.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/deinterlace_dbg.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DI_DBG_H
|
||||
#define _DI_DBG_H
|
||||
#include "deinterlace.h"
|
||||
|
||||
void dim_parse_cmd_params(char *buf_orig, char **parm);
|
||||
void dim_dump_pre_stru(struct di_pre_stru_s *ppre);
|
||||
void dim_dump_post_stru(struct di_post_stru_s *di_post_stru_p);
|
||||
void dim_dump_di_buf(struct di_buf_s *di_buf);
|
||||
void dim_dump_pool(struct queue_s *q);
|
||||
void dim_dump_vframe(vframe_t *vf);
|
||||
void dim_print_di_buf(struct di_buf_s *di_buf, int format);
|
||||
void dim_dump_pre_mif_state(void);
|
||||
void dim_dump_post_mif_reg(void);
|
||||
void dim_dump_buf_addr(struct di_buf_s *di_buf, unsigned int num);
|
||||
void dim_dump_mif_size_state(struct di_pre_stru_s *pre,
|
||||
struct di_post_stru_s *post);
|
||||
void debug_device_files_add(struct device *dev);
|
||||
void debug_device_files_del(struct device *dev);
|
||||
void dim_debugfs_init(void);
|
||||
void dim_debugfs_exit(void);
|
||||
int dim_state_show(struct seq_file *seq, void *v,
|
||||
unsigned int channel);
|
||||
int dim_dump_mif_size_state_show(struct seq_file *seq, void *v,
|
||||
unsigned int channel);
|
||||
|
||||
#endif
|
||||
4236
drivers/amlogic/media/di_multi/deinterlace_hw.c
Normal file
4236
drivers/amlogic/media/di_multi/deinterlace_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
277
drivers/amlogic/media/di_multi/deinterlace_hw.h
Normal file
277
drivers/amlogic/media/di_multi/deinterlace_hw.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/deinterlace_hw.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DI_HW_H
|
||||
#define _DI_HW_H
|
||||
#include <linux/amlogic/media/amvecm/amvecm.h>
|
||||
|
||||
#include "../deinterlace/di_pqa.h"
|
||||
|
||||
/* if post size < 80, filter of ei can't work */
|
||||
#define MIN_POST_WIDTH 80
|
||||
#define MIN_BLEND_WIDTH 27
|
||||
|
||||
#define SKIP_CTRE_NUM 13
|
||||
/*move from deinterlace.c*/
|
||||
enum eAFBC_REG {
|
||||
eAFBC_ENABLE,
|
||||
eAFBC_MODE,
|
||||
eAFBC_SIZE_IN,
|
||||
eAFBC_DEC_DEF_COLOR,
|
||||
eAFBC_CONV_CTRL,
|
||||
eAFBC_LBUF_DEPTH,
|
||||
eAFBC_HEAD_BADDR,
|
||||
eAFBC_BODY_BADDR,
|
||||
eAFBC_SIZE_OUT,
|
||||
eAFBC_OUT_YSCOPE,
|
||||
eAFBC_STAT,
|
||||
eAFBC_VD_CFMT_CTRL,
|
||||
eAFBC_VD_CFMT_W,
|
||||
eAFBC_MIF_HOR_SCOPE,
|
||||
eAFBC_MIF_VER_SCOPE,
|
||||
eAFBC_PIXEL_HOR_SCOPE,
|
||||
eAFBC_PIXEL_VER_SCOPE,
|
||||
eAFBC_VD_CFMT_H,
|
||||
};
|
||||
|
||||
enum eAFBC_DEC {
|
||||
eAFBC_DEC0,
|
||||
eAFBC_DEC1,
|
||||
};
|
||||
|
||||
#define AFBC_REG_INDEX_NUB (18)
|
||||
#define AFBC_DEC_NUB (2)
|
||||
|
||||
struct DI_MIF_s {
|
||||
unsigned short luma_x_start0;
|
||||
unsigned short luma_x_end0;
|
||||
unsigned short luma_y_start0;
|
||||
unsigned short luma_y_end0;
|
||||
unsigned short chroma_x_start0;
|
||||
unsigned short chroma_x_end0;
|
||||
unsigned short chroma_y_start0;
|
||||
unsigned short chroma_y_end0;
|
||||
unsigned int nocompress;
|
||||
unsigned set_separate_en:2;
|
||||
unsigned src_field_mode:1;
|
||||
unsigned src_prog:1;
|
||||
unsigned video_mode:1;
|
||||
unsigned output_field_num:1;
|
||||
unsigned bit_mode:2;
|
||||
/*
|
||||
* unsigned burst_size_y:2; set 3 as default
|
||||
* unsigned burst_size_cb:2;set 1 as default
|
||||
* unsigned burst_size_cr:2;set 1 as default
|
||||
*/
|
||||
unsigned canvas0_addr0:8;
|
||||
unsigned canvas0_addr1:8;
|
||||
unsigned canvas0_addr2:8;
|
||||
};
|
||||
|
||||
struct DI_SIM_MIF_s {
|
||||
unsigned short start_x;
|
||||
unsigned short end_x;
|
||||
unsigned short start_y;
|
||||
unsigned short end_y;
|
||||
unsigned short canvas_num;
|
||||
unsigned short bit_mode;
|
||||
};
|
||||
|
||||
struct DI_MC_MIF_s {
|
||||
unsigned short start_x;
|
||||
unsigned short start_y;
|
||||
unsigned short end_y;
|
||||
unsigned short size_x;
|
||||
unsigned short size_y;
|
||||
unsigned short canvas_num;
|
||||
unsigned short blend_en;
|
||||
unsigned short vecrd_offset;
|
||||
};
|
||||
|
||||
enum gate_mode_e {
|
||||
GATE_AUTO,
|
||||
GATE_ON,
|
||||
GATE_OFF,
|
||||
};
|
||||
|
||||
struct mcinfo_lmv_s {
|
||||
unsigned char lock_flag;
|
||||
char lmv;
|
||||
unsigned short lock_cnt;
|
||||
};
|
||||
|
||||
struct di_pq_parm_s {
|
||||
struct am_pq_parm_s pq_parm;
|
||||
struct am_reg_s *regs;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void dim_read_pulldown_info(unsigned int *glb_frm_mot_num,
|
||||
unsigned int *glb_fid_mot_num);
|
||||
|
||||
#if 0
|
||||
|
||||
void read_new_pulldown_info(struct FlmModReg_t *pFMRegp);
|
||||
#endif
|
||||
void dim_pulldown_info_clear_g12a(void);
|
||||
void dimh_combing_pd22_window_config(unsigned int width, unsigned int height);
|
||||
void dimh_hw_init(bool pulldown_en, bool mc_enable);
|
||||
void dimh_hw_uninit(void);
|
||||
void dimh_enable_di_pre_aml(struct DI_MIF_s *di_inp_mif,
|
||||
struct DI_MIF_s *di_mem_mif,
|
||||
struct DI_MIF_s *di_chan2_mif,
|
||||
struct DI_SIM_MIF_s *di_nrwr_mif,
|
||||
struct DI_SIM_MIF_s *di_mtnwr_mif,
|
||||
struct DI_SIM_MIF_s *di_contp2rd_mif,
|
||||
struct DI_SIM_MIF_s *di_contprd_mif,
|
||||
struct DI_SIM_MIF_s *di_contwr_mif,
|
||||
unsigned char madi_en,
|
||||
unsigned char pre_field_num,
|
||||
unsigned char pre_vdin_link);
|
||||
void dimh_enable_afbc_input(struct vframe_s *vf);
|
||||
|
||||
void dimh_mc_pre_mv_irq(void);
|
||||
void dimh_enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif,
|
||||
struct DI_MC_MIF_s *di_mcinfowr_mif,
|
||||
struct DI_MC_MIF_s *di_mcvecwr_mif,
|
||||
unsigned char mcdi_en);
|
||||
void dimh_enable_mc_di_pre_g12(struct DI_MC_MIF_s *di_mcinford_mif,
|
||||
struct DI_MC_MIF_s *di_mcinfowr_mif,
|
||||
struct DI_MC_MIF_s *di_mcvecwr_mif,
|
||||
unsigned char mcdi_en);
|
||||
|
||||
void dimh_enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif,
|
||||
int urgent, bool reverse, int invert_mv);
|
||||
void dimh_enable_mc_di_post_g12(struct DI_MC_MIF_s *di_mcvecrd_mif,
|
||||
int urgent, bool reverse, int invert_mv);
|
||||
|
||||
void dimh_disable_post_deinterlace_2(void);
|
||||
void dimh_initial_di_post_2(int hsize_post, int vsize_post,
|
||||
int hold_line, bool write_en);
|
||||
void dimh_enable_di_post_2(
|
||||
struct DI_MIF_s *di_buf0_mif,
|
||||
struct DI_MIF_s *di_buf1_mif,
|
||||
struct DI_MIF_s *di_buf2_mif,
|
||||
struct DI_SIM_MIF_s *di_diwr_mif,
|
||||
struct DI_SIM_MIF_s *di_mtnprd_mif,
|
||||
int ei_en, int blend_en, int blend_mtn_en, int blend_mode,
|
||||
int di_vpp_en, int di_ddr_en,
|
||||
int post_field_num, int hold_line, int urgent,
|
||||
int invert_mv, int vskip_cnt
|
||||
);
|
||||
void dimh_post_switch_buffer(
|
||||
struct DI_MIF_s *di_buf0_mif,
|
||||
struct DI_MIF_s *di_buf1_mif,
|
||||
struct DI_MIF_s *di_buf2_mif,
|
||||
struct DI_SIM_MIF_s *di_diwr_mif,
|
||||
struct DI_SIM_MIF_s *di_mtnprd_mif,
|
||||
struct DI_MC_MIF_s *di_mcvecrd_mif,
|
||||
int ei_en, int blend_en, int blend_mtn_en, int blend_mode,
|
||||
int di_vpp_en, int di_ddr_en,
|
||||
int post_field_num, int hold_line, int urgent,
|
||||
int invert_mv, bool pd_en, bool mc_enable,
|
||||
int vskip_cnt
|
||||
);
|
||||
void dim_post_read_reverse_irq(bool reverse,
|
||||
unsigned char mc_pre_flag, bool mc_enable);
|
||||
void dim_top_gate_control(bool top_en, bool mc_en);
|
||||
void dim_pre_gate_control(bool enable, bool mc_enable);
|
||||
void dim_post_gate_control(bool gate);
|
||||
void dim_set_power_control(unsigned char enable);
|
||||
void dim_hw_disable(bool mc_enable);
|
||||
void dimh_enable_di_pre_mif(bool enable, bool mc_enable);
|
||||
void dimh_enable_di_post_mif(enum gate_mode_e mode);
|
||||
|
||||
void dimh_combing_pd22_window_config(unsigned int width, unsigned int height);
|
||||
void dimh_calc_lmv_init(void);
|
||||
void dimh_calc_lmv_base_mcinfo(unsigned int vf_height,
|
||||
unsigned long mcinfo_adr,
|
||||
unsigned int mcinfo_size);
|
||||
void dimh_init_field_mode(unsigned short height);
|
||||
void dim_film_mode_win_config(unsigned int width, unsigned int height);
|
||||
void dimh_pulldown_vof_win_config(struct pulldown_detected_s *wins);
|
||||
void dimh_load_regs(struct di_pq_parm_s *di_pq_ptr);
|
||||
void dim_pre_frame_reset_g12(unsigned char madi_en, unsigned char mcdi_en);
|
||||
void dim_pre_frame_reset(void);
|
||||
void dimh_interrupt_ctrl(unsigned char ma_en,
|
||||
unsigned char det3d_en, unsigned char nrds_en,
|
||||
unsigned char post_wr, unsigned char mc_en);
|
||||
void dimh_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en);
|
||||
bool dimh_afbc_is_supported(void);
|
||||
|
||||
void dimh_afbc_reg_sw(bool on);
|
||||
|
||||
void dump_vd2_afbc(void);
|
||||
|
||||
u8 *dim_vmap(ulong addr, u32 size, bool *bflg);
|
||||
void dim_unmap_phyaddr(u8 *vaddr);
|
||||
int dim_print(const char *fmt, ...);
|
||||
|
||||
#define DI_MC_SW_OTHER (1 << 0)
|
||||
#define DI_MC_SW_REG (1 << 1)
|
||||
/*#define DI_MC_SW_POST (1 << 2)*/
|
||||
#define DI_MC_SW_IC (1 << 2)
|
||||
|
||||
#define DI_MC_SW_ON_MASK (DI_MC_SW_REG | DI_MC_SW_OTHER | DI_MC_SW_IC)
|
||||
|
||||
void dimh_patch_post_update_mc(void);
|
||||
void dimh_patch_post_update_mc_sw(unsigned int cmd, bool on);
|
||||
|
||||
void dim_rst_protect(bool on);
|
||||
void dim_pre_nr_wr_done_sel(bool on);
|
||||
void dim_arb_sw(bool on);
|
||||
void dbg_set_DI_PRE_CTRL(void);
|
||||
void di_async_reset2(void); /*2019-04-05 add for debug*/
|
||||
|
||||
enum DI_HW_POST_CTRL {
|
||||
DI_HW_POST_CTRL_INIT,
|
||||
DI_HW_POST_CTRL_RESET,
|
||||
};
|
||||
|
||||
void dimh_post_ctrl(enum DI_HW_POST_CTRL contr,
|
||||
unsigned int post_write_en);
|
||||
void dimh_int_ctr(unsigned int set_mod, unsigned char ma_en,
|
||||
unsigned char det3d_en, unsigned char nrds_en,
|
||||
unsigned char post_wr, unsigned char mc_en);
|
||||
|
||||
void h_dbg_reg_set(unsigned int val);
|
||||
|
||||
enum eDI_POST_FLOW {
|
||||
eDI_POST_FLOW_STEP1_STOP,
|
||||
eDI_POST_FLOW_STEP2_START,
|
||||
/* eDI_POST_FLOW_STEP3_RESET_INT,*/
|
||||
};
|
||||
|
||||
void di_post_set_flow(unsigned int post_wr_en, enum eDI_POST_FLOW step);
|
||||
void post_mif_sw(bool on);
|
||||
void post_dbg_contr(void);
|
||||
void post_close_new(void);
|
||||
void di_post_reset(void);
|
||||
void dimh_pst_trig_resize(void);
|
||||
|
||||
void hpst_power_ctr(bool on);
|
||||
void hpst_dbg_power_ctr_trig(unsigned int cmd);
|
||||
void hpst_dbg_mem_pd_trig(unsigned int cmd);
|
||||
void hpst_dbg_trig_gate(unsigned int cmd);
|
||||
void hpst_dbg_trig_mif(unsigned int cmd);
|
||||
void hpst_mem_pd_sw(unsigned int on);
|
||||
void hpst_vd1_sw(unsigned int on);
|
||||
|
||||
void dim_init_setting_once(void);
|
||||
void dim_hw_init_reg(void);
|
||||
|
||||
#endif
|
||||
107
drivers/amlogic/media/di_multi/di_api.c
Normal file
107
drivers/amlogic/media/di_multi/di_api.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_api.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/amlogic/media/vpu/vpu.h>
|
||||
|
||||
#include "di_api.h"
|
||||
/**********************************
|
||||
* DI api is used for other module
|
||||
*********************************/
|
||||
static const struct di_ext_ops di_ext = {
|
||||
.di_post_reg_rd = l_DI_POST_REG_RD,
|
||||
.di_post_wr_reg_bits = l_DI_POST_WR_REG_BITS,
|
||||
.post_update_mc = NULL,
|
||||
};
|
||||
|
||||
void dim_attach_to_local(void)
|
||||
{
|
||||
dil_attach_ext_api(&di_ext);
|
||||
}
|
||||
|
||||
bool dim_attach_ext_api(struct di_ext_ops *di_api)
|
||||
{
|
||||
#if 1
|
||||
if (!di_api)
|
||||
return false;
|
||||
|
||||
memcpy(di_api, &di_ext, sizeof(struct di_ext_ops));
|
||||
#else
|
||||
di_api = &di_ext;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*EXPORT_SYMBOL(dim_attach_ext_api);*/
|
||||
|
||||
/**********************************
|
||||
* ext_api used by DI
|
||||
********************************/
|
||||
#define ARY_TEMP2
|
||||
#ifdef ARY_TEMP2
|
||||
void ext_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on)
|
||||
{
|
||||
switch_vpu_mem_pd_vmod(vmod,
|
||||
on ? VPU_MEM_POWER_ON : VPU_MEM_POWER_DOWN);
|
||||
}
|
||||
|
||||
const struct ext_ops_s ext_ops = {
|
||||
.switch_vpu_mem_pd_vmod = ext_switch_vpu_mem_pd_vmod,
|
||||
/*no use ?*/
|
||||
/* .vf_get_receiver_name = vf_get_receiver_name,*/
|
||||
.switch_vpu_clk_gate_vmod = switch_vpu_clk_gate_vmod,
|
||||
.get_current_vscale_skip_count = get_current_vscale_skip_count,
|
||||
.canvas_pool_alloc_canvas_table = canvas_pool_alloc_canvas_table,
|
||||
};
|
||||
|
||||
#else
|
||||
void n_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on)
|
||||
{
|
||||
}
|
||||
|
||||
char *n_vf_get_receiver_name(const char *provider_name)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void n_switch_vpu_clk_gate_vmod(unsigned int vmod, int flag)
|
||||
{
|
||||
}
|
||||
|
||||
int n_get_current_vscale_skip_count(struct vframe_s *vf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 n_canvas_pool_alloc_canvas_table(const char *owner, u32 *tab,
|
||||
int size,
|
||||
enum canvas_map_type_e type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ext_ops_s ext_ops = {
|
||||
.switch_vpu_mem_pd_vmod = n_switch_vpu_mem_pd_vmod,
|
||||
.vf_get_receiver_name = n_vf_get_receiver_name,
|
||||
.switch_vpu_clk_gate_vmod = n_switch_vpu_clk_gate_vmod,
|
||||
.get_current_vscale_skip_count = n_get_current_vscale_skip_count,
|
||||
.canvas_pool_alloc_canvas_table = n_canvas_pool_alloc_canvas_table,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
55
drivers/amlogic/media/di_multi/di_api.h
Normal file
55
drivers/amlogic/media/di_multi/di_api.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_api.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_API_H__
|
||||
#define __DI_API_H__
|
||||
|
||||
#include <linux/amlogic/media/canvas/canvas_mgr.h>
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "../di_local/di_local.h"
|
||||
|
||||
/*--------------------------*/
|
||||
unsigned int l_DI_POST_REG_RD(unsigned int addr);
|
||||
int l_DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len);
|
||||
|
||||
/*--------------------------*/
|
||||
bool di_attach_ext_api(struct di_ext_ops *di_api);
|
||||
|
||||
/*attach di_ops to di_local*/
|
||||
bool dil_attach_ext_api(const struct di_ext_ops *di_api);
|
||||
void dim_attach_to_local(void);
|
||||
|
||||
/*--------------------------*/
|
||||
int get_current_vscale_skip_count(struct vframe_s *vf);
|
||||
|
||||
struct ext_ops_s {
|
||||
void (*switch_vpu_mem_pd_vmod)(unsigned int vmod, bool on);
|
||||
/* char *(*vf_get_receiver_name)(const char *provider_name);*/
|
||||
void (*switch_vpu_clk_gate_vmod)(unsigned int vmod, int flag);
|
||||
int (*get_current_vscale_skip_count)(struct vframe_s *vf);
|
||||
u32 (*canvas_pool_alloc_canvas_table)(const char *owner, u32 *tab,
|
||||
int size,
|
||||
enum canvas_map_type_e type);
|
||||
};
|
||||
|
||||
extern const struct ext_ops_s ext_ops;
|
||||
|
||||
/*--------------------------*/
|
||||
void dil_get_rev_mem(unsigned long *mstart, unsigned int *msize);
|
||||
void dil_get_flg(unsigned int *flg);
|
||||
|
||||
#endif /*__DI_API_H__*/
|
||||
21
drivers/amlogic/media/di_multi/di_data.h
Normal file
21
drivers/amlogic/media/di_multi/di_data.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_data.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_DATA_H__
|
||||
#define __DI_DATA_H__
|
||||
|
||||
#endif /*__DI_DATA_H__*/
|
||||
1374
drivers/amlogic/media/di_multi/di_data_l.h
Normal file
1374
drivers/amlogic/media/di_multi/di_data_l.h
Normal file
File diff suppressed because it is too large
Load Diff
1641
drivers/amlogic/media/di_multi/di_dbg.c
Normal file
1641
drivers/amlogic/media/di_multi/di_dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
69
drivers/amlogic/media/di_multi/di_dbg.h
Normal file
69
drivers/amlogic/media/di_multi/di_dbg.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_dbg.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_DBG_H__
|
||||
#define __DI_DBG_H__
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_provider.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_receiver.h>
|
||||
|
||||
void didbg_fs_init(void);
|
||||
void didbg_fs_exit(void);
|
||||
|
||||
void di_cfgx_init_val(void);
|
||||
|
||||
void didbg_vframe_in_copy(unsigned int ch, struct vframe_s *pvfm);
|
||||
void didbg_vframe_out_save(struct vframe_s *pvfm);
|
||||
|
||||
/********************************
|
||||
*debug register:
|
||||
*******************************/
|
||||
void ddbg_reg_save(unsigned int addr, unsigned int val,
|
||||
unsigned int st, unsigned int bw);
|
||||
void dim_ddbg_mod_save(unsigned int mod,
|
||||
unsigned int ch,
|
||||
unsigned int cnt);
|
||||
void ddbg_sw(unsigned int mode, bool on);
|
||||
|
||||
/********************************
|
||||
*time:
|
||||
*******************************/
|
||||
u64 cur_to_msecs(void);
|
||||
u64 cur_to_usecs(void); /*2019*/
|
||||
|
||||
/********************************
|
||||
*trace:
|
||||
*******************************/
|
||||
struct dim_tr_ops_s {
|
||||
void (*pre)(unsigned int index, unsigned long ctime);
|
||||
void (*post)(unsigned int index, unsigned long ctime);
|
||||
void (*pre_get)(unsigned int index);
|
||||
void (*pre_set)(unsigned int index);
|
||||
void (*pre_ready)(unsigned int index);
|
||||
void (*post_ready)(unsigned int index);
|
||||
void (*post_get)(unsigned int index);
|
||||
void (*post_get2)(unsigned int index);
|
||||
void (*post_set)(unsigned int index);
|
||||
void (*post_ir)(unsigned int index);
|
||||
void (*post_do)(unsigned int index);
|
||||
void (*post_peek)(unsigned int index);
|
||||
};
|
||||
|
||||
extern const struct dim_tr_ops_s dim_tr_ops;
|
||||
|
||||
#endif /*__DI_DBG_H__*/
|
||||
389
drivers/amlogic/media/di_multi/di_post.c
Normal file
389
drivers/amlogic/media/di_multi/di_post.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_post.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
#include "deinterlace_dbg.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_que.h"
|
||||
#include "di_task.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
#include "di_post.h"
|
||||
|
||||
#include "nr_downscale.h"
|
||||
#include "register.h"
|
||||
|
||||
void dpost_clear(void)/*not been called*/
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
memset(pst, 0, sizeof(struct di_hpst_s));
|
||||
}
|
||||
|
||||
void dpost_init(void)
|
||||
{/*reg:*/
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
|
||||
/*timer out*/
|
||||
di_tout_int(&pst->tout, 40); /*ms*/
|
||||
}
|
||||
|
||||
void pw_use_hw_post(enum eDI_SUB_ID channel, bool on)
|
||||
{
|
||||
struct di_hpst_s *post = get_hw_pst();
|
||||
|
||||
post->hw_flg_busy_post = on;
|
||||
if (on)
|
||||
post->curr_ch = channel;
|
||||
}
|
||||
|
||||
static bool pw_try_sw_ch_next_post(enum eDI_SUB_ID channel)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
struct di_hpst_s *post = get_hw_pst();
|
||||
enum eDI_SUB_ID lst_ch, nch;
|
||||
|
||||
lst_ch = channel;
|
||||
|
||||
nch = pw_ch_next_count(lst_ch);
|
||||
if (!get_reg_flag(nch) || get_flag_trig_unreg(nch))
|
||||
return false;
|
||||
|
||||
if (nch != channel)
|
||||
dim_ddbg_mod_save(eDI_DBG_MOD_POST_CH_CHG, nch, 0);/*dbg*/
|
||||
|
||||
post->curr_ch = nch;
|
||||
post->hw_flg_busy_post = true;
|
||||
ret = true;
|
||||
|
||||
/*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* debug */
|
||||
/*****************************/
|
||||
|
||||
/*****************************/
|
||||
/* STEP */
|
||||
/*****************************/
|
||||
|
||||
bool dpst_step_idle(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
bool reflesh = false;
|
||||
|
||||
if (!pw_try_sw_ch_next_post(pst->curr_ch))
|
||||
return false;
|
||||
|
||||
pst->pres = get_pre_stru(pst->curr_ch);
|
||||
pst->psts = get_post_stru(pst->curr_ch);
|
||||
pst->state++;/*tmp*/
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_check(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
struct di_post_stru_s *ppost;
|
||||
bool reflesh = false;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
ppost = get_post_stru(ch);
|
||||
|
||||
if (queue_empty(ch, QUEUE_POST_DOING)) {
|
||||
ppost->post_peek_underflow++;
|
||||
pst->state--;
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
pst->state++;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_set(void)
|
||||
{
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
vframe_t *vf_p = NULL;
|
||||
struct di_post_stru_s *ppost;
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
ppost = get_post_stru(ch);
|
||||
|
||||
di_buf = get_di_buf_head(ch, QUEUE_POST_DOING);
|
||||
if (dim_check_di_buf(di_buf, 20, ch)) {
|
||||
PR_ERR("%s:err1\n", __func__);
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
vf_p = di_buf->vframe;
|
||||
if (ppost->run_early_proc_fun_flag) {
|
||||
if (vf_p->early_process_fun)
|
||||
vf_p->early_process_fun = dim_do_post_wr_fun;
|
||||
}
|
||||
|
||||
dim_print("%s:pr_index=%d\n", __func__, di_buf->process_fun_index);
|
||||
if (di_buf->process_fun_index) { /*not bypass?*/
|
||||
|
||||
ppost->post_wr_cnt++;
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_process(di_buf, 0, vf_p->width - 1,
|
||||
0, vf_p->height - 1, vf_p);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
/*begin to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_EN, &pst->tout);
|
||||
|
||||
ppost->post_de_busy = 1;
|
||||
ppost->irq_time = cur_to_msecs();
|
||||
|
||||
/*state*/
|
||||
pst->state++;
|
||||
/*reflesh = true;*/
|
||||
} else {
|
||||
ppost->de_post_process_done = 1; /*trig done*/
|
||||
pst->flg_int_done = 1;
|
||||
|
||||
/*state*/
|
||||
pst->state++;/*pst->state = eDI_PST_ST_DONE;*/
|
||||
reflesh = true;
|
||||
}
|
||||
ppost->cur_post_buf = di_buf;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_wait_int(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
struct di_post_stru_s *ppost;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
|
||||
dim_print("%s:ch[%d],done_flg[%d]\n", __func__,
|
||||
pst->curr_ch, pst->flg_int_done);
|
||||
if (pst->flg_int_done) {
|
||||
/*finish to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_FINISH, &pst->tout);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_de_done_buf_config(ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
pst->flg_int_done = false;
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
} else {
|
||||
/*check if timeout:*/
|
||||
if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pst->tout)) {
|
||||
ppost = get_post_stru(ch);
|
||||
PR_WARN("ch[%d]:post timeout[%d]\n", ch,
|
||||
ppost->cur_post_buf->seq);
|
||||
dim_ddbg_mod_save(eDI_DBG_MOD_POST_TIMEOUT, ch, 0);
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_TIMEOUT;
|
||||
reflesh = true;
|
||||
}
|
||||
}
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
void dpst_timeout(unsigned int ch)
|
||||
{
|
||||
hpst_dbg_mem_pd_trig(0);
|
||||
post_close_new();
|
||||
#if 0
|
||||
di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP);
|
||||
di_post_reset();
|
||||
#endif
|
||||
dimh_pst_trig_resize();
|
||||
}
|
||||
|
||||
bool dpst_step_timeout(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
ulong flags = 0;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
dpst_timeout(ch);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_post_de_done_buf_config(ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
pst->flg_int_done = false;
|
||||
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpst_step_done(void)/*this step no use ?*/
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
unsigned int ch;
|
||||
bool reflesh = false;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
/* dim_post_de_done_buf_config(ch);*/
|
||||
|
||||
/*state*/
|
||||
pst->state = eDI_PST_ST_IDLE;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
const struct di_func_tab_s di_pst_func_tab[] = {
|
||||
{eDI_PST_ST_EXIT, NULL},
|
||||
{eDI_PST_ST_IDLE, dpst_step_idle},
|
||||
{eDI_PST_ST_CHECK, dpst_step_check},
|
||||
{eDI_PST_ST_SET, dpst_step_set},
|
||||
{eDI_PST_ST_WAIT_INT, dpst_step_wait_int},
|
||||
{eDI_PST_ST_TIMEOUT, dpst_step_timeout},
|
||||
{eDI_PST_ST_DONE, dpst_step_done},
|
||||
};
|
||||
|
||||
const char * const dpst_state_name[] = {
|
||||
"EXIT",
|
||||
"IDLE", /*swith to next channel?*/
|
||||
"CHECK",
|
||||
"SET",
|
||||
"WAIT_INT",
|
||||
"TIMEOUT",
|
||||
"DONE",
|
||||
};
|
||||
|
||||
const char *dpst_state_name_get(enum eDI_PST_ST state)
|
||||
{
|
||||
if (state > eDI_PST_ST_DONE)
|
||||
return "nothing";
|
||||
|
||||
return dpst_state_name[state];
|
||||
}
|
||||
|
||||
bool dpst_can_exit(unsigned int ch)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
bool ret = false;
|
||||
|
||||
if (ch != pst->curr_ch) {
|
||||
ret = true;
|
||||
} else {
|
||||
if (pst->state <= eDI_PST_ST_IDLE)
|
||||
ret = true;
|
||||
}
|
||||
pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n",
|
||||
__func__,
|
||||
ch, pst->curr_ch,
|
||||
dpst_state_name_get(pst->state),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool dpst_process_step2(void)
|
||||
{
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
enum eDI_PST_ST pst_st = pst->state;
|
||||
unsigned int ch;
|
||||
|
||||
ch = pst->curr_ch;
|
||||
if (pst_st > eDI_PST_ST_EXIT)
|
||||
dim_recycle_post_back(ch);
|
||||
|
||||
if ((pst_st <= eDI_PST_ST_DONE) &&
|
||||
di_pst_func_tab[pst_st].func)
|
||||
return di_pst_func_tab[pst_st].func();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void dpst_dbg_f_trig(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
PR_ERR("%s:can't get sem\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*set on/off and trig*/
|
||||
if (cmd & 0x10) {
|
||||
pst->dbg_f_en = 1;
|
||||
pst->dbg_f_cnt = cmd & 0xf;
|
||||
pst->dbg_f_lstate = pst->state;
|
||||
} else {
|
||||
pst->dbg_f_en = 0;
|
||||
}
|
||||
|
||||
up(&tsk->sem);
|
||||
}
|
||||
|
||||
void dpst_process(void)
|
||||
{
|
||||
bool reflesh;
|
||||
|
||||
struct di_hpst_s *pst = get_hw_pst();
|
||||
|
||||
if (pst->dbg_f_en) {
|
||||
if (pst->dbg_f_cnt) {
|
||||
dpst_process_step2();
|
||||
pst->dbg_f_cnt--;
|
||||
}
|
||||
if (pst->dbg_f_lstate != pst->state) {
|
||||
pr_info("ch[%d]:state:%s->%s\n",
|
||||
pst->curr_ch,
|
||||
dpst_state_name_get(pst->dbg_f_lstate),
|
||||
dpst_state_name_get(pst->state));
|
||||
|
||||
pst->dbg_f_lstate = pst->state;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reflesh = true;
|
||||
|
||||
while (reflesh)
|
||||
reflesh = dpst_process_step2();
|
||||
}
|
||||
27
drivers/amlogic/media/di_multi/di_post.h
Normal file
27
drivers/amlogic/media/di_multi/di_post.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_post.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_POST_H__
|
||||
#define __DI_POST_H__
|
||||
|
||||
void dpost_init(void);
|
||||
void dpst_process(void);
|
||||
const char *dpst_state_name_get(enum eDI_PST_ST state);
|
||||
void dpst_dbg_f_trig(unsigned int cmd);
|
||||
bool dpst_can_exit(unsigned int ch);
|
||||
|
||||
#endif /*__DI_POST_H__*/
|
||||
628
drivers/amlogic/media/di_multi/di_pps.c
Normal file
628
drivers/amlogic/media/di_multi/di_pps.c
Normal file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pps.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/amlogic/media/registers/regs/di_regs.h>
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "di_pps.h"
|
||||
#include "register.h"
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#if 0
|
||||
/* pps filter coefficients */
|
||||
#define COEF_BICUBIC 0
|
||||
#define COEF_3POINT_TRIANGLE 1
|
||||
#define COEF_4POINT_TRIANGLE 2
|
||||
#define COEF_BILINEAR 3
|
||||
#define COEF_2POINT_BILINEAR 4
|
||||
#define COEF_BICUBIC_SHARP 5
|
||||
#define COEF_3POINT_TRIANGLE_SHARP 6
|
||||
#define COEF_3POINT_BSPLINE 7
|
||||
#define COEF_4POINT_BSPLINE 8
|
||||
#define COEF_3D_FILTER 9
|
||||
#define COEF_NULL 0xff
|
||||
#define TOTAL_FILTERS 10
|
||||
|
||||
#define MAX_NONLINEAR_FACTOR 0x40
|
||||
|
||||
const u32 vpp_filter_coefs_bicubic_sharp[] = {
|
||||
3,
|
||||
33 | 0x8000,
|
||||
/* 0x01f80090, 0x01f80100, 0xff7f0200, 0xfe7f0300, */
|
||||
0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300,
|
||||
0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
|
||||
0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
|
||||
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
|
||||
0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
|
||||
0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
|
||||
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
|
||||
0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_bicubic[] = {
|
||||
4,
|
||||
33,
|
||||
0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
|
||||
0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
|
||||
0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
|
||||
0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
|
||||
0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
|
||||
0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
|
||||
0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
|
||||
0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_bilinear[] = {
|
||||
4,
|
||||
33,
|
||||
0x00800000, 0x007e0200, 0x007c0400, 0x007a0600,
|
||||
0x00780800, 0x00760a00, 0x00740c00, 0x00720e00,
|
||||
0x00701000, 0x006e1200, 0x006c1400, 0x006a1600,
|
||||
0x00681800, 0x00661a00, 0x00641c00, 0x00621e00,
|
||||
0x00602000, 0x005e2200, 0x005c2400, 0x005a2600,
|
||||
0x00582800, 0x00562a00, 0x00542c00, 0x00522e00,
|
||||
0x00503000, 0x004e3200, 0x004c3400, 0x004a3600,
|
||||
0x00483800, 0x00463a00, 0x00443c00, 0x00423e00,
|
||||
0x00404000
|
||||
};
|
||||
|
||||
const u32 vpp_3d_filter_coefs_bilinear[] = {
|
||||
2,
|
||||
33,
|
||||
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000,
|
||||
0x78080000, 0x760a0000, 0x740c0000, 0x720e0000,
|
||||
0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
|
||||
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000,
|
||||
0x60200000, 0x5e220000, 0x5c240000, 0x5a260000,
|
||||
0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
|
||||
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000,
|
||||
0x48380000, 0x463a0000, 0x443c0000, 0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_3point_triangle[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3f400100, 0x3d410200, 0x3c410300,
|
||||
0x3a420400, 0x39420500, 0x37430600, 0x36430700,
|
||||
0x35430800, 0x33450800, 0x32450900, 0x31450a00,
|
||||
0x30450b00, 0x2e460c00, 0x2d460d00, 0x2c470d00,
|
||||
0x2b470e00, 0x29480f00, 0x28481000, 0x27481100,
|
||||
0x26491100, 0x25491200, 0x24491300, 0x234a1300,
|
||||
0x224a1400, 0x214a1500, 0x204a1600, 0x1f4b1600,
|
||||
0x1e4b1700, 0x1d4b1800, 0x1c4c1800, 0x1b4c1900,
|
||||
0x1a4c1a00
|
||||
};
|
||||
|
||||
/* point_num =4, filt_len =4, group_num = 64, [1 2 1] */
|
||||
const u32 vpp_filter_coefs_4point_triangle[] = {
|
||||
4,
|
||||
33,
|
||||
0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
|
||||
0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
|
||||
0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
|
||||
0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
|
||||
0x18382808, 0x18382808, 0x17372909, 0x17372909,
|
||||
0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
|
||||
0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
|
||||
0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
|
||||
0x10303010
|
||||
};
|
||||
|
||||
/*
|
||||
*4th order (cubic) b-spline
|
||||
*filt_cubic point_num =4, filt_len =4, group_num = 64, [1 5 1]
|
||||
*/
|
||||
const u32 vpp_filter_coefs_4point_bspline[] = {
|
||||
4,
|
||||
33,
|
||||
0x15561500, 0x14561600, 0x13561700, 0x12561800,
|
||||
0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
|
||||
0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
|
||||
0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
|
||||
0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
|
||||
0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
|
||||
0x05473301, 0x05463401, 0x04453601, 0x04433702,
|
||||
0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
|
||||
0x033d3d03
|
||||
};
|
||||
|
||||
/*3rd order (quadratic) b-spline*/
|
||||
/*filt_quadratic, point_num =3, filt_len =3, group_num = 64, [1 6 1] */
|
||||
const u32 vpp_filter_coefs_3point_bspline[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3e420000, 0x3c440000, 0x3a460000,
|
||||
0x38480000, 0x364a0000, 0x344b0100, 0x334c0100,
|
||||
0x314e0100, 0x304f0100, 0x2e500200, 0x2c520200,
|
||||
0x2a540200, 0x29540300, 0x27560300, 0x26570300,
|
||||
0x24580400, 0x23590400, 0x215a0500, 0x205b0500,
|
||||
0x1e5c0600, 0x1d5c0700, 0x1c5d0700, 0x1a5e0800,
|
||||
0x195e0900, 0x185e0a00, 0x175f0a00, 0x15600b00,
|
||||
0x14600c00, 0x13600d00, 0x12600e00, 0x11600f00,
|
||||
0x10601000
|
||||
};
|
||||
|
||||
/*filt_triangle, point_num =3, filt_len =2.6, group_num = 64, [1 7 1] */
|
||||
const u32 vpp_filter_coefs_3point_triangle_sharp[] = {
|
||||
3,
|
||||
33,
|
||||
0x40400000, 0x3e420000, 0x3d430000, 0x3b450000,
|
||||
0x3a460000, 0x38480000, 0x37490000, 0x354b0000,
|
||||
0x344c0000, 0x324e0000, 0x314f0000, 0x2f510000,
|
||||
0x2e520000, 0x2c540000, 0x2b550000, 0x29570000,
|
||||
0x28580000, 0x265a0000, 0x245c0000, 0x235d0000,
|
||||
0x215f0000, 0x20600000, 0x1e620000, 0x1d620100,
|
||||
0x1b620300, 0x19630400, 0x17630600, 0x15640700,
|
||||
0x14640800, 0x12640a00, 0x11640b00, 0x0f650c00,
|
||||
0x0d660d00
|
||||
};
|
||||
|
||||
const u32 vpp_filter_coefs_2point_binilear[] = {
|
||||
2,
|
||||
33,
|
||||
0x80000000, 0x7e020000, 0x7c040000, 0x7a060000,
|
||||
0x78080000, 0x760a0000, 0x740c0000, 0x720e0000,
|
||||
0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
|
||||
0x68180000, 0x661a0000, 0x641c0000, 0x621e0000,
|
||||
0x60200000, 0x5e220000, 0x5c240000, 0x5a260000,
|
||||
0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
|
||||
0x50300000, 0x4e320000, 0x4c340000, 0x4a360000,
|
||||
0x48380000, 0x463a0000, 0x443c0000, 0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
static const u32 *filter_table[] = {
|
||||
vpp_filter_coefs_bicubic,
|
||||
vpp_filter_coefs_3point_triangle,
|
||||
vpp_filter_coefs_4point_triangle,
|
||||
vpp_filter_coefs_bilinear,
|
||||
vpp_filter_coefs_2point_binilear,
|
||||
vpp_filter_coefs_bicubic_sharp,
|
||||
vpp_filter_coefs_3point_triangle_sharp,
|
||||
vpp_filter_coefs_3point_bspline,
|
||||
vpp_filter_coefs_4point_bspline,
|
||||
vpp_3d_filter_coefs_bilinear
|
||||
};
|
||||
|
||||
static int chroma_filter_table[] = {
|
||||
COEF_BICUBIC, /* bicubic */
|
||||
COEF_3POINT_TRIANGLE,
|
||||
COEF_4POINT_TRIANGLE,
|
||||
COEF_4POINT_TRIANGLE, /* bilinear */
|
||||
COEF_2POINT_BILINEAR,
|
||||
COEF_3POINT_TRIANGLE, /* bicubic_sharp */
|
||||
COEF_3POINT_TRIANGLE, /* 3point_triangle_sharp */
|
||||
COEF_3POINT_TRIANGLE, /* 3point_bspline */
|
||||
COEF_4POINT_TRIANGLE, /* 4point_bspline */
|
||||
COEF_3D_FILTER /* can not change */
|
||||
};
|
||||
|
||||
static unsigned int vert_scaler_filter = 0xff;
|
||||
module_param(vert_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(vert_scaler_filter, "vert_scaler_filter");
|
||||
|
||||
static unsigned int vert_chroma_scaler_filter = 0xff;
|
||||
module_param(vert_chroma_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(vert_chroma_scaler_filter, "vert_chroma_scaler_filter");
|
||||
|
||||
static unsigned int horz_scaler_filter = 0xff;
|
||||
module_param(horz_scaler_filter, uint, 0664);
|
||||
MODULE_PARM_DESC(horz_scaler_filter, "horz_scaler_filter");
|
||||
|
||||
bool pre_scaler_en = true;
|
||||
module_param(pre_scaler_en, bool, 0664);
|
||||
MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en");
|
||||
#endif
|
||||
/*bicubic*/
|
||||
static const unsigned int di_filt_coef0[] = {
|
||||
0x00800000,
|
||||
0x007f0100,
|
||||
0xff7f0200,
|
||||
0xfe7f0300,
|
||||
0xfd7e0500,
|
||||
0xfc7e0600,
|
||||
0xfb7d0800,
|
||||
0xfb7c0900,
|
||||
0xfa7b0b00,
|
||||
0xfa7a0dff,
|
||||
0xf9790fff,
|
||||
0xf97711ff,
|
||||
0xf87613ff,
|
||||
0xf87416fe,
|
||||
0xf87218fe,
|
||||
0xf8701afe,
|
||||
0xf76f1dfd,
|
||||
0xf76d1ffd,
|
||||
0xf76b21fd,
|
||||
0xf76824fd,
|
||||
0xf76627fc,
|
||||
0xf76429fc,
|
||||
0xf7612cfc,
|
||||
0xf75f2ffb,
|
||||
0xf75d31fb,
|
||||
0xf75a34fb,
|
||||
0xf75837fa,
|
||||
0xf7553afa,
|
||||
0xf8523cfa,
|
||||
0xf8503ff9,
|
||||
0xf84d42f9,
|
||||
0xf84a45f9,
|
||||
0xf84848f8
|
||||
};
|
||||
|
||||
/* 2 point bilinear */
|
||||
static const unsigned int di_filt_coef1[] = {
|
||||
0x00800000,
|
||||
0x007e0200,
|
||||
0x007c0400,
|
||||
0x007a0600,
|
||||
0x00780800,
|
||||
0x00760a00,
|
||||
0x00740c00,
|
||||
0x00720e00,
|
||||
0x00701000,
|
||||
0x006e1200,
|
||||
0x006c1400,
|
||||
0x006a1600,
|
||||
0x00681800,
|
||||
0x00661a00,
|
||||
0x00641c00,
|
||||
0x00621e00,
|
||||
0x00602000,
|
||||
0x005e2200,
|
||||
0x005c2400,
|
||||
0x005a2600,
|
||||
0x00582800,
|
||||
0x00562a00,
|
||||
0x00542c00,
|
||||
0x00522e00,
|
||||
0x00503000,
|
||||
0x004e3200,
|
||||
0x004c3400,
|
||||
0x004a3600,
|
||||
0x00483800,
|
||||
0x00463a00,
|
||||
0x00443c00,
|
||||
0x00423e00,
|
||||
0x00404000
|
||||
};
|
||||
|
||||
/* 2 point bilinear, bank_length == 2*/
|
||||
static const unsigned int di_filt_coef2[] = {
|
||||
0x80000000,
|
||||
0x7e020000,
|
||||
0x7c040000,
|
||||
0x7a060000,
|
||||
0x78080000,
|
||||
0x760a0000,
|
||||
0x740c0000,
|
||||
0x720e0000,
|
||||
0x70100000,
|
||||
0x6e120000,
|
||||
0x6c140000,
|
||||
0x6a160000,
|
||||
0x68180000,
|
||||
0x661a0000,
|
||||
0x641c0000,
|
||||
0x621e0000,
|
||||
0x60200000,
|
||||
0x5e220000,
|
||||
0x5c240000,
|
||||
0x5a260000,
|
||||
0x58280000,
|
||||
0x562a0000,
|
||||
0x542c0000,
|
||||
0x522e0000,
|
||||
0x50300000,
|
||||
0x4e320000,
|
||||
0x4c340000,
|
||||
0x4a360000,
|
||||
0x48380000,
|
||||
0x463a0000,
|
||||
0x443c0000,
|
||||
0x423e0000,
|
||||
0x40400000
|
||||
};
|
||||
|
||||
#define ZOOM_BITS 20
|
||||
#define PHASE_BITS 16
|
||||
|
||||
static enum f2v_vphase_type_e top_conv_type = F2V_P2P;
|
||||
static enum f2v_vphase_type_e bot_conv_type = F2V_P2P;
|
||||
static unsigned int prehsc_en;
|
||||
static unsigned int prevsc_en;
|
||||
|
||||
static const unsigned char f2v_420_in_pos_luma[F2V_TYPE_MAX] = {
|
||||
0, 2, 0, 2, 0, 0, 0, 2, 0};
|
||||
#if 0
|
||||
static const unsigned char f2v_420_in_pos_chroma[F2V_TYPE_MAX] = {
|
||||
1, 5, 1, 5, 2, 2, 1, 5, 2};
|
||||
#endif
|
||||
static const unsigned char f2v_420_out_pos[F2V_TYPE_MAX] = {
|
||||
0, 2, 2, 0, 0, 2, 0, 0, 0};
|
||||
|
||||
static void f2v_get_vertical_phase(unsigned int zoom_ratio,
|
||||
enum f2v_vphase_type_e type,
|
||||
unsigned char bank_length,
|
||||
struct pps_f2v_vphase_s *vphase)
|
||||
{
|
||||
int offset_in, offset_out;
|
||||
|
||||
/* luma */
|
||||
offset_in = f2v_420_in_pos_luma[type] << PHASE_BITS;
|
||||
offset_out = (f2v_420_out_pos[type] * zoom_ratio)
|
||||
>> (ZOOM_BITS - PHASE_BITS);
|
||||
|
||||
vphase->rcv_num = bank_length;
|
||||
if (bank_length == 4 || bank_length == 3)
|
||||
vphase->rpt_num = 1;
|
||||
else
|
||||
vphase->rpt_num = 0;
|
||||
|
||||
if (offset_in > offset_out) {
|
||||
vphase->rpt_num = vphase->rpt_num + 1;
|
||||
vphase->phase =
|
||||
((4 << PHASE_BITS) + offset_out - offset_in) >> 2;
|
||||
} else {
|
||||
while ((offset_in + (4 << PHASE_BITS)) <= offset_out) {
|
||||
if (vphase->rpt_num == 1)
|
||||
vphase->rpt_num = 0;
|
||||
else
|
||||
vphase->rcv_num++;
|
||||
offset_in += 4 << PHASE_BITS;
|
||||
}
|
||||
vphase->phase = (offset_out - offset_in) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* patch 1: inp scaler 0: di wr scaler
|
||||
* support: TM2
|
||||
* not support: SM1
|
||||
*/
|
||||
void dim_pps_config(unsigned char path, int src_w, int src_h,
|
||||
int dst_w, int dst_h)
|
||||
{
|
||||
struct pps_f2v_vphase_s vphase;
|
||||
|
||||
int i;
|
||||
int hsc_en = 0, vsc_en = 0;
|
||||
int vsc_double_line_mode;
|
||||
unsigned int p_src_w, p_src_h;
|
||||
unsigned int vert_phase_step, horz_phase_step;
|
||||
unsigned char top_rcv_num, bot_rcv_num;
|
||||
unsigned char top_rpt_num, bot_rpt_num;
|
||||
unsigned short top_vphase, bot_vphase;
|
||||
unsigned char is_frame;
|
||||
int vert_bank_length = 4;
|
||||
|
||||
const unsigned int *filt_coef0 = di_filt_coef0;
|
||||
/*unsigned int *filt_coef1 = di_filt_coef1;*/
|
||||
const unsigned int *filt_coef2 = di_filt_coef2;
|
||||
|
||||
vsc_double_line_mode = 0;
|
||||
|
||||
if (src_h != dst_h)
|
||||
vsc_en = 1;
|
||||
if (src_w != dst_w)
|
||||
hsc_en = 1;
|
||||
/* config hdr size */
|
||||
Wr_reg_bits(DI_HDR_IN_HSIZE, dst_w, 0, 13);
|
||||
Wr_reg_bits(DI_HDR_IN_VSIZE, dst_h, 0, 13);
|
||||
p_src_w = (prehsc_en ? ((src_w + 1) >> 1) : src_w);
|
||||
p_src_h = prevsc_en ? ((src_h + 1) >> 1) : src_h;
|
||||
|
||||
Wr(DI_SC_HOLD_LINE, 0x10);
|
||||
|
||||
if (p_src_w > 2048) {
|
||||
/*force vert bank length = 2*/
|
||||
vert_bank_length = 2;
|
||||
vsc_double_line_mode = 1;
|
||||
}
|
||||
|
||||
/*write vert filter coefs*/
|
||||
Wr(DI_SC_COEF_IDX, 0x0000);
|
||||
for (i = 0; i < 33; i++) {
|
||||
if (vert_bank_length == 2)
|
||||
Wr(DI_SC_COEF, filt_coef2[i]); /*bilinear*/
|
||||
else
|
||||
Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/
|
||||
}
|
||||
|
||||
/*write horz filter coefs*/
|
||||
Wr(DI_SC_COEF_IDX, 0x0100);
|
||||
for (i = 0; i < 33; i++)
|
||||
Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/
|
||||
|
||||
if (p_src_h > 2048)
|
||||
vert_phase_step = ((p_src_h << 18) / dst_h) << 2;
|
||||
else
|
||||
vert_phase_step = (p_src_h << 20) / dst_h;
|
||||
if (p_src_w > 2048)
|
||||
horz_phase_step = ((p_src_w << 18) / dst_w) << 2;
|
||||
else
|
||||
horz_phase_step = (p_src_w << 20) / dst_w;
|
||||
|
||||
is_frame = ((top_conv_type == F2V_IT2P) ||
|
||||
(top_conv_type == F2V_IB2P) ||
|
||||
(top_conv_type == F2V_P2P));
|
||||
|
||||
if (is_frame) {
|
||||
f2v_get_vertical_phase(vert_phase_step, top_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
top_rcv_num = vphase.rcv_num;
|
||||
top_rpt_num = vphase.rpt_num;
|
||||
top_vphase = vphase.phase;
|
||||
|
||||
bot_rcv_num = 0;
|
||||
bot_rpt_num = 0;
|
||||
bot_vphase = 0;
|
||||
} else {
|
||||
f2v_get_vertical_phase(vert_phase_step, top_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
top_rcv_num = vphase.rcv_num;
|
||||
top_rpt_num = vphase.rpt_num;
|
||||
top_vphase = vphase.phase;
|
||||
|
||||
f2v_get_vertical_phase(vert_phase_step, bot_conv_type,
|
||||
vert_bank_length, &vphase);
|
||||
bot_rcv_num = vphase.rcv_num;
|
||||
bot_rpt_num = vphase.rpt_num;
|
||||
bot_vphase = vphase.phase;
|
||||
}
|
||||
vert_phase_step = (vert_phase_step << 4);
|
||||
horz_phase_step = (horz_phase_step << 4);
|
||||
|
||||
Wr(DI_SC_LINE_IN_LENGTH, src_w);
|
||||
Wr(DI_SC_PIC_IN_HEIGHT, src_h);
|
||||
Wr(DI_VSC_REGION12_STARTP, 0);
|
||||
Wr(DI_VSC_REGION34_STARTP, ((dst_h << 16) | dst_h));
|
||||
Wr(DI_VSC_REGION4_ENDP, (dst_h - 1));
|
||||
|
||||
Wr(DI_VSC_START_PHASE_STEP, vert_phase_step);
|
||||
Wr(DI_VSC_REGION0_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION1_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION3_PHASE_SLOPE, 0);
|
||||
Wr(DI_VSC_REGION4_PHASE_SLOPE, 0);
|
||||
|
||||
Wr(DI_VSC_PHASE_CTRL,
|
||||
((vsc_double_line_mode << 17) |
|
||||
(!is_frame) << 16) |
|
||||
(0 << 15) |
|
||||
(bot_rpt_num << 13) |
|
||||
(bot_rcv_num << 8) |
|
||||
(0 << 7) |
|
||||
(top_rpt_num << 5) |
|
||||
(top_rcv_num));
|
||||
Wr(DI_VSC_INI_PHASE, (bot_vphase << 16) | top_vphase);
|
||||
Wr(DI_HSC_REGION12_STARTP, 0);
|
||||
Wr(DI_HSC_REGION34_STARTP, (dst_w << 16) | dst_w);
|
||||
Wr(DI_HSC_REGION4_ENDP, dst_w - 1);
|
||||
|
||||
Wr(DI_HSC_START_PHASE_STEP, horz_phase_step);
|
||||
Wr(DI_HSC_REGION0_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION1_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION3_PHASE_SLOPE, 0);
|
||||
Wr(DI_HSC_REGION4_PHASE_SLOPE, 0);
|
||||
|
||||
Wr(DI_HSC_PHASE_CTRL, (1 << 21) | (4 << 16) | 0);
|
||||
Wr_reg_bits(DI_SC_TOP_CTRL, (path ? 3 : 0), 29, 2);
|
||||
Wr(DI_SC_MISC,
|
||||
(prevsc_en << 21) |
|
||||
(prehsc_en << 20) | /* prehsc_en */
|
||||
(prevsc_en << 19) | /* prevsc_en */
|
||||
(vsc_en << 18) | /* vsc_en */
|
||||
(hsc_en << 17) | /* hsc_en */
|
||||
((vsc_en | hsc_en) << 16) | /* sc_top_en */
|
||||
(1 << 15) | /* vd1 sc out enable */
|
||||
(0 << 12) | /* horz nonlinear 4region enable */
|
||||
(4 << 8) | /* horz scaler bank length */
|
||||
(0 << 5) | /* vert scaler phase field enable */
|
||||
(0 << 4) | /* vert nonlinear 4region enable */
|
||||
(vert_bank_length << 0) /* vert scaler bank length */
|
||||
);
|
||||
|
||||
pr_info("[pps] %s input %d %d output %d %d.\n",
|
||||
path ? "pre" : "post", src_w, src_h, dst_w, dst_h);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x374e ~ 0x376d, 20 regs
|
||||
*/
|
||||
void dim_dump_pps_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x374e;
|
||||
|
||||
pr_info("-----dump pps start-----\n");
|
||||
for (i = 0x374e; i < 0x376e; i++) {
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2),
|
||||
i, dim_RDMA_RD(i));
|
||||
}
|
||||
pr_info("-----dump pps end-----\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* di pre h scaling down function
|
||||
* only have h scaling down
|
||||
* support: sm1 tm2 ...
|
||||
* 0x37b0 ~ 0x37b5
|
||||
*/
|
||||
void dim_inp_hsc_setting(u32 src_w, u32 dst_w)
|
||||
{
|
||||
u32 i;
|
||||
u32 hsc_en;
|
||||
u32 horz_phase_step;
|
||||
const int *filt_coef0 = di_filt_coef0;
|
||||
/*int *filt_coef1 = di_filt_coef1;*/
|
||||
/*int *filt_coef2 = di_filt_coef2;*/
|
||||
|
||||
if (src_w == dst_w) {
|
||||
hsc_en = 0;
|
||||
} else {
|
||||
hsc_en = 1;
|
||||
/*write horz filter coefs*/
|
||||
dim_RDMA_WR(DI_VIU_HSC_COEF_IDX, 0x0100);
|
||||
for (i = 0; i < 33; i++) /*bicubic*/
|
||||
dim_RDMA_WR(DI_VIU_HSC_COEF, filt_coef0[i]);
|
||||
|
||||
horz_phase_step = (src_w << 20) / dst_w;
|
||||
horz_phase_step = (horz_phase_step << 4);
|
||||
dim_RDMA_WR(DI_VIU_HSC_WIDTHM1,
|
||||
(src_w - 1) << 16 | (dst_w - 1));
|
||||
dim_RDMA_WR(DI_VIU_HSC_PHASE_STEP, horz_phase_step);
|
||||
dim_RDMA_WR(DI_VIU_HSC_PHASE_CTRL, 0);
|
||||
}
|
||||
dim_RDMA_WR(DI_VIU_HSC_CTRL,
|
||||
(4 << 20) | /* initial receive number*/
|
||||
(0 << 12) | /* initial pixel ptr*/
|
||||
(1 << 10) | /* repeat first pixel number*/
|
||||
(0 << 8) | /* sp422 mode*/
|
||||
(4 << 4) | /* horz scaler bank length*/
|
||||
(0 << 2) | /* phase0 always en*/
|
||||
(0 << 1) | /* nearest_en*/
|
||||
(hsc_en << 0)); /* hsc_en*/
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x37b0 ~ 0x37b5
|
||||
*/
|
||||
void dim_dump_hdownscler_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x374e;
|
||||
|
||||
pr_info("-----dump hdownscler start-----\n");
|
||||
for (i = 0x37b0; i < 0x37b5; i++) {
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2),
|
||||
i, dim_RDMA_RD(i));
|
||||
}
|
||||
pr_info("-----dump hdownscler end-----\n");
|
||||
}
|
||||
|
||||
int dim_seq_file_module_para_pps(struct seq_file *seq)
|
||||
{
|
||||
seq_puts(seq, "pps---------------\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
112
drivers/amlogic/media/di_multi/di_pps.h
Normal file
112
drivers/amlogic/media/di_multi/di_pps.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pps.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DI_PPS_H
|
||||
#define DI_PPS_H
|
||||
#include <linux/amlogic/media/video_sink/video.h>
|
||||
#include <linux/amlogic/media/video_sink/vpp.h>
|
||||
#if 0
|
||||
#define VPP_FLAG_WIDEMODE_MASK 0x0000000F
|
||||
#define VPP_FLAG_INTERLACE_OUT 0x00000010
|
||||
#define VPP_FLAG_INTERLACE_IN 0x00000020
|
||||
#define VPP_FLAG_CBCR_SEPARATE 0x00000040
|
||||
#define VPP_FLAG_ZOOM_SHORTSIDE 0x00000080
|
||||
#define VPP_FLAG_AR_MASK 0x0003ff00
|
||||
#define VPP_FLAG_AR_BITS 8
|
||||
#define VPP_FLAG_PORTRAIT_MODE 0x00040000
|
||||
#define VPP_FLAG_VSCALE_DISABLE 0x00080000
|
||||
|
||||
#define IDX_H (2 << 8)
|
||||
#define IDX_V_Y (1 << 13)
|
||||
#define IDX_V_CBCR ((1 << 13) | (1 << 8))
|
||||
|
||||
#define ASPECT_4_3 ((3 << 8) / 4)
|
||||
#define ASPECT_16_9 ((9 << 8) / 16)
|
||||
|
||||
#define SPEED_CHECK_DONE 0
|
||||
#define SPEED_CHECK_HSKIP 1
|
||||
#define SPEED_CHECK_VSKIP 2
|
||||
|
||||
enum f2v_vphase_type_e {
|
||||
F2V_IT2IT = 0,
|
||||
F2V_IB2IB,
|
||||
F2V_IT2IB,
|
||||
F2V_IB2IT,
|
||||
F2V_P2IT,
|
||||
F2V_P2IB,
|
||||
F2V_IT2P,
|
||||
F2V_IB2P,
|
||||
F2V_P2P,
|
||||
F2V_TYPE_MAX
|
||||
}; /* frame to video conversion type */
|
||||
#endif
|
||||
|
||||
enum hdr2_scaler_e {
|
||||
hdr2_scaler_postdi = 0,
|
||||
hdr2_scaler_predi = 1,
|
||||
};
|
||||
|
||||
struct pps_f2v_vphase_s {
|
||||
unsigned char rcv_num;
|
||||
unsigned char rpt_num;
|
||||
unsigned short phase;
|
||||
};
|
||||
|
||||
struct ppsfilter_mode_s {
|
||||
u32 pps_hf_start_phase_step;
|
||||
u32 pps_hf_start_phase_slope;
|
||||
u32 pps_hf_end_phase_slope;
|
||||
const u32 *pps_vert_coeff;
|
||||
const u32 *pps_horz_coeff;
|
||||
u32 pps_sc_misc_;
|
||||
u32 pps_vsc_start_phase_step;
|
||||
u32 pps_hsc_start_phase_step;
|
||||
bool pps_pre_vsc_en;
|
||||
bool pps_pre_hsc_en;
|
||||
u32 pps_vert_filter;
|
||||
u32 pps_horz_filter;
|
||||
const u32 *pps_chroma_coeff;
|
||||
u32 pps_chroma_filter_en;
|
||||
};
|
||||
|
||||
struct pps_frame_par_s {
|
||||
u32 pps_vsc_startp;
|
||||
u32 pps_vsc_endp;
|
||||
u32 pps_hsc_startp;
|
||||
u32 pps_hsc_linear_startp;
|
||||
u32 pps_hsc_linear_endp;
|
||||
u32 pps_hsc_endp;
|
||||
u32 VPP_hf_ini_phase_;
|
||||
struct f2v_vphase_s VPP_vf_ini_phase_[9];
|
||||
u32 pps_pic_in_height_;
|
||||
u32 pps_line_in_length_;
|
||||
struct ppsfilter_mode_s pps_filter;
|
||||
u32 pps_3d_mode;
|
||||
u32 trans_fmt;
|
||||
/* bit[1:0] 0: 1 pic,1:two pic one buf,2:tow pic two buf */
|
||||
/* bit[2]0:select pic0,1:select pic1 */
|
||||
/* bit[3]0:pic0 first,1:pic1 first */
|
||||
bool pps_3d_scale;
|
||||
};
|
||||
|
||||
void dim_pps_config(unsigned char path, int src_w, int src_h,
|
||||
int dst_w, int dst_h);
|
||||
void dim_dump_pps_reg(unsigned int base_addr);
|
||||
void dim_inp_hsc_setting(u32 src_w, u32 dst_w);
|
||||
void dim_dump_hdownscler_reg(unsigned int base_addr);
|
||||
|
||||
#endif
|
||||
1969
drivers/amlogic/media/di_multi/di_prc.c
Normal file
1969
drivers/amlogic/media/di_multi/di_prc.c
Normal file
File diff suppressed because it is too large
Load Diff
131
drivers/amlogic/media/di_multi/di_prc.h
Normal file
131
drivers/amlogic/media/di_multi/di_prc.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_prc.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_PRC_H__
|
||||
#define __DI_PRC_H__
|
||||
|
||||
bool dip_prob(void);
|
||||
void dip_exit(void);
|
||||
|
||||
void dip_even_reg_init_val(unsigned int ch);
|
||||
void dip_even_unreg_val(unsigned int ch);
|
||||
|
||||
/************************/
|
||||
/* CMA */
|
||||
/************************/
|
||||
void dip_wq_cma_run(unsigned char ch, bool reg_cmd);
|
||||
bool dip_cma_st_is_ready(unsigned int ch);
|
||||
bool dip_cma_st_is_idle(unsigned int ch);
|
||||
bool dip_cma_st_is_idl_all(void);
|
||||
enum eDI_CMA_ST dip_cma_get_st(unsigned int ch);
|
||||
void dip_cma_st_set_ready_all(void);
|
||||
void dip_cma_close(void);
|
||||
const char *di_cma_dbg_get_st_name(unsigned int ch);
|
||||
|
||||
/*************************/
|
||||
/* STATE*/
|
||||
/*************************/
|
||||
bool dip_event_reg_chst(unsigned int ch);
|
||||
bool dip_event_unreg_chst(unsigned int ch);
|
||||
void dip_chst_process_reg(unsigned int ch);
|
||||
|
||||
void dip_hw_process(void);
|
||||
|
||||
void dip_chst_process_ch(void);
|
||||
bool dip_chst_change_2unreg(void);
|
||||
|
||||
enum eDI_TOP_STATE dip_chst_get(unsigned int ch);
|
||||
const char *dip_chst_get_name_curr(unsigned int ch);
|
||||
const char *dip_chst_get_name(enum eDI_TOP_STATE chst);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* summmary variable
|
||||
*
|
||||
**************************************/
|
||||
void di_sum_reg_init(unsigned int ch);
|
||||
void di_sum_set(unsigned int ch, enum eDI_SUM id, unsigned int val);
|
||||
unsigned int di_sum_inc(unsigned int ch, enum eDI_SUM id);
|
||||
unsigned int di_sum_get(unsigned int ch, enum eDI_SUM id);
|
||||
void di_sum_get_info(unsigned int ch, enum eDI_SUM id, char **name,
|
||||
unsigned int *pval);
|
||||
unsigned int di_sum_get_tab_size(void);
|
||||
bool di_sum_check(unsigned int ch, enum eDI_SUM id);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* cfg ctr top
|
||||
* bool
|
||||
**************************************/
|
||||
char *di_cfg_top_get_name(enum eDI_CFG_TOP_IDX idx);
|
||||
void di_cfg_top_get_info(unsigned int idx, char **name);
|
||||
void di_cfg_top_init_val(void);
|
||||
bool di_cfg_top_get(enum eDI_CFG_TOP_IDX id);
|
||||
void di_cfg_top_set(enum eDI_CFG_TOP_IDX id, bool en);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* cfg ctr x
|
||||
* bool
|
||||
**************************************/
|
||||
char *di_cfgx_get_name(enum eDI_CFGX_IDX idx);
|
||||
void di_cfgx_get_info(enum eDI_CFGX_IDX idx, char **name);
|
||||
void di_cfgx_init_val(void);
|
||||
bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx);
|
||||
void di_cfgx_set(unsigned int ch, enum eDI_CFGX_IDX idx, bool en);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* module para top
|
||||
* int
|
||||
**************************************/
|
||||
char *di_mp_uit_get_name(enum eDI_MP_UI_T idx);
|
||||
void di_mp_uit_init_val(void);
|
||||
int di_mp_uit_get(enum eDI_MP_UI_T idx);
|
||||
void di_mp_uit_set(enum eDI_MP_UI_T idx, int val);
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* module para x
|
||||
* unsigned int
|
||||
**************************************/
|
||||
char *di_mp_uix_get_name(enum eDI_MP_UIX_T idx);
|
||||
void di_mp_uix_init_val(void);
|
||||
unsigned int di_mp_uix_get(unsigned int ch, enum eDI_MP_UIX_T idx);
|
||||
void di_mp_uix_set(unsigned int ch, enum eDI_MP_UIX_T idx,
|
||||
unsigned int val);
|
||||
|
||||
/****************************************/
|
||||
/* do_table */
|
||||
/****************************************/
|
||||
void do_table_init(struct do_table_s *pdo,
|
||||
const struct do_table_ops_s *ptable,
|
||||
unsigned int size_tab);
|
||||
/* now only call in same thread */
|
||||
void do_talbe_cmd(struct do_table_s *pdo, enum eDO_TABLE_CMD cmd);
|
||||
void do_table_working(struct do_table_s *pdo);
|
||||
bool do_table_is_crr(struct do_table_s *pdo, unsigned int state);
|
||||
|
||||
enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel);
|
||||
|
||||
void dip_init_value_reg(unsigned int ch);
|
||||
|
||||
bool di_is_pause(unsigned int ch);
|
||||
void di_pause_step_done(unsigned int ch);
|
||||
void di_pause(unsigned int ch, bool on);
|
||||
|
||||
#endif /*__DI_PRC_H__*/
|
||||
985
drivers/amlogic/media/di_multi/di_pre.c
Normal file
985
drivers/amlogic/media/di_multi/di_pre.c
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pre.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
#include "deinterlace_dbg.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_que.h"
|
||||
#include "di_task.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
#include "di_pre.h"
|
||||
|
||||
#include "nr_downscale.h"
|
||||
#include "register.h"
|
||||
|
||||
/****************************************
|
||||
* 1. copy curr to last
|
||||
* 2. set curr
|
||||
****************************************/
|
||||
void pre_vinfo_set(unsigned int ch,
|
||||
struct vframe_s *ori_vframe)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
|
||||
memcpy(vl, vc, sizeof(struct di_vinfo_s));
|
||||
|
||||
vc->ch = ch;
|
||||
vc->vtype = ori_vframe->type;
|
||||
vc->src_type = ori_vframe->source_type;
|
||||
vc->trans_fmt = ori_vframe->trans_fmt;
|
||||
|
||||
if (COM_ME(ori_vframe->type, VIDTYPE_COMPRESS)) {
|
||||
vc->h = ori_vframe->compWidth;
|
||||
vc->v = ori_vframe->compHeight;
|
||||
} else {
|
||||
vc->h = ori_vframe->width;
|
||||
vc->v = ori_vframe->height;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* compare current vframe info with last
|
||||
* return
|
||||
* 0. no change
|
||||
* 1. video format channge
|
||||
* 2. scan mode channge?
|
||||
****************************************/
|
||||
unsigned int is_vinfo_change(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
struct di_pre_stru_s *ppre = get_pre_stru(ch);
|
||||
unsigned int ret = 0;
|
||||
|
||||
if (vc->src_type != vl->src_type ||
|
||||
!COM_M(DI_VFM_T_MASK_CHANGE, vc->vtype, vl->vtype) ||
|
||||
vc->v != vl->v ||
|
||||
vc->h != vl->h ||
|
||||
vc->trans_fmt != vl->trans_fmt) {
|
||||
/* video format changed */
|
||||
ret = 1;
|
||||
} else if (!COM_M(VIDTYPE_VIU_FIELD, vc->vtype, vl->vtype))
|
||||
/* just scan mode changed */
|
||||
ret = 2;
|
||||
|
||||
if (ret) {
|
||||
dim_print(
|
||||
"%s:ch[%d]: %dth source change 2: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n",
|
||||
__func__,
|
||||
ch,
|
||||
/*jiffies_to_msecs(jiffies_64),*/
|
||||
ppre->in_seq,
|
||||
vl->vtype,
|
||||
vl->h,
|
||||
vl->v,
|
||||
vl->src_type,
|
||||
vc->vtype,
|
||||
vc->h,
|
||||
vc->v,
|
||||
vc->src_type);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (!vfm)
|
||||
return ret;
|
||||
pre_vinfo_set(ch, vfm);
|
||||
if (is_vinfo_change(ch)) {
|
||||
if (!is_bypass2(vfm, ch)) {
|
||||
set_bypass2_complete(ch, false);
|
||||
PR_INF("%s:\n", __func__);
|
||||
/*task_send_ready();*/
|
||||
task_send_cmd(LCMD1(eCMD_CHG, ch));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int di_get_other_ch(unsigned int curr)
|
||||
{
|
||||
return curr ? 0 : 1;
|
||||
}
|
||||
|
||||
bool is_bypass_i_p(void)
|
||||
{
|
||||
bool ret = false;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
struct di_vinfo_s *vc = &pre->vinf_curr;
|
||||
#if 0
|
||||
struct di_vinfo_s *vl = &pre->vinf_lst;
|
||||
|
||||
if (vl->ch != vc->ch &&
|
||||
vf_type_is_interlace(vl->vtype) &&
|
||||
vf_type_is_prog(vc->vtype)) {
|
||||
ret = true;
|
||||
}
|
||||
#else
|
||||
unsigned int ch_c, ch_l;
|
||||
|
||||
struct di_pre_stru_s *ppre_c, *ppre_l;
|
||||
|
||||
if (!get_reg_flag(0) ||
|
||||
!get_reg_flag(1))
|
||||
return ret;
|
||||
|
||||
ch_c = vc->ch;
|
||||
ch_l = (ch_c ? 0 : 1);
|
||||
ppre_c = get_pre_stru(ch_c);
|
||||
ppre_l = get_pre_stru(ch_l);
|
||||
if (vf_type_is_interlace(ppre_l->cur_inp_type) &&
|
||||
vf_type_is_prog(ppre_c->cur_inp_type)) {
|
||||
ret = true;
|
||||
dim_print("ch[%d]:bypass p\n", ch_c);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_clear(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
memset(pre, 0, sizeof(struct di_hpre_s));
|
||||
}
|
||||
|
||||
void dpre_init(void)
|
||||
{/*reg:*/
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->pre_st = eDI_PRE_ST_IDLE;
|
||||
|
||||
/*timer out*/
|
||||
di_tout_int(&pre->tout, 40); /*ms*/
|
||||
}
|
||||
|
||||
void pw_use_hw_pre(enum eDI_SUB_ID channel, bool on)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->hw_flg_busy_pre = on;
|
||||
if (on)
|
||||
pre->curr_ch = channel;
|
||||
}
|
||||
|
||||
enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel)
|
||||
{
|
||||
int i;
|
||||
unsigned int lch, nch;
|
||||
|
||||
nch = channel;
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++) {
|
||||
lch = channel + i + 1;
|
||||
if (lch >= DI_CHANNEL_NUB)
|
||||
lch -= DI_CHANNEL_NUB;
|
||||
#if 0
|
||||
if (pbm->sub_act_flg[lch]) {
|
||||
nch = lch;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (get_reg_flag(lch) &&
|
||||
!get_flag_trig_unreg(lch) &&
|
||||
!is_bypss2_complete(lch)) {
|
||||
nch = lch;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nch;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
static bool pw_try_sw_ch_next_pre(enum eDI_SUB_ID channel)
|
||||
{
|
||||
bool ret = false;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
enum eDI_SUB_ID lst_ch, nch;
|
||||
|
||||
lst_ch = channel;
|
||||
|
||||
nch = pw_ch_next_count(lst_ch);
|
||||
if (!get_reg_flag(nch) ||
|
||||
get_flag_trig_unreg(nch) ||
|
||||
is_bypss2_complete(nch))
|
||||
return false;
|
||||
|
||||
pre->curr_ch = nch;
|
||||
pre->hw_flg_busy_pre = true;
|
||||
ret = true;
|
||||
|
||||
/*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* debug */
|
||||
/*****************************/
|
||||
|
||||
unsigned int di_dbg_pre_cnt;
|
||||
|
||||
void dbg_cnt_begin(void)
|
||||
{
|
||||
di_dbg_pre_cnt = 0x10;
|
||||
}
|
||||
|
||||
void dbg_cnt_print(void)
|
||||
{
|
||||
if (di_dbg_pre_cnt < 0xf)
|
||||
return;
|
||||
|
||||
if (di_dbg_pre_cnt > 0x10) {
|
||||
di_dbg_pre_cnt++;
|
||||
pr_info("di:[%d]\n", di_dbg_pre_cnt);
|
||||
}
|
||||
|
||||
if (di_dbg_pre_cnt > 0x15)
|
||||
di_dbg_pre_cnt = 0;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* STEP */
|
||||
/*****************************/
|
||||
void dpre_recyc(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
pre->check_recycle_buf_cnt = 0;
|
||||
while (dim_check_recycle_buf(ch) & 1) {
|
||||
if (pre->check_recycle_buf_cnt++ > MAX_IN_BUF_NUM) {
|
||||
di_pr_info("%s: dim_check_recycle_buf time out!!\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dpre_vdoing(unsigned int ch)
|
||||
{
|
||||
struct di_post_stru_s *ppost = get_post_stru(ch);
|
||||
|
||||
ppost->di_post_process_cnt = 0;
|
||||
while (dim_process_post_vframe(ch)) {
|
||||
if (ppost->di_post_process_cnt++ >
|
||||
MAX_POST_BUF_NUM) {
|
||||
di_pr_info("%s: dim_process_post_vframe time out!!\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dpre_can_exit(unsigned int ch)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool ret = false;
|
||||
|
||||
if (ch != pre->curr_ch) {
|
||||
ret = true;
|
||||
} else {
|
||||
if (pre->pre_st <= eDI_PRE_ST4_IDLE)
|
||||
ret = true;
|
||||
}
|
||||
pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n",
|
||||
__func__,
|
||||
ch, pre->curr_ch,
|
||||
dpre_state4_name_get(pre->pre_st),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_dbg_f_trig(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
PR_ERR("%s:can't get sem\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*set on/off and trig*/
|
||||
if (cmd & 0x10) {
|
||||
pre->dbg_f_en = 1;
|
||||
pre->dbg_f_cnt = cmd & 0xf;
|
||||
pre->dbg_f_lstate = pre->pre_st;
|
||||
} else {
|
||||
pre->dbg_f_en = 0;
|
||||
}
|
||||
|
||||
up(&tsk->sem);
|
||||
}
|
||||
|
||||
void dpre_process(void)
|
||||
{
|
||||
bool reflesh;
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (pre->dbg_f_en) {
|
||||
if (pre->dbg_f_cnt) {
|
||||
dpre_process_step4();
|
||||
pre->dbg_f_cnt--;
|
||||
}
|
||||
if (pre->dbg_f_lstate != pre->pre_st) {
|
||||
pr_info("ch[%d]:state:%s->%s\n",
|
||||
pre->curr_ch,
|
||||
dpre_state4_name_get(pre->dbg_f_lstate),
|
||||
dpre_state4_name_get(pre->pre_st));
|
||||
|
||||
pre->dbg_f_lstate = pre->pre_st;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reflesh = true;
|
||||
|
||||
while (reflesh) {
|
||||
reflesh = dpre_process_step4();
|
||||
#if 0 /*debug only*/
|
||||
dbg_tsk("ch[%d]:st[%s]r[%d]\n", pre->curr_ch,
|
||||
dpre_state4_name_get(pre->pre_st), reflesh);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
enum eDI_PRE_MT {
|
||||
eDI_PRE_MT_CHECK = K_DO_TABLE_ID_START,
|
||||
eDI_PRE_MT_SET,
|
||||
eDI_PRE_MT_WAIT_INT,
|
||||
eDI_PRE_MT_TIME_OUT,
|
||||
};
|
||||
|
||||
/*use do_table:*/
|
||||
unsigned int dpre_mtotal_check(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if ((pre_run_flag == DI_RUN_FLAG_RUN) ||
|
||||
(pre_run_flag == DI_RUN_FLAG_STEP)) {
|
||||
if (pre_run_flag == DI_RUN_FLAG_STEP)
|
||||
pre_run_flag = DI_RUN_FLAG_STEP_DONE;
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
if (dim_pre_de_buf_config(pre->curr_ch))
|
||||
ret = K_DO_R_FINISH;
|
||||
else
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
|
||||
dim_dbg_pre_cnt(pre->curr_ch, "x");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_set(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
ulong flags = 0;
|
||||
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_pre_de_process(pre->curr_ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
/*begin to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_EN, &pre->tout);
|
||||
|
||||
return K_DO_R_FINISH;
|
||||
}
|
||||
|
||||
enum eDI_WAIT_INT {
|
||||
eDI_WAIT_INT_NEED_WAIT,
|
||||
eDI_WAIT_INT_HAVE_INT,
|
||||
eDI_WAIT_INT_TIME_OUT,
|
||||
};
|
||||
|
||||
/*
|
||||
*return: enum eDI_WAIT_INT
|
||||
*
|
||||
*/
|
||||
enum eDI_WAIT_INT di_pre_wait_int(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
ulong flags = 0;
|
||||
struct di_pre_stru_s *ppre;
|
||||
|
||||
enum eDI_WAIT_INT ret = eDI_WAIT_INT_NEED_WAIT;
|
||||
|
||||
if (pre->flg_int_done) {
|
||||
/*have INT done flg*/
|
||||
/*DI_INTR_CTRL[bit 0], NRWR_done, set by
|
||||
* hardware when NRWR is done,clear by write 1
|
||||
* by code;[bit 1]
|
||||
* MTNWR_done, set by hardware when MTNWR
|
||||
* is done, clear by write 1 by code;these two
|
||||
* bits have nothing to do with
|
||||
* DI_INTR_CTRL[16](NRW irq mask, 0 to enable
|
||||
* irq) and DI_INTR_CTRL[17]
|
||||
* (MTN irq mask, 0 to enable irq).two
|
||||
* interrupts are raised if both
|
||||
* DI_INTR_CTRL[16] and DI_INTR_CTRL[17] are 0
|
||||
*/
|
||||
#if 0
|
||||
data32 = Rd(DI_INTR_CTRL);
|
||||
if (((data32 & 0x1) &&
|
||||
((ppre->enable_mtnwr == 0) || (data32 & 0x2))) ||
|
||||
(ppre->pre_de_clear_flag == 2)) {
|
||||
dim_RDMA_WR(DI_INTR_CTRL, data32);
|
||||
}
|
||||
#endif
|
||||
di_pre_wait_irq_set(false);
|
||||
/*finish to count timer*/
|
||||
di_tout_contr(eDI_TOUT_CONTR_FINISH, &pre->tout);
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
|
||||
dim_pre_de_done_buf_config(pre->curr_ch, false);
|
||||
|
||||
pre->flg_int_done = 0;
|
||||
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
ppre = get_pre_stru(pre->curr_ch);
|
||||
#if 0
|
||||
if (ppre->field_count_for_cont == 1) {
|
||||
usleep_range(2000, 2001);
|
||||
pr_info("delay 1ms\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = eDI_WAIT_INT_HAVE_INT;
|
||||
|
||||
} else {
|
||||
/*check if timeout:*/
|
||||
if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pre->tout)) {
|
||||
di_pre_wait_irq_set(false);
|
||||
/*return K_DO_R_FINISH;*/
|
||||
ret = eDI_WAIT_INT_TIME_OUT;
|
||||
}
|
||||
}
|
||||
/*debug:*/
|
||||
if (dbg_first_cnt_pre)
|
||||
dbg_first_frame("ch[%d],w_int[%d]\n", pre->curr_ch, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_wait_int(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpre_mtotal_timeout_contr(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
/*move from di_pre_trigger_work*/
|
||||
if (dimp_get(eDI_MP_di_dbg_mask) & 4)
|
||||
dim_dump_mif_size_state(pre->pres, pre->psts);
|
||||
|
||||
dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en));
|
||||
if (di_get_dts_nrds_en())
|
||||
dim_nr_ds_hw_ctrl(false);
|
||||
pre->pres->pre_de_irq_timeout_count++;
|
||||
|
||||
pre->pres->pre_de_busy = 0;
|
||||
pre->pres->pre_de_clear_flag = 2;
|
||||
if ((dimp_get(eDI_MP_di_dbg_mask) & 0x2)) {
|
||||
pr_info("DI:ch[%d]*****wait %d timeout 0x%x(%d ms)*****\n",
|
||||
pre->curr_ch,
|
||||
pre->pres->field_count_for_cont,
|
||||
Rd(DI_INTR_CTRL),
|
||||
(unsigned int)(cur_to_msecs() -
|
||||
pre->pres->irq_time[1]));
|
||||
}
|
||||
/*******************************/
|
||||
dim_pre_de_done_buf_config(pre->curr_ch, true);
|
||||
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
/*******************************/
|
||||
/*dpre_recyc(pre->curr_ch);*/
|
||||
}
|
||||
|
||||
unsigned int dpre_mtotal_timeout(void *data)
|
||||
{
|
||||
ulong flags = 0;
|
||||
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dpre_mtotal_timeout_contr();
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
|
||||
return K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
|
||||
const struct do_table_ops_s pr_mode_total[] = {
|
||||
/*fix*/
|
||||
[K_DO_TABLE_ID_PAUSE] = {
|
||||
.id = K_DO_TABLE_ID_PAUSE,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pause",
|
||||
},
|
||||
[K_DO_TABLE_ID_STOP] = {
|
||||
.id = K_DO_TABLE_ID_STOP,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "stop",
|
||||
},
|
||||
/******************/
|
||||
[K_DO_TABLE_ID_START] = { /*eDI_PRE_MT_CHECK*/
|
||||
.id = K_DO_TABLE_ID_START,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_check,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MT_SET] = {
|
||||
.id = eDI_PRE_MT_SET,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "set",
|
||||
},
|
||||
[eDI_PRE_MT_WAIT_INT] = {
|
||||
.id = eDI_PRE_MT_WAIT_INT,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_wait_int,
|
||||
.do_stop_op = NULL,
|
||||
.name = "wait_int",
|
||||
},
|
||||
[eDI_PRE_MT_TIME_OUT] = {
|
||||
.id = eDI_PRE_MT_TIME_OUT,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = dpre_mtotal_timeout,
|
||||
.do_stop_op = NULL,
|
||||
.name = "timeout",
|
||||
},
|
||||
};
|
||||
|
||||
/****************************
|
||||
*
|
||||
* mode for p
|
||||
*
|
||||
****************************/
|
||||
enum eDI_PRE_MP {
|
||||
eDI_PRE_MP_CHECK = K_DO_TABLE_ID_START,
|
||||
eDI_PRE_MP_SET,
|
||||
eDI_PRE_MP_WAIT_INT,
|
||||
eDI_PRE_MP_TIME_OUT,
|
||||
eDI_PRE_MP_CHECK2,
|
||||
eDI_PRE_MP_SET2,
|
||||
eDI_PRE_MP_WAIT_INT2,
|
||||
eDI_PRE_MP_TIME_OUT2,
|
||||
};
|
||||
|
||||
unsigned int dpre_mp_check(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if ((pre_run_flag == DI_RUN_FLAG_RUN) ||
|
||||
(pre_run_flag == DI_RUN_FLAG_STEP)) {
|
||||
if (pre_run_flag == DI_RUN_FLAG_STEP)
|
||||
pre_run_flag = DI_RUN_FLAG_STEP_DONE;
|
||||
/*dim_print("%s:\n", __func__);*/
|
||||
if (dim_pre_de_buf_config(pre->curr_ch)) {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
/*pre_p_asi_set_next(pre->curr_ch);*/
|
||||
ret = K_DO_R_FINISH;
|
||||
} else {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
dim_dbg_pre_cnt(pre->curr_ch, "x");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_check2(void *data)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
if (dim_pre_de_buf_config(pre->curr_ch)) {
|
||||
/*pre->flg_wait_int = false;*/
|
||||
ret = K_DO_R_FINISH;
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
PR_ERR("%s:not second?ch[%d]\n", __func__, pre->curr_ch);
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_wait_int(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(eDI_PRE_MP_CHECK2);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_wait_int2(void *data)
|
||||
{
|
||||
enum eDI_WAIT_INT wret;
|
||||
unsigned int ret = K_DO_R_NOT_FINISH;
|
||||
|
||||
wret = di_pre_wait_int(NULL);
|
||||
switch (wret) {
|
||||
case eDI_WAIT_INT_NEED_WAIT:
|
||||
ret = K_DO_R_NOT_FINISH;
|
||||
break;
|
||||
case eDI_WAIT_INT_HAVE_INT:
|
||||
ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
break;
|
||||
case eDI_WAIT_INT_TIME_OUT:
|
||||
ret = K_DO_R_FINISH;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_timeout(void *data)
|
||||
{
|
||||
dpre_mtotal_timeout_contr();
|
||||
|
||||
return K_DO_R_FINISH;
|
||||
}
|
||||
|
||||
unsigned int dpre_mp_timeout2(void *data)
|
||||
{
|
||||
dpre_mtotal_timeout_contr();
|
||||
|
||||
return K_DO_R_JUMP(K_DO_TABLE_ID_STOP);
|
||||
}
|
||||
|
||||
const struct do_table_ops_s pre_mode_proc[] = {
|
||||
/*fix*/
|
||||
[K_DO_TABLE_ID_PAUSE] = {
|
||||
.id = K_DO_TABLE_ID_PAUSE,
|
||||
.mark = 0,
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pause",
|
||||
},
|
||||
[K_DO_TABLE_ID_STOP] = {
|
||||
.id = K_DO_TABLE_ID_STOP,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL,
|
||||
.do_op = NULL,
|
||||
.do_stop_op = NULL,
|
||||
.name = "stop",
|
||||
},
|
||||
/******************/
|
||||
[K_DO_TABLE_ID_START] = { /*eDI_PRE_MP_CHECK*/
|
||||
.id = K_DO_TABLE_ID_START,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL,
|
||||
.do_op = dpre_mp_check,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MP_SET] = {
|
||||
.id = eDI_PRE_MP_SET,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pset",
|
||||
},
|
||||
[eDI_PRE_MP_WAIT_INT] = {
|
||||
.id = eDI_PRE_MP_WAIT_INT,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_wait_int,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pwait_int",
|
||||
},
|
||||
[eDI_PRE_MP_TIME_OUT] = {
|
||||
.id = eDI_PRE_MP_TIME_OUT,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_timeout,
|
||||
.do_stop_op = NULL,
|
||||
.name = "ptimeout",
|
||||
},
|
||||
/******/
|
||||
[eDI_PRE_MP_CHECK2] = { /*eDI_PRE_MP_CHECK2*/
|
||||
.id = eDI_PRE_MP_CHECK2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_check2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "start-check",
|
||||
},
|
||||
[eDI_PRE_MP_SET2] = {
|
||||
.id = eDI_PRE_MP_SET2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mtotal_set,
|
||||
.do_stop_op = NULL,
|
||||
.name = "psetp2",
|
||||
},
|
||||
[eDI_PRE_MP_WAIT_INT2] = {
|
||||
.id = eDI_PRE_MP_WAIT_INT2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_wait_int2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "pwait_int2",
|
||||
},
|
||||
[eDI_PRE_MP_TIME_OUT2] = {
|
||||
.id = eDI_PRE_MP_TIME_OUT2,
|
||||
.mark = 0, /*stop / pause*/
|
||||
.con = NULL, /*condition*/
|
||||
.do_op = dpre_mp_timeout2,
|
||||
.do_stop_op = NULL,
|
||||
.name = "ptimeout2",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
void pre_mode_setting(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
|
||||
if (pre->pre_st != eDI_PRE_ST4_DO_TABLE)
|
||||
return;
|
||||
|
||||
do_table_working(&pre->sdt_mode);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
enum eDI_WORK_MODE pre_cfg_count_mode(unsigned int ch, struct vframe_s *vframe)
|
||||
{
|
||||
enum eDI_WORK_MODE pmode;
|
||||
|
||||
if (is_bypass2(vframe, ch)) {
|
||||
pmode = eDI_WORK_MODE_bypass_all;
|
||||
return pmode;
|
||||
}
|
||||
|
||||
if (COM_ME(vframe->type, VIDTYPE_INTERLACE)) {
|
||||
/*interlace:*/
|
||||
pmode = eDI_WORK_MODE_i;
|
||||
return pmode;
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_prog_proc_config) & 0x10)
|
||||
pmode = eDI_WORK_MODE_p_as_p;
|
||||
else if (is_from_vdin(vframe))
|
||||
pmode = eDI_WORK_MODE_p_use_ibuf;
|
||||
else
|
||||
pmode = eDI_WORK_MODE_p_as_i;
|
||||
|
||||
return pmode;
|
||||
}
|
||||
|
||||
unsigned int dpre_check_mode(unsigned int ch)
|
||||
{
|
||||
struct vframe_s *vframe;
|
||||
unsigned int mode;
|
||||
|
||||
vframe = pw_vf_peek(ch);
|
||||
|
||||
if (!vframe)
|
||||
return eDI_WORK_MODE_NONE;
|
||||
mode = pre_cfg_count_mode(ch, vframe);/*eDI_WORK_MODE_all;*/
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
bool dpre_step4_idle(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
unsigned int ch;
|
||||
|
||||
ch = pre->curr_ch;
|
||||
if (!pw_try_sw_ch_next_pre(ch))
|
||||
return false;
|
||||
|
||||
if (pre->idle_cnt >= DI_CHANNEL_NUB) {
|
||||
pre->idle_cnt = 0;
|
||||
return false;
|
||||
}
|
||||
pre->pres = get_pre_stru(pre->curr_ch);
|
||||
pre->psts = get_post_stru(pre->curr_ch);
|
||||
|
||||
/*state*/
|
||||
pre->pre_st++;/*tmp*/
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpre_step4_check(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
unsigned int mode;
|
||||
|
||||
/*get vframe and select mode
|
||||
* now: fix use total table
|
||||
*/
|
||||
|
||||
mode = dpre_check_mode(pre->curr_ch);
|
||||
|
||||
if (mode == eDI_WORK_MODE_NONE) {
|
||||
pre->pre_st--;
|
||||
pre->idle_cnt++;
|
||||
return true;
|
||||
}
|
||||
pre->idle_cnt = 0;
|
||||
if (mode == eDI_WORK_MODE_p_as_i) {
|
||||
do_table_init(&pre->sdt_mode,
|
||||
&pre_mode_proc[0],
|
||||
ARRAY_SIZE(pre_mode_proc));
|
||||
|
||||
} else {
|
||||
do_table_init(&pre->sdt_mode,
|
||||
&pr_mode_total[0],
|
||||
ARRAY_SIZE(pr_mode_total));
|
||||
}
|
||||
do_talbe_cmd(&pre->sdt_mode, eDO_TABLE_CMD_START);
|
||||
|
||||
/*state*/
|
||||
pre->pre_st++;
|
||||
reflesh = true;
|
||||
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
bool dpre_step4_do_table(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
bool reflesh = false;
|
||||
|
||||
if (do_table_is_crr(&pre->sdt_mode, K_DO_TABLE_ID_STOP)) {
|
||||
pre->pre_st = eDI_PRE_ST4_IDLE;
|
||||
reflesh = true;
|
||||
}
|
||||
return reflesh;
|
||||
}
|
||||
|
||||
const struct di_func_tab_s di_pre_func_tab4[] = {
|
||||
{eDI_PRE_ST4_EXIT, NULL},
|
||||
{eDI_PRE_ST4_IDLE, dpre_step4_idle},
|
||||
{eDI_PRE_ST4_CHECK, dpre_step4_check},
|
||||
{eDI_PRE_ST4_DO_TABLE, dpre_step4_do_table},
|
||||
};
|
||||
|
||||
const char * const dpre_state_name4[] = {
|
||||
"EXIT",
|
||||
"IDLE", /*swith to next channel?*/
|
||||
"CHECK",
|
||||
"DO_TABLE",
|
||||
};
|
||||
|
||||
const char *dpre_state4_name_get(enum eDI_PRE_ST4 state)
|
||||
{
|
||||
if (state > eDI_PRE_ST4_DO_TABLE)
|
||||
return "nothing";
|
||||
|
||||
return dpre_state_name4[state];
|
||||
}
|
||||
|
||||
bool dpre_process_step4(void)
|
||||
{
|
||||
struct di_hpre_s *pre = get_hw_pre();
|
||||
enum eDI_PRE_ST4 pre_st = pre->pre_st;
|
||||
ulong flags = 0;
|
||||
|
||||
if (pre_st > eDI_PRE_ST4_EXIT) {
|
||||
spin_lock_irqsave(&plist_lock, flags);
|
||||
dim_recycle_post_back(pre->curr_ch);
|
||||
dpre_recyc(pre->curr_ch);
|
||||
dpre_vdoing(pre->curr_ch);
|
||||
spin_unlock_irqrestore(&plist_lock, flags);
|
||||
}
|
||||
if ((pre_st <= eDI_PRE_ST4_DO_TABLE) &&
|
||||
di_pre_func_tab4[pre_st].func) {
|
||||
return di_pre_func_tab4[pre_st].func();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
38
drivers/amlogic/media/di_multi/di_pre.h
Normal file
38
drivers/amlogic/media/di_multi/di_pre.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_pre.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_PRE_H__
|
||||
#define __DI_PRE_H__
|
||||
|
||||
void dpre_process(void);
|
||||
|
||||
void dpre_init(void);
|
||||
|
||||
const char *dpre_state_name_get(enum eDI_PRE_ST state);
|
||||
void dpre_dbg_f_trig(unsigned int cmd);
|
||||
void pre_vinfo_set(unsigned int ch,
|
||||
struct vframe_s *ori_vframe);
|
||||
unsigned int is_vinfo_change(unsigned int ch);
|
||||
bool dpre_can_exit(unsigned int ch);
|
||||
bool is_bypass_i_p(void);
|
||||
bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm);
|
||||
|
||||
void pre_mode_setting(void);
|
||||
bool dpre_process_step4(void);
|
||||
const char *dpre_state4_name_get(enum eDI_PRE_ST4 state);
|
||||
|
||||
#endif /*__DI_PRE_H__*/
|
||||
995
drivers/amlogic/media/di_multi/di_que.c
Normal file
995
drivers/amlogic/media/di_multi/di_que.c
Normal file
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_que.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include "deinterlace.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_que.h"
|
||||
#include "di_vframe.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
|
||||
const char * const di_name_new_que[QUE_NUB] = {
|
||||
"QUE_IN_FREE", /*0*/
|
||||
"QUE_PRE_READY", /*1*/
|
||||
"QUE_POST_FREE", /*2*/
|
||||
"QUE_POST_READY", /*3*/
|
||||
"QUE_POST_BACK", /*4*/
|
||||
"QUE_DBG",
|
||||
/* "QUE_NUB",*/
|
||||
|
||||
};
|
||||
|
||||
#define que_dbg dim_print
|
||||
|
||||
static void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return;
|
||||
#endif
|
||||
kfifo_reset(&pch->fifo[qtype]);
|
||||
}
|
||||
|
||||
bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype, unsigned int buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_in(&pch->fifo[qtype], &buf_index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
#if 0
|
||||
|
||||
/*below for debug: save in que*/
|
||||
if (qtype <= QUE_POST_RECYC) {
|
||||
if (buf_index >= MAX_POST_BUF_NUM) {
|
||||
pr_err("%s:err:overflow?[%d]\n", __func__, buf_index);
|
||||
} else {
|
||||
ppw = &pch->lpost_buf[buf_index];
|
||||
ppw->in_qtype = qtype;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_out(&pch->fifo[qtype], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*buf_index = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pw_queue_peek(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (kfifo_out_peek(&pch->fifo[qtype], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*buf_index = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_move(unsigned int ch, enum QUE_TYPE qtypef, enum QUE_TYPE qtypet,
|
||||
unsigned int *oindex)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int index;
|
||||
|
||||
/*struct di_post_buf_s *ppw;*/ /*debug only*/
|
||||
|
||||
#if 0
|
||||
if (qtypef >= QUE_NUB || qtypet >= QUE_NUB)
|
||||
return false;
|
||||
#endif
|
||||
if (kfifo_out(&pch->fifo[qtypef], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("qtypef[%d] is empty\n", qtypef);
|
||||
return false;
|
||||
}
|
||||
if (kfifo_in(&pch->fifo[qtypet], &index, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("qtypet[%d] is full\n", qtypet);
|
||||
return false;
|
||||
}
|
||||
|
||||
*oindex = index;
|
||||
#if 0
|
||||
if (qtypet <= QUE_POST_RECYC) {
|
||||
/*below for debug: save in que*/
|
||||
if (index >= MAX_POST_BUF_NUM) {
|
||||
pr_err("%s:err:overflow?[%d]\n", __func__, index);
|
||||
} else {
|
||||
ppw = &pch->lpost_buf[index];
|
||||
ppw->in_qtype = qtypet;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
if (kfifo_is_empty(&pch->fifo[qtype]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
unsigned int length;
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return -1;
|
||||
#endif
|
||||
length = kfifo_len(&pch->fifo[qtype]);
|
||||
length = length / sizeof(unsigned int);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
/*outbuf : array size MAX_FIFO_SIZE*/
|
||||
/***************************************/
|
||||
bool di_que_list(unsigned int ch, enum QUE_TYPE qtype, unsigned int *outbuf,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
/* unsigned int tmp[MAX_FIFO_SIZE + 1];*/
|
||||
int i;
|
||||
unsigned int index;
|
||||
bool ret = false;
|
||||
|
||||
/*que_dbg("%s:begin\n", __func__);*/
|
||||
for (i = 0; i < MAX_FIFO_SIZE; i++)
|
||||
outbuf[i] = 0xff;
|
||||
|
||||
if (kfifo_is_empty(&pch->fifo[qtype])) {
|
||||
que_dbg("\t%d:empty\n", qtype);
|
||||
*rsize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
memcpy(&pch->fifo[QUE_DBG], &pch->fifo[qtype],
|
||||
sizeof(pch->fifo[qtype]));
|
||||
|
||||
#if 0
|
||||
if (kfifo_is_empty(&pbm->fifo[QUE_DBG]))
|
||||
pr_err("%s:err, kfifo can not copy?\n", __func__);
|
||||
|
||||
#endif
|
||||
i = 0;
|
||||
*rsize = 0;
|
||||
|
||||
while (kfifo_out(&pch->fifo[QUE_DBG], &index, sizeof(unsigned int))
|
||||
== sizeof(unsigned int)) {
|
||||
outbuf[i] = index;
|
||||
/*pr_info("%d->%d\n",i,index);*/
|
||||
i++;
|
||||
}
|
||||
*rsize = di_que_list_count(ch, qtype);
|
||||
#if 0 /*debug only*/
|
||||
que_dbg("%s: size[%d]\n", di_name_new_que[qtype], *rsize);
|
||||
for (i = 0; i < *rsize; i++)
|
||||
que_dbg("%d,", outbuf[i]);
|
||||
|
||||
que_dbg("\n");
|
||||
#endif
|
||||
/*que_dbg("finish\n");*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
#if 0
|
||||
if (qtype >= QUE_NUB)
|
||||
return -1;
|
||||
#endif
|
||||
return kfifo_is_empty(&pch->fifo[qtype]);
|
||||
}
|
||||
|
||||
void di_que_init(unsigned int ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < QUE_NUB; i++)
|
||||
pw_queue_clear(ch, i);
|
||||
}
|
||||
|
||||
bool di_que_alloc(unsigned int ch)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
bool flg_err;
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
|
||||
/*kfifo----------------------------*/
|
||||
flg_err = 0;
|
||||
for (i = 0; i < QUE_NUB; i++) {
|
||||
ret = kfifo_alloc(&pch->fifo[i],
|
||||
sizeof(unsigned int) * MAX_FIFO_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
flg_err = 1;
|
||||
PR_ERR("%s:%d:can't get kfifo\n", __func__, i);
|
||||
break;
|
||||
}
|
||||
pch->flg_fifo[i] = 1;
|
||||
}
|
||||
#if 0
|
||||
/*canvas-----------------------------*/
|
||||
canvas_alloc();
|
||||
#endif
|
||||
/* pdp_clear();*/
|
||||
|
||||
if (!flg_err) {
|
||||
/*pbm->flg_fifo = 1;*/
|
||||
pr_info("%s:ok\n", __func__);
|
||||
ret = true;
|
||||
} else {
|
||||
di_que_release(ch);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void di_que_release(unsigned int ch)
|
||||
{
|
||||
struct di_ch_s *pch = get_chdata(ch);
|
||||
int i;
|
||||
|
||||
/* canvas_release();*/
|
||||
for (i = 0; i < QUE_NUB; i++) {
|
||||
if (pch->flg_fifo[i]) {
|
||||
kfifo_free(&pch->fifo[i]);
|
||||
pch->flg_fifo[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("%s:ok\n", __func__);
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*get di_buf from index that same in que
|
||||
* (di_buf->type << 8) | (di_buf->index)
|
||||
********************************************/
|
||||
struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex)
|
||||
{
|
||||
union uDI_QBUF_INDEX index;
|
||||
struct di_buf_s *di_buf;
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(ch);
|
||||
|
||||
index.d32 = qindex;
|
||||
di_buf = &pbuf_pool[index.b.type - 1].di_buf_ptr[index.b.index];
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/*get di_buf from index that same in que*/
|
||||
/*(di_buf->type << 8) | (di_buf->index)*/
|
||||
/********************************************/
|
||||
static unsigned int pw_buf_2_qindex(unsigned int ch, struct di_buf_s *pdi_buf)
|
||||
{
|
||||
union uDI_QBUF_INDEX index;
|
||||
|
||||
index.b.index = pdi_buf->index;
|
||||
index.b.type = pdi_buf->type;
|
||||
return index.d32;
|
||||
}
|
||||
|
||||
/*di_buf is out*/
|
||||
struct di_buf_s *di_que_out_to_di_buf(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
unsigned int q_index;
|
||||
struct di_buf_s *pdi_buf = NULL;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return pdi_buf;
|
||||
|
||||
pdi_buf = pw_qindex_2_buf(ch, q_index);
|
||||
if (!pdi_buf) {
|
||||
PR_ERR("di:err:%s:buf is null[%d]\n", __func__, q_index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pw_queue_out(ch, qtype, &q_index);
|
||||
pdi_buf->queue_index = -1;
|
||||
|
||||
return pdi_buf;
|
||||
}
|
||||
|
||||
/*di_buf is input*/
|
||||
bool di_que_out(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
unsigned int q_index2;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return false;
|
||||
|
||||
q_index2 = pw_buf_2_qindex(ch, di_buf);
|
||||
if (q_index2 != q_index) {
|
||||
PR_ERR("di:%s:not map[%d,%d]\n", __func__, q_index2, q_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
pw_queue_out(ch, qtype, &q_index);
|
||||
di_buf->queue_index = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool di_que_in(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("di:%s:err:di_buf is NULL,ch[%d],qtype[%d]\n",
|
||||
__func__, ch, qtype);
|
||||
return false;
|
||||
}
|
||||
if (di_buf->queue_index != -1) {
|
||||
PR_ERR("di:%s:buf in some que,ch[%d],qt[%d],qi[%d],bi[%d]\n",
|
||||
__func__,
|
||||
ch, qtype, di_buf->queue_index, di_buf->index);
|
||||
return false;
|
||||
}
|
||||
|
||||
q_index = pw_buf_2_qindex(ch, di_buf);
|
||||
|
||||
if (!pw_queue_in(ch, qtype, q_index)) {
|
||||
PR_ERR("di:%s:err:can't que in,ch[%d],qtype[%d],q_index[%d]\n",
|
||||
__func__,
|
||||
ch, qtype, q_index);
|
||||
return false;
|
||||
}
|
||||
di_buf->queue_index = qtype + QUEUE_NUM;
|
||||
|
||||
if (qtype == QUE_PRE_READY)
|
||||
dim_print("di:pre_ready in %d\n", di_buf->index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf)
|
||||
{
|
||||
unsigned int q_index;
|
||||
unsigned int arr[MAX_FIFO_SIZE + 1];
|
||||
unsigned int asize = 0;
|
||||
bool ret = false;
|
||||
unsigned int i;
|
||||
|
||||
if (!di_buf)
|
||||
return false;
|
||||
|
||||
q_index = pw_buf_2_qindex(ch, di_buf);
|
||||
|
||||
di_que_list(ch, qtype, &arr[0], &asize);
|
||||
|
||||
if (asize == 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < asize; i++) {
|
||||
if (arr[i] == q_index) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*same as get_di_buf_head*/
|
||||
struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype)
|
||||
{
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
unsigned int q_index;
|
||||
|
||||
if (!pw_queue_peek(ch, qtype, &q_index))
|
||||
return di_buf;
|
||||
di_buf = pw_qindex_2_buf(ch, q_index);
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype)
|
||||
{
|
||||
if (!F_IN(q_type, QUEUE_NEW_THD_MIN, QUEUE_NEW_THD_MAX))
|
||||
return false;
|
||||
*nqtype = (enum QUE_TYPE)(q_type - QUEUE_NUM);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/**********************************************************/
|
||||
/*ary add this function for reg ini value, no need wait peek*/
|
||||
void queue_init2(unsigned int channel)
|
||||
{
|
||||
int i, j;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
|
||||
for (i = 0; i < QUEUE_NUM; i++) {
|
||||
queue_t *q = &pqueue[i];
|
||||
|
||||
for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++)
|
||||
q->pool[j] = 0;
|
||||
|
||||
q->in_idx = 0;
|
||||
q->out_idx = 0;
|
||||
q->num = 0;
|
||||
q->type = 0;
|
||||
if ((i == QUEUE_RECYCLE) ||
|
||||
(i == QUEUE_DISPLAY) ||
|
||||
(i == QUEUE_TMP) ||
|
||||
(i == QUEUE_POST_DOING))
|
||||
q->type = 1;
|
||||
|
||||
#if 0
|
||||
if ((i == QUEUE_LOCAL_FREE) && dim_get_use_2_int_buf())
|
||||
q->type = 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void queue_init(unsigned int channel, int local_buffer_num)
|
||||
{
|
||||
int i, j;
|
||||
struct di_buf_s *pbuf_local = get_buf_local(channel);
|
||||
struct di_buf_s *pbuf_in = get_buf_in(channel);
|
||||
struct di_buf_s *pbuf_post = get_buf_post(channel);
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel);
|
||||
|
||||
for (i = 0; i < QUEUE_NUM; i++) {
|
||||
queue_t *q = &pqueue[i];
|
||||
|
||||
for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++)
|
||||
q->pool[j] = 0;
|
||||
|
||||
q->in_idx = 0;
|
||||
q->out_idx = 0;
|
||||
q->num = 0;
|
||||
q->type = 0;
|
||||
if ((i == QUEUE_RECYCLE) ||
|
||||
(i == QUEUE_DISPLAY) ||
|
||||
(i == QUEUE_TMP)
|
||||
/*||(i == QUEUE_POST_DOING)*/
|
||||
)
|
||||
q->type = 1;
|
||||
|
||||
if ((i == QUEUE_LOCAL_FREE) &&
|
||||
dimp_get(eDI_MP_use_2_interlace_buff))
|
||||
q->type = 2;
|
||||
}
|
||||
if (local_buffer_num > 0) {
|
||||
pbuf_pool[VFRAME_TYPE_IN - 1].di_buf_ptr = &pbuf_in[0];
|
||||
pbuf_pool[VFRAME_TYPE_IN - 1].size = MAX_IN_BUF_NUM;
|
||||
|
||||
pbuf_pool[VFRAME_TYPE_LOCAL - 1].di_buf_ptr = &pbuf_local[0];
|
||||
pbuf_pool[VFRAME_TYPE_LOCAL - 1].size = local_buffer_num;
|
||||
|
||||
pbuf_pool[VFRAME_TYPE_POST - 1].di_buf_ptr = &pbuf_post[0];
|
||||
pbuf_pool[VFRAME_TYPE_POST - 1].size = MAX_POST_BUF_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
struct di_buf_s *get_di_buf_head(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
queue_t *q = &pqueue[queue_idx];
|
||||
int idx;
|
||||
unsigned int pool_idx, di_buf_idx;
|
||||
struct di_buf_s *di_buf = NULL;
|
||||
struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d>\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx);
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype))
|
||||
return di_que_peek(channel, nqtype);
|
||||
|
||||
/* **************** */
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
idx = q->out_idx;
|
||||
} else {
|
||||
for (idx = 0; idx < MAX_QUEUE_POOL_SIZE; idx++)
|
||||
if (q->pool[idx] != 0)
|
||||
break;
|
||||
}
|
||||
if (idx < MAX_QUEUE_POOL_SIZE) {
|
||||
pool_idx = ((q->pool[idx] >> 8) & 0xff) - 1;
|
||||
di_buf_idx = q->pool[idx] & 0xff;
|
||||
|
||||
if (pool_idx < VFRAME_TYPE_NUM) {
|
||||
if (di_buf_idx < pbuf_pool[pool_idx].size)
|
||||
di_buf = &pbuf_pool[pool_idx].di_buf_ptr[di_buf_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((di_buf) && ((((pool_idx + 1) << 8) | di_buf_idx) !=
|
||||
((di_buf->type << 8) | (di_buf->index)))) {
|
||||
pr_dbg("%s: Error (%x,%x)\n", __func__,
|
||||
(((pool_idx + 1) << 8) | di_buf_idx),
|
||||
((di_buf->type << 8) | (di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(2);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
di_buf = NULL;
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) {
|
||||
if (di_buf)
|
||||
dim_print("%s: 0x%p(%d,%d)\n", __func__, di_buf,
|
||||
pool_idx, di_buf_idx);
|
||||
else
|
||||
dim_print("%s: 0x%p\n", __func__, di_buf);
|
||||
}
|
||||
|
||||
return di_buf;
|
||||
}
|
||||
|
||||
/*ary: note:*/
|
||||
/*a. di_buf->queue_index = -1*/
|
||||
/*b. */
|
||||
void queue_out(unsigned int channel, struct di_buf_s *di_buf)
|
||||
{
|
||||
int i;
|
||||
queue_t *q;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0)
|
||||
dim_vcry_set_log_reason(3);
|
||||
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(di_buf->queue_index, &nqtype)) {
|
||||
di_que_out(channel, nqtype, di_buf); /*?*/
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) {
|
||||
q = &pqueue[di_buf->queue_index];
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
if (q->pool[q->out_idx] ==
|
||||
((di_buf->type << 8) | (di_buf->index))) {
|
||||
q->num--;
|
||||
q->pool[q->out_idx] = 0;
|
||||
q->out_idx++;
|
||||
if (q->out_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->out_idx = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR(
|
||||
"%s: Error (%d, %x,%x)\n",
|
||||
__func__,
|
||||
di_buf->queue_index,
|
||||
q->pool[q->out_idx],
|
||||
((di_buf->type << 8) |
|
||||
(di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(4);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 1) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == pool_val) {
|
||||
q->num--;
|
||||
q->pool[i] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == pool_val)) {
|
||||
q->num--;
|
||||
q->pool[di_buf->index] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PR_ERR("%s: Error, queue_index %d is not right\n",
|
||||
__func__, di_buf->queue_index);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(6);
|
||||
dim_vcry_set_log_q_idx(0);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf)
|
||||
{
|
||||
int i;
|
||||
queue_t *q;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0)
|
||||
dim_vcry_set_log_reason(3);
|
||||
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(di_buf->queue_index, &nqtype)) {
|
||||
di_que_out(channel, nqtype, di_buf); /*?*/
|
||||
pr_info("dbg1:nqtype=%d\n", nqtype);
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) {
|
||||
q = &pqueue[di_buf->queue_index];
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__,
|
||||
di_buf->queue_index, q->num, q->in_idx,
|
||||
q->out_idx, di_buf);
|
||||
|
||||
if (q->num > 0) {
|
||||
if (q->type == 0) {
|
||||
pr_info("dbg3\n");
|
||||
if (q->pool[q->out_idx] ==
|
||||
((di_buf->type << 8) | (di_buf->index))) {
|
||||
q->num--;
|
||||
q->pool[q->out_idx] = 0;
|
||||
q->out_idx++;
|
||||
if (q->out_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->out_idx = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR(
|
||||
"%s: Error (%d, %x,%x)\n",
|
||||
__func__,
|
||||
di_buf->queue_index,
|
||||
q->pool[q->out_idx],
|
||||
((di_buf->type << 8) |
|
||||
(di_buf->index)));
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(4);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 1) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == pool_val) {
|
||||
q->num--;
|
||||
q->pool[i] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pr_info("dbg2:i=%d,qindex=%d\n", i,
|
||||
di_buf->queue_index);
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(5);
|
||||
dim_vcry_set_log_q_idx(di_buf->queue_index);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
int pool_val =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
|
||||
pr_info("dbg4\n");
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == pool_val)) {
|
||||
q->num--;
|
||||
q->pool[di_buf->index] = 0;
|
||||
di_buf->queue_index = -1;
|
||||
} else {
|
||||
PR_ERR("%s: Error\n", __func__);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set(5,
|
||||
di_buf->queue_index,
|
||||
di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PR_ERR("%s: Error, queue_index %d is not right\n",
|
||||
__func__, di_buf->queue_index);
|
||||
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(6);
|
||||
dim_vcry_set_log_q_idx(0);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
/* set di_buf->queue_index*/
|
||||
/***************************************/
|
||||
void queue_in(unsigned int channel, struct di_buf_s *di_buf, int queue_idx)
|
||||
{
|
||||
queue_t *q = NULL;
|
||||
struct queue_s *pqueue = get_queue(channel);
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
if (!di_buf) {
|
||||
PR_ERR("%s:Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(7);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
di_que_in(channel, nqtype, di_buf);
|
||||
return;
|
||||
}
|
||||
/* **************** */
|
||||
if (di_buf->queue_index != -1) {
|
||||
PR_ERR("%s:%s[%d] queue_index(%d) is not -1, to que[%d]\n",
|
||||
__func__, dim_get_vfm_type_name(di_buf->type),
|
||||
di_buf->index, di_buf->queue_index, queue_idx);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(8);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
dim_vcry_set_log_di_buf(di_buf);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
return;
|
||||
}
|
||||
q = &pqueue[queue_idx];
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, queue_idx,
|
||||
q->num, q->in_idx, q->out_idx, di_buf);
|
||||
|
||||
if (q->type == 0) {
|
||||
q->pool[q->in_idx] = (di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->in_idx++;
|
||||
if (q->in_idx >= MAX_QUEUE_POOL_SIZE)
|
||||
q->in_idx = 0;
|
||||
|
||||
q->num++;
|
||||
} else if (q->type == 1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) {
|
||||
if (q->pool[i] == 0) {
|
||||
q->pool[i] =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_QUEUE_POOL_SIZE) {
|
||||
pr_dbg("%s: Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(9);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
} else if (q->type == 2) {
|
||||
if ((di_buf->index < MAX_QUEUE_POOL_SIZE) &&
|
||||
(q->pool[di_buf->index] == 0)) {
|
||||
q->pool[di_buf->index] =
|
||||
(di_buf->type << 8) | (di_buf->index);
|
||||
di_buf->queue_index = queue_idx;
|
||||
q->num++;
|
||||
} else {
|
||||
pr_dbg("%s: Error\n", __func__);
|
||||
if (dim_vcry_get_flg() == 0) {
|
||||
dim_vcry_set_log_reason(9);
|
||||
dim_vcry_set_log_q_idx(queue_idx);
|
||||
}
|
||||
dim_vcry_flg_inc();
|
||||
}
|
||||
}
|
||||
|
||||
if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE)
|
||||
dim_print("%s done\n", __func__);
|
||||
}
|
||||
|
||||
int list_count(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
PR_ERR("%s:err: over flow\n", __func__);
|
||||
return di_que_list_count(channel, nqtype);
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
pqueue = get_queue(channel);
|
||||
return pqueue[queue_idx].num;
|
||||
}
|
||||
|
||||
bool queue_empty(unsigned int channel, int queue_idx)
|
||||
{
|
||||
struct queue_s *pqueue;
|
||||
bool ret;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype)) {
|
||||
PR_ERR("%s:err: over flow\n", __func__);
|
||||
return di_que_is_empty(channel, nqtype);
|
||||
}
|
||||
/* **************** */
|
||||
|
||||
pqueue = get_queue(channel);
|
||||
ret = (pqueue[queue_idx].num == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf, int queue_idx)
|
||||
{
|
||||
bool ret = 0;
|
||||
struct di_buf_s *p = NULL;
|
||||
int itmp;
|
||||
unsigned int overflow_cnt;
|
||||
enum QUE_TYPE nqtype;/*new que*/
|
||||
|
||||
/* ****new que***** */
|
||||
if (di_que_type_2_new(queue_idx, &nqtype))
|
||||
return di_que_is_in_que(channel, nqtype, di_buf);
|
||||
|
||||
/* **************** */
|
||||
|
||||
overflow_cnt = 0;
|
||||
if (!di_buf || (queue_idx < 0) || (queue_idx >= QUEUE_NUM)) {
|
||||
ret = 0;
|
||||
dim_print("%s: not in queue:%d!!!\n", __func__, queue_idx);
|
||||
return ret;
|
||||
}
|
||||
queue_for_each_entry(p, channel, queue_idx, list) {
|
||||
if (p == di_buf) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
if (overflow_cnt++ > MAX_QUEUE_POOL_SIZE) {
|
||||
ret = 0;
|
||||
dim_print("%s: overflow_cnt!!!\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
76
drivers/amlogic/media/di_multi/di_que.h
Normal file
76
drivers/amlogic/media/di_multi/di_que.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_que.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_QUE_H__
|
||||
#define __DI_QUE_H__
|
||||
|
||||
void queue_init(unsigned int channel, int local_buffer_num);
|
||||
void queue_out(unsigned int channel, struct di_buf_s *di_buf);
|
||||
void queue_in(unsigned int channel, struct di_buf_s *di_buf,
|
||||
int queue_idx);
|
||||
int list_count(unsigned int channel, int queue_idx);
|
||||
bool queue_empty(unsigned int channel, int queue_idx);
|
||||
bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf,
|
||||
int queue_idx);
|
||||
struct di_buf_s *get_di_buf_head(unsigned int channel,
|
||||
int queue_idx);
|
||||
|
||||
void queue_init2(unsigned int channel);
|
||||
|
||||
/*new buf:*/
|
||||
bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int buf_index);
|
||||
bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *buf_index);
|
||||
bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype);
|
||||
|
||||
/******************************************/
|
||||
/*new api*/
|
||||
/******************************************/
|
||||
union uDI_QBUF_INDEX {
|
||||
unsigned int d32;
|
||||
struct {
|
||||
unsigned int index:8, /*low*/
|
||||
type:8,
|
||||
reserved0:16;
|
||||
} b;
|
||||
};
|
||||
|
||||
void di_que_init(unsigned int ch);
|
||||
bool di_que_alloc(unsigned int ch);
|
||||
void di_que_release(unsigned int ch);
|
||||
|
||||
int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_out(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
|
||||
struct di_buf_s *di_que_out_to_di_buf(unsigned int ch,
|
||||
enum QUE_TYPE qtype);
|
||||
bool di_que_in(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
|
||||
struct di_buf_s *di_buf);
|
||||
struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype);
|
||||
int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype);
|
||||
bool di_que_list(unsigned int ch, enum QUE_TYPE qtype,
|
||||
unsigned int *outbuf, unsigned int *rsize);
|
||||
|
||||
struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex);
|
||||
|
||||
void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf);
|
||||
#endif /*__DI_QUE_H__*/
|
||||
249
drivers/amlogic/media/di_multi/di_reg_tab.c
Normal file
249
drivers/amlogic/media/di_multi/di_reg_tab.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_reg_tab.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/amlogic/iomap.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "register.h"
|
||||
|
||||
static const struct reg_t rtab_contr[] = {
|
||||
/*--------------------------*/
|
||||
{VD1_AFBCD0_MISC_CTRL, 20, 2, 0, "VD1_AFBCD0_MISC_CTRL",
|
||||
"vd1_go_field_sel",
|
||||
"0: gofile;1: post;2: pre"},
|
||||
{VD1_AFBCD0_MISC_CTRL, 9, 1, 0, "",
|
||||
"afbc0_mux_vpp_mad",
|
||||
"afbc0 to 0:vpp; 1:di"},
|
||||
{VD1_AFBCD0_MISC_CTRL, 8, 1, 0, "",
|
||||
"di_mif0_en",
|
||||
":mif to 0-vpp;1-di"},
|
||||
/*--------------------------*/
|
||||
{DI_POST_CTRL, 12, 1, 0, "DI_POST_CTRL",
|
||||
"di_post_viu_link",
|
||||
""},
|
||||
{DI_POST_CTRL, 8, 1, 0, "",
|
||||
"di_vpp_out_en",
|
||||
""},
|
||||
/*--------------------------*/
|
||||
{VIU_MISC_CTRL0, 20, 1, 0, "VIU_MISC_CTRL0",
|
||||
"?",
|
||||
"?"},
|
||||
{VIU_MISC_CTRL0, 18, 1, 0, "",
|
||||
"Vdin0_wr_out_ctrl",
|
||||
"0: nr_inp to vdin; 1: vdin wr dout"},
|
||||
{VIU_MISC_CTRL0, 17, 1, 0, "",
|
||||
"Afbc_inp_sel",
|
||||
"0: mif to INP; 1: afbc to INP"},
|
||||
{VIU_MISC_CTRL0, 16, 1, 0, "",
|
||||
"di_mif0_en",
|
||||
" vd1(afbc) to di post(if0) enable"},
|
||||
/*--------------------------*/
|
||||
{DI_IF1_GEN_REG, 0, 1, 0, "DI_IF1_GEN_REG",
|
||||
"enable",
|
||||
""},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF1_GEN_REG3, 8, 2, 0, "DI_IF1_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF2_GEN_REG3, 8, 2, 0, "DI_IF2_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_IF0_GEN_REG3, 8, 2, 0, "DI_IF0_GEN_REG3",
|
||||
"cntl_bits_mode",
|
||||
"0:8bit;1:10bit 422;2:10bit 444"},
|
||||
|
||||
/*--------------------------*/
|
||||
{DI_POST_GL_CTRL, 31, 1, 0, "DI_POST_GL_CTRL",
|
||||
"post count enable",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 30, 1, 0, "",
|
||||
"post count reset",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 16, 14, 0, "",
|
||||
"total line number for post count",
|
||||
""},
|
||||
{DI_POST_GL_CTRL, 0, 14, 0, "",
|
||||
"the line number of post frame reset",
|
||||
""},
|
||||
|
||||
{TABLE_FLG_END, 0, 0, 0, "end", "end", ""},
|
||||
|
||||
};
|
||||
|
||||
/**********************/
|
||||
/* debug register */
|
||||
/**********************/
|
||||
static unsigned int get_reg_bits(unsigned int val, unsigned int bstart,
|
||||
unsigned int bw)
|
||||
{
|
||||
return((val &
|
||||
(((1L << bw) - 1) << bstart)) >> (bstart));
|
||||
}
|
||||
|
||||
static void dbg_reg_tab(struct seq_file *s, const struct reg_t *pRegTab)
|
||||
{
|
||||
struct reg_t creg;
|
||||
int i;
|
||||
unsigned int l_add;
|
||||
unsigned int val32 = 1, val;
|
||||
char *bname;
|
||||
char *info;
|
||||
|
||||
i = 0;
|
||||
l_add = 0;
|
||||
creg = pRegTab[i];
|
||||
|
||||
do {
|
||||
if (creg.add != l_add) {
|
||||
val32 = Rd(creg.add); /*RD*/
|
||||
seq_printf(s, "add:0x%x = 0x%08x, %s\n",
|
||||
creg.add, val32, creg.name);
|
||||
l_add = creg.add;
|
||||
}
|
||||
val = get_reg_bits(val32, creg.bit, creg.wid); /*RD_B*/
|
||||
|
||||
if (creg.bname)
|
||||
bname = creg.bname;
|
||||
else
|
||||
bname = "";
|
||||
if (creg.info)
|
||||
info = creg.info;
|
||||
else
|
||||
info = "";
|
||||
|
||||
seq_printf(s, "\tbit[%d,%d]:\t0x%x[%d]:\t%s:\t%s\n",
|
||||
creg.bit, creg.wid, val, val, bname, info);
|
||||
|
||||
i++;
|
||||
creg = pRegTab[i];
|
||||
if (i > TABLE_LEN_MAX) {
|
||||
pr_info("warn: too long, stop\n");
|
||||
break;
|
||||
}
|
||||
} while (creg.add != TABLE_FLG_END);
|
||||
}
|
||||
|
||||
int reg_con_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
dbg_reg_tab(seq, &rtab_contr[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reg_t rtab_cue_int[] = {
|
||||
/*--------------------------*/
|
||||
{NR2_CUE_CON_DIF0, 0, 32, 0x1400, "NR2_CUE_CON_DIF0",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF1, 0, 32, 0x80064, "NR2_CUE_CON_DIF1",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF2, 0, 32, 0x80064, "NR2_CUE_CON_DIF2",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_CON_DIF3, 0, 32, 0x80a0a, "NR2_CUE_CON_DIF3",
|
||||
NULL,
|
||||
NULL},
|
||||
{NR2_CUE_PRG_DIF, 0, 32, 0x80a0a, "NR2_CUE_PRG_DIF",
|
||||
NULL,
|
||||
NULL},
|
||||
{TABLE_FLG_END, 0, 0, 0, "end", "end", ""},
|
||||
/*--------------------------*/
|
||||
};
|
||||
|
||||
/************************************************
|
||||
* register table
|
||||
************************************************/
|
||||
static bool di_g_rtab_cue(const struct reg_t **tab, unsigned int *tabsize)
|
||||
{
|
||||
*tab = &rtab_cue_int[0];
|
||||
*tabsize = ARRAY_SIZE(rtab_cue_int);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int dim_reg_read(unsigned int addr)
|
||||
{
|
||||
return aml_read_vcbus(addr);
|
||||
}
|
||||
|
||||
static const struct reg_acc di_pre_regset = {
|
||||
.wr = dim_DI_Wr,
|
||||
.rd = dim_reg_read,
|
||||
.bwr = dim_RDMA_WR_BITS,
|
||||
.brd = dim_RDMA_RD_BITS,
|
||||
};
|
||||
|
||||
static bool di_wr_tab(const struct reg_acc *ops,
|
||||
const struct reg_t *ptab, unsigned int tabsize)
|
||||
{
|
||||
int i;
|
||||
const struct reg_t *pl;
|
||||
|
||||
pl = ptab;
|
||||
|
||||
if (!ops ||
|
||||
!tabsize ||
|
||||
!ptab)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tabsize; i++) {
|
||||
if (pl->add == TABLE_FLG_END ||
|
||||
i > TABLE_LEN_MAX) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pl->wid == 32)
|
||||
ops->wr(pl->add, pl->df_val);
|
||||
else
|
||||
ops->bwr(pl->add, pl->df_val, pl->bit, pl->wid);
|
||||
|
||||
pl++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dim_wr_cue_int(void)
|
||||
{
|
||||
const struct reg_t *ptab;
|
||||
unsigned int tabsize;
|
||||
|
||||
di_g_rtab_cue(&ptab, &tabsize);
|
||||
di_wr_tab(&di_pre_regset,
|
||||
ptab,
|
||||
tabsize);
|
||||
PR_INF("%s:finish\n", __func__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int dim_reg_cue_int_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
dbg_reg_tab(seq, &rtab_cue_int[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
drivers/amlogic/media/di_multi/di_reg_tab.h
Normal file
26
drivers/amlogic/media/di_multi/di_reg_tab.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_reg_tab.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_REG_TABL_H__
|
||||
#define __DI_REG_TABL_H__
|
||||
|
||||
int reg_con_show(struct seq_file *seq, void *v);
|
||||
|
||||
bool dim_wr_cue_int(void);
|
||||
int dim_reg_cue_int_show(struct seq_file *seq, void *v);
|
||||
|
||||
#endif /*__DI_REG_TABL_H__*/
|
||||
754
drivers/amlogic/media/di_multi/di_sys.c
Normal file
754
drivers/amlogic/media/di_multi/di_sys.c
Normal file
@@ -0,0 +1,754 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_sys.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/cma.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
|
||||
/*dma_get_cma_size_int_byte*/
|
||||
#include <linux/amlogic/media/codec_mm/codec_mm.h>
|
||||
|
||||
#include "deinterlace_dbg.h"
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "di_data.h"
|
||||
#include "di_dbg.h"
|
||||
#include "di_vframe.h"
|
||||
#include "di_task.h"
|
||||
#include "di_prc.h"
|
||||
#include "di_sys.h"
|
||||
#include "di_api.h"
|
||||
|
||||
#include "register.h"
|
||||
#include "nr_downscale.h"
|
||||
|
||||
static di_dev_t *di_pdev;
|
||||
|
||||
struct di_dev_s *get_dim_de_devp(void)
|
||||
{
|
||||
return di_pdev;
|
||||
}
|
||||
|
||||
unsigned int di_get_dts_nrds_en(void)
|
||||
{
|
||||
return get_dim_de_devp()->nrds_enable;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* mem
|
||||
*******************************************/
|
||||
|
||||
/********************************************/
|
||||
static ssize_t
|
||||
show_config(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t show_tvp_region(struct device *dev,
|
||||
struct device_attribute *attr, char *buff)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
struct di_dev_s *de_devp = get_dim_de_devp();
|
||||
|
||||
len = sprintf(buff, "segment DI:%lx - %lx (size:0x%x)\n",
|
||||
de_devp->mem_start,
|
||||
de_devp->mem_start + de_devp->mem_size - 1,
|
||||
de_devp->mem_size);
|
||||
return len;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t
|
||||
show_log(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return dim_read_log(buf);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_frame_format(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int channel = get_current_channel(); /*debug only*/
|
||||
struct di_pre_stru_s *ppre = get_pre_stru(channel);
|
||||
|
||||
if (get_init_flag(channel))
|
||||
ret += sprintf(buf + ret, "%s\n",
|
||||
ppre->cur_prog_flag
|
||||
? "progressive" : "interlace");
|
||||
|
||||
else
|
||||
ret += sprintf(buf + ret, "%s\n", "null");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(frame_format, 0444, show_frame_format, NULL);
|
||||
static DEVICE_ATTR(config, 0640, show_config, store_config);
|
||||
static DEVICE_ATTR(debug, 0200, NULL, store_dbg);
|
||||
static DEVICE_ATTR(dump_pic, 0200, NULL, store_dump_mem);
|
||||
static DEVICE_ATTR(log, 0640, show_log, store_log);
|
||||
static DEVICE_ATTR(provider_vframe_status, 0444, show_vframe_status, NULL);
|
||||
static DEVICE_ATTR(tvp_region, 0444, show_tvp_region, NULL);
|
||||
|
||||
/********************************************/
|
||||
static int di_open(struct inode *node, struct file *file)
|
||||
{
|
||||
di_dev_t *di_in_devp;
|
||||
|
||||
/* Get the per-device structure that contains this cdev */
|
||||
di_in_devp = container_of(node->i_cdev, di_dev_t, cdev);
|
||||
file->private_data = di_in_devp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int di_release(struct inode *node, struct file *file)
|
||||
{
|
||||
/* di_dev_t *di_in_devp = file->private_data; */
|
||||
|
||||
/* Reset file pointer */
|
||||
|
||||
/* Release some other fields */
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long di_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
if (_IOC_TYPE(cmd) != _DI_) {
|
||||
PR_ERR("%s invalid command: %u\n", __func__, cmd);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
dbg_reg("no pq\n");
|
||||
return 0;
|
||||
#endif
|
||||
switch (cmd) {
|
||||
case AMDI_IOC_SET_PQ_PARM:
|
||||
ret = dim_pq_load_io(arg);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long di_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
arg = (unsigned long)compat_ptr(arg);
|
||||
ret = di_ioctl(file, cmd, arg);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct file_operations di_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = di_open,
|
||||
.release = di_release,
|
||||
.unlocked_ioctl = di_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = di_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int dim_rev_mem(struct di_dev_s *di_devp)
|
||||
{
|
||||
unsigned int ch;
|
||||
unsigned int o_size;
|
||||
unsigned long rmstart;
|
||||
unsigned int rmsize;
|
||||
unsigned int flg_map;
|
||||
|
||||
if (di_devp && !di_devp->flag_cma) {
|
||||
dil_get_rev_mem(&rmstart, &rmsize);
|
||||
dil_get_flg(&flg_map);
|
||||
if (!rmstart) {
|
||||
PR_ERR("%s:reserved mem start add is 0\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
di_devp->mem_start = rmstart;
|
||||
di_devp->mem_size = rmsize;
|
||||
|
||||
if (!flg_map)
|
||||
di_devp->flags |= DI_MAP_FLAG;
|
||||
|
||||
o_size = rmsize / DI_CHANNEL_NUB;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
di_set_mem_info(ch,
|
||||
di_devp->mem_start + (o_size * ch),
|
||||
o_size);
|
||||
PR_INF("rmem:ch[%d]:start:0x%lx, size:%uB\n",
|
||||
ch,
|
||||
(di_devp->mem_start + (o_size * ch)),
|
||||
o_size);
|
||||
}
|
||||
PR_INF("rmem:0x%lx, size %uMB.\n",
|
||||
di_devp->mem_start, (di_devp->mem_size >> 20));
|
||||
|
||||
di_devp->mem_flg = true;
|
||||
return 0;
|
||||
}
|
||||
PR_INF("%s:no dev or no rev mem\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool dim_rev_mem_check(void)/*tmp*/
|
||||
{
|
||||
di_dev_t *di_devp = get_dim_de_devp();
|
||||
|
||||
if (di_devp && !di_devp->flag_cma && di_devp->mem_flg)
|
||||
return true;
|
||||
|
||||
if (!di_devp) {
|
||||
PR_ERR("%s:no dev\n", __func__);
|
||||
return false;
|
||||
}
|
||||
PR_INF("%s\n", __func__);
|
||||
dim_rev_mem(di_devp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ARY_MATCH (1)
|
||||
#ifdef ARY_MATCH
|
||||
|
||||
static const struct di_meson_data data_g12a = {
|
||||
.name = "dim_g12a",
|
||||
};
|
||||
|
||||
static const struct di_meson_data data_sm1 = {
|
||||
.name = "dim_sm1",
|
||||
};
|
||||
|
||||
/* #ifdef CONFIG_USE_OF */
|
||||
static const struct of_device_id amlogic_deinterlace_dt_match[] = {
|
||||
/*{ .compatible = "amlogic, deinterlace", },*/
|
||||
{ .compatible = "amlogic, dim-g12a",
|
||||
.data = &data_g12a,
|
||||
}, { .compatible = "amlogic, dim-g12b",
|
||||
.data = &data_sm1,
|
||||
}, { .compatible = "amlogic, dim-sm1",
|
||||
.data = &data_sm1,
|
||||
}, {}
|
||||
};
|
||||
#endif
|
||||
static int dim_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
int i;
|
||||
#ifdef ARY_MATCH
|
||||
const struct of_device_id *match;
|
||||
struct di_data_l_s *pdata;
|
||||
#endif
|
||||
PR_INF("%s:\n", __func__);
|
||||
|
||||
#if 1 /*move from init to here*/
|
||||
|
||||
di_pdev = kzalloc(sizeof(*di_pdev), GFP_KERNEL);
|
||||
if (!di_pdev) {
|
||||
PR_ERR("%s fail to allocate memory.\n", __func__);
|
||||
goto fail_kmalloc_dev;
|
||||
}
|
||||
|
||||
/******************/
|
||||
ret = alloc_chrdev_region(&di_pdev->devno, 0, DI_COUNT, DEVICE_NAME);
|
||||
if (ret < 0) {
|
||||
PR_ERR("%s: failed to allocate major number\n", __func__);
|
||||
goto fail_alloc_cdev_region;
|
||||
}
|
||||
PR_INF("%s: major %d\n", __func__, MAJOR(di_pdev->devno));
|
||||
di_pdev->pclss = class_create(THIS_MODULE, CLASS_NAME);
|
||||
if (IS_ERR(di_pdev->pclss)) {
|
||||
ret = PTR_ERR(di_pdev->pclss);
|
||||
PR_ERR("%s: failed to create class\n", __func__);
|
||||
goto fail_class_create;
|
||||
}
|
||||
#endif
|
||||
|
||||
di_devp = di_pdev;
|
||||
/* *********new********* */
|
||||
di_pdev->data_l = NULL;
|
||||
di_pdev->data_l = kzalloc(sizeof(struct di_data_l_s), GFP_KERNEL);
|
||||
if (!di_pdev->data_l) {
|
||||
PR_ERR("%s fail to allocate data l.\n", __func__);
|
||||
goto fail_kmalloc_datal;
|
||||
}
|
||||
/*memset(di_pdev->data_l, 0, sizeof(struct di_data_l_s));*/
|
||||
/*pr_info("\tdata size: %ld\n", sizeof(struct di_data_l_s));*/
|
||||
/************************/
|
||||
if (!dip_prob())
|
||||
goto fail_cdev_add;
|
||||
|
||||
di_devp->flags |= DI_SUSPEND_FLAG;
|
||||
cdev_init(&di_devp->cdev, &di_fops);
|
||||
di_devp->cdev.owner = THIS_MODULE;
|
||||
ret = cdev_add(&di_devp->cdev, di_devp->devno, DI_COUNT);
|
||||
if (ret)
|
||||
goto fail_cdev_add;
|
||||
|
||||
di_devp->devt = MKDEV(MAJOR(di_devp->devno), 0);
|
||||
di_devp->dev = device_create(di_devp->pclss, &pdev->dev,
|
||||
di_devp->devt, di_devp, "di%d", 0);
|
||||
|
||||
if (!di_devp->dev) {
|
||||
pr_error("device_create create error\n");
|
||||
goto fail_cdev_add;
|
||||
}
|
||||
dev_set_drvdata(di_devp->dev, di_devp);
|
||||
platform_set_drvdata(pdev, di_devp);
|
||||
|
||||
#ifdef ARY_MATCH
|
||||
/************************/
|
||||
match = of_match_device(amlogic_deinterlace_dt_match,
|
||||
&pdev->dev);
|
||||
if (!match) {
|
||||
PR_ERR("%s,no matched table\n", __func__);
|
||||
goto fail_cdev_add;
|
||||
}
|
||||
pdata = (struct di_data_l_s *)di_pdev->data_l;
|
||||
pdata->mdata = match->data;
|
||||
PR_INF("match name: %s\n", pdata->mdata->name);
|
||||
#endif
|
||||
|
||||
ret = of_reserved_mem_device_init(&pdev->dev);
|
||||
if (ret != 0)
|
||||
PR_INF("no reserved mem.\n");
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"flag_cma", &di_devp->flag_cma);
|
||||
if (ret)
|
||||
PR_ERR("DI-%s: get flag_cma error.\n", __func__);
|
||||
else
|
||||
PR_INF("flag_cma=%d\n", di_devp->flag_cma);
|
||||
|
||||
dim_rev_mem(di_devp);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"nrds-enable", &di_devp->nrds_enable);
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"pps-enable", &di_devp->pps_enable);
|
||||
|
||||
/*di pre h scaling down :sm1 tm2*/
|
||||
/*pre_hsc_down_en;*/
|
||||
di_devp->h_sc_down_en = di_mp_uit_get(eDI_MP_pre_hsc_down_en);
|
||||
|
||||
if (di_devp->flag_cma >= 1) {
|
||||
#ifdef CONFIG_CMA
|
||||
di_devp->pdev = pdev;
|
||||
di_devp->flags |= DI_MAP_FLAG;
|
||||
#if 0
|
||||
di_devp->mem_size = dma_get_cma_size_int_byte(&pdev->dev);
|
||||
#else
|
||||
if (di_devp->flag_cma == 1 ||
|
||||
di_devp->flag_cma == 2) {
|
||||
di_devp->mem_size
|
||||
= dma_get_cma_size_int_byte(&pdev->dev);
|
||||
PR_INF("mem size from dts:0x%x\n", di_devp->mem_size);
|
||||
}
|
||||
|
||||
if (di_devp->mem_size <= 0x800000) {/*need check??*/
|
||||
di_devp->mem_size = 0x2800000;
|
||||
/*(flag_cma ? 3) reserved in*/
|
||||
/*codec mm : cma in codec mm*/
|
||||
if (di_devp->flag_cma != 3) {
|
||||
/*no di cma, try use*/
|
||||
/*cma from codec mm*/
|
||||
di_devp->flag_cma = 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pr_info("DI: CMA size 0x%x.\n", di_devp->mem_size);
|
||||
if (di_devp->flag_cma == 2) {
|
||||
if (dim_cma_alloc_total(di_devp))
|
||||
dip_cma_st_set_ready_all();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
dip_cma_st_set_ready_all();
|
||||
}
|
||||
/* mutex_init(&di_devp->cma_mutex); */
|
||||
INIT_LIST_HEAD(&di_devp->pq_table_list);
|
||||
|
||||
atomic_set(&di_devp->pq_flag, 0);
|
||||
|
||||
di_devp->pre_irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
|
||||
pr_info("pre_irq:%d\n",
|
||||
di_devp->pre_irq);
|
||||
di_devp->post_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
|
||||
pr_info("post_irq:%d\n",
|
||||
di_devp->post_irq);
|
||||
|
||||
di_pr_info("%s allocate rdma channel %d.\n", __func__,
|
||||
di_devp->rdma_handle);
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
|
||||
dim_get_vpu_clkb(&pdev->dev, di_devp);
|
||||
#ifdef CLK_TREE_SUPPORT
|
||||
clk_prepare_enable(di_devp->vpu_clkb);
|
||||
pr_info("DI:enable vpu clkb.\n");
|
||||
#else
|
||||
aml_write_hiubus(HHI_VPU_CLKB_CNTL, 0x1000100);
|
||||
#endif
|
||||
}
|
||||
di_devp->flags &= (~DI_SUSPEND_FLAG);
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"buffer-size", &di_devp->buffer_size);
|
||||
if (ret)
|
||||
PR_ERR("DI-%s: get buffer size error.\n", __func__);
|
||||
|
||||
/* set flag to indicate that post_wr is supportted */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"post-wr-support",
|
||||
&di_devp->post_wr_support);
|
||||
if (ret)
|
||||
dimp_set(eDI_MP_post_wr_support, 0);/*post_wr_support = 0;*/
|
||||
else /*post_wr_support = di_devp->post_wr_support;*/
|
||||
dimp_set(eDI_MP_post_wr_support, di_devp->post_wr_support);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"nr10bit-support",
|
||||
&di_devp->nr10bit_support);
|
||||
if (ret)
|
||||
dimp_set(eDI_MP_nr10bit_support, 0);/*nr10bit_support = 0;*/
|
||||
else /*nr10bit_support = di_devp->nr10bit_support;*/
|
||||
dimp_set(eDI_MP_nr10bit_support, di_devp->nr10bit_support);
|
||||
|
||||
#ifdef DI_USE_FIXED_CANVAS_IDX
|
||||
if (dim_get_canvas()) {
|
||||
pr_dbg("DI get canvas error.\n");
|
||||
ret = -EEXIST;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
device_create_file(di_devp->dev, &dev_attr_config);
|
||||
device_create_file(di_devp->dev, &dev_attr_debug);
|
||||
device_create_file(di_devp->dev, &dev_attr_dump_pic);
|
||||
device_create_file(di_devp->dev, &dev_attr_log);
|
||||
device_create_file(di_devp->dev, &dev_attr_provider_vframe_status);
|
||||
device_create_file(di_devp->dev, &dev_attr_frame_format);
|
||||
device_create_file(di_devp->dev, &dev_attr_tvp_region);
|
||||
|
||||
/*pd_device_files_add*/
|
||||
get_ops_pd()->prob(di_devp->dev);
|
||||
|
||||
get_ops_nr()->nr_drv_init(di_devp->dev);
|
||||
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++) {
|
||||
set_init_flag(i, false);
|
||||
set_reg_flag(i, false);
|
||||
}
|
||||
|
||||
set_or_act_flag(true);
|
||||
/*PR_INF("\t 11\n");*/
|
||||
ret = devm_request_irq(&pdev->dev, di_devp->pre_irq, &dim_irq,
|
||||
IRQF_SHARED,
|
||||
"pre_di", (void *)"pre_di");
|
||||
if (di_devp->post_wr_support) {
|
||||
ret = devm_request_irq(&pdev->dev, di_devp->post_irq,
|
||||
&dim_post_irq,
|
||||
IRQF_SHARED, "post_di",
|
||||
(void *)"post_di");
|
||||
}
|
||||
|
||||
di_devp->sema_flg = 1; /*di_sema_init_flag = 1;*/
|
||||
dimh_hw_init(dimp_get(eDI_MP_pulldown_enable),
|
||||
dimp_get(eDI_MP_mcpre_en));
|
||||
|
||||
dim_set_di_flag();
|
||||
|
||||
task_start();
|
||||
|
||||
post_mif_sw(false);
|
||||
|
||||
dim_debugfs_init(); /*2018-07-18 add debugfs*/
|
||||
|
||||
dimh_patch_post_update_mc_sw(DI_MC_SW_IC, true);
|
||||
|
||||
pr_info("%s:ok\n", __func__);
|
||||
return ret;
|
||||
|
||||
fail_cdev_add:
|
||||
pr_info("%s:fail_cdev_add\n", __func__);
|
||||
kfree(di_devp->data_l);
|
||||
|
||||
fail_kmalloc_datal:
|
||||
pr_info("%s:fail_kmalloc datal\n", __func__);
|
||||
|
||||
#if 1 /*move from init*/
|
||||
/*fail_pdrv_register:*/
|
||||
class_destroy(di_pdev->pclss);
|
||||
fail_class_create:
|
||||
unregister_chrdev_region(di_pdev->devno, DI_COUNT);
|
||||
fail_alloc_cdev_region:
|
||||
kfree(di_pdev);
|
||||
fail_kmalloc_dev:
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dim_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
PR_INF("%s:\n", __func__);
|
||||
di_devp = platform_get_drvdata(pdev);
|
||||
|
||||
dimh_hw_uninit();
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
|
||||
clk_disable_unprepare(di_devp->vpu_clkb);
|
||||
|
||||
di_devp->di_event = 0xff;
|
||||
|
||||
dim_uninit_buf(1, 0);/*channel 0*/
|
||||
di_set_flg_hw_int(false);
|
||||
|
||||
task_stop();
|
||||
|
||||
dim_rdma_exit();
|
||||
|
||||
/* Remove the cdev */
|
||||
device_remove_file(di_devp->dev, &dev_attr_config);
|
||||
device_remove_file(di_devp->dev, &dev_attr_debug);
|
||||
device_remove_file(di_devp->dev, &dev_attr_log);
|
||||
device_remove_file(di_devp->dev, &dev_attr_dump_pic);
|
||||
device_remove_file(di_devp->dev, &dev_attr_provider_vframe_status);
|
||||
device_remove_file(di_devp->dev, &dev_attr_frame_format);
|
||||
device_remove_file(di_devp->dev, &dev_attr_tvp_region);
|
||||
/*pd_device_files_del*/
|
||||
get_ops_pd()->remove(di_devp->dev);
|
||||
get_ops_nr()->nr_drv_uninit(di_devp->dev);
|
||||
cdev_del(&di_devp->cdev);
|
||||
|
||||
if (di_devp->flag_cma == 2) {
|
||||
if (dma_release_from_contiguous(&pdev->dev,
|
||||
di_devp->total_pages,
|
||||
di_devp->mem_size >> PAGE_SHIFT)) {
|
||||
di_devp->total_pages = NULL;
|
||||
di_devp->mem_start = 0;
|
||||
pr_dbg("DI CMA total release ok.\n");
|
||||
} else {
|
||||
pr_dbg("DI CMA total release fail.\n");
|
||||
}
|
||||
if (di_pdev->nrds_enable) {
|
||||
dim_nr_ds_buf_uninit(di_pdev->flag_cma,
|
||||
&pdev->dev);
|
||||
}
|
||||
}
|
||||
device_destroy(di_devp->pclss, di_devp->devno);
|
||||
|
||||
/* free drvdata */
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
#if 1 /*move to remove*/
|
||||
class_destroy(di_pdev->pclss);
|
||||
|
||||
dim_debugfs_exit();
|
||||
|
||||
dip_exit();
|
||||
unregister_chrdev_region(di_pdev->devno, DI_COUNT);
|
||||
#endif
|
||||
|
||||
kfree(di_devp->data_l);
|
||||
kfree(di_pdev);
|
||||
|
||||
PR_INF("%s:finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dim_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
int i;
|
||||
|
||||
di_devp = platform_get_drvdata(pdev);
|
||||
|
||||
for (i = 0; i < DI_CHANNEL_NUB; i++)
|
||||
set_init_flag(i, false);
|
||||
|
||||
if (is_meson_txlx_cpu())
|
||||
dim_top_gate_control(true, true);
|
||||
else
|
||||
dim_DI_Wr(DI_CLKG_CTRL, 0x2);
|
||||
|
||||
if (!is_meson_txlx_cpu())
|
||||
diext_clk_b_sw(false);
|
||||
|
||||
PR_INF("%s.\n", __func__);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static void di_clear_for_suspend(struct di_dev_s *di_devp)
|
||||
{
|
||||
unsigned int channel = get_current_channel(); /*tmp*/
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
di_vframe_unreg(channel);/*have flag*/
|
||||
|
||||
if (dip_chst_get(channel) != eDI_TOP_STATE_IDLE)
|
||||
dim_unreg_process_irq(channel);
|
||||
|
||||
dip_cma_close();
|
||||
pr_info("%s end\n", __func__);
|
||||
}
|
||||
|
||||
/* must called after lcd */
|
||||
static int di_suspend(struct device *dev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
di_devp = dev_get_drvdata(dev);
|
||||
di_devp->flags |= DI_SUSPEND_FLAG;
|
||||
|
||||
di_clear_for_suspend(di_devp);
|
||||
|
||||
if (!is_meson_txlx_cpu())
|
||||
diext_clk_b_sw(false);
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD))
|
||||
clk_disable_unprepare(di_devp->vpu_clkb);
|
||||
PR_INF("%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* must called before lcd */
|
||||
static int di_resume(struct device *dev)
|
||||
{
|
||||
struct di_dev_s *di_devp = NULL;
|
||||
|
||||
PR_INF("%s\n", __func__);
|
||||
di_devp = dev_get_drvdata(dev);
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))
|
||||
clk_prepare_enable(di_devp->vpu_clkb);
|
||||
|
||||
di_devp->flags &= ~DI_SUSPEND_FLAG;
|
||||
|
||||
/************/
|
||||
PR_INF("%s finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops di_pm_ops = {
|
||||
.suspend_late = di_suspend,
|
||||
.resume_early = di_resume,
|
||||
};
|
||||
#endif
|
||||
#ifndef ARY_MATCH
|
||||
/* #ifdef CONFIG_USE_OF */
|
||||
static const struct of_device_id amlogic_deinterlace_dt_match[] = {
|
||||
/*{ .compatible = "amlogic, deinterlace", },*/
|
||||
{ .compatible = "amlogic, dim-g12a", },
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
/* #else */
|
||||
/* #define amlogic_deinterlace_dt_match NULL */
|
||||
/* #endif */
|
||||
|
||||
static struct platform_driver di_driver = {
|
||||
.probe = dim_probe,
|
||||
.remove = dim_remove,
|
||||
.shutdown = dim_shutdown,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = amlogic_deinterlace_dt_match,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &di_pm_ops,
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
static int __init dim_module_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
PR_INF("%s\n", __func__);
|
||||
|
||||
ret = platform_driver_register(&di_driver);
|
||||
if (ret != 0) {
|
||||
PR_ERR("%s: failed to register driver\n", __func__);
|
||||
/*goto fail_pdrv_register;*/
|
||||
return -ENODEV;
|
||||
}
|
||||
PR_INF("%s finish\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dim_module_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&di_driver);
|
||||
PR_INF("%s: ok.\n", __func__);
|
||||
}
|
||||
|
||||
module_init(dim_module_init);
|
||||
module_exit(dim_module_exit);
|
||||
|
||||
MODULE_DESCRIPTION("AMLOGIC MULTI-DI driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("4.0.0");
|
||||
|
||||
26
drivers/amlogic/media/di_multi/di_sys.h
Normal file
26
drivers/amlogic/media/di_multi/di_sys.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_sys.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_SYS_H__
|
||||
#define __DI_SYS_H__
|
||||
|
||||
#define DEVICE_NAME "di_multi"
|
||||
#define CLASS_NAME "deinterlace"
|
||||
|
||||
bool dim_rev_mem_check(void);
|
||||
|
||||
#endif /*__DI_SYS_H__*/
|
||||
315
drivers/amlogic/media/di_multi/di_task.c
Normal file
315
drivers/amlogic/media/di_multi/di_task.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_task.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kthread.h> /*ary add*/
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
|
||||
#include "di_prc.h"
|
||||
|
||||
#include "di_task.h"
|
||||
#include "di_vframe.h"
|
||||
|
||||
static void task_wakeup(struct di_task *tsk);
|
||||
|
||||
unsigned int di_dbg_task_flg; /*debug only*/
|
||||
|
||||
bool task_send_cmd(unsigned int cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
unsigned int val;
|
||||
|
||||
dbg_reg("%s:cmd[%d]:\n", __func__, cmd);
|
||||
if (kfifo_is_full(&tsk->fifo_cmd)) {
|
||||
if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int)) {
|
||||
PR_ERR("%s:can't out\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
PR_ERR("%s:lost cmd[%d]\n", __func__, val);
|
||||
tsk->err_cmd_cnt++;
|
||||
/*return false;*/
|
||||
}
|
||||
kfifo_in_spinlocked(&tsk->fifo_cmd, &cmd, sizeof(unsigned int),
|
||||
&tsk->lock_cmd);
|
||||
|
||||
task_wakeup(tsk);
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_send_ready(void)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool task_have_vf(unsigned int ch)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
#endif
|
||||
bool task_get_cmd(unsigned int *cmd)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
unsigned int val;
|
||||
|
||||
if (kfifo_is_empty(&tsk->fifo_cmd))
|
||||
return false;
|
||||
|
||||
if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int))
|
||||
!= sizeof(unsigned int))
|
||||
return false;
|
||||
|
||||
*cmd = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_polling_cmd(void)
|
||||
{
|
||||
int i;
|
||||
union DI_L_CMD_BITS cmdbyte;
|
||||
|
||||
for (i = 0; i < MAX_KFIFO_L_CMD_NUB; i++) {
|
||||
if (!task_get_cmd(&cmdbyte.cmd32))
|
||||
break;
|
||||
dip_chst_process_reg(cmdbyte.b.ch);
|
||||
}
|
||||
}
|
||||
|
||||
static int task_is_exiting(struct di_task *tsk)
|
||||
{
|
||||
if (tsk->exit)
|
||||
return 1;
|
||||
|
||||
/* if (afepriv->dvbdev->writers == 1)
|
||||
* if (time_after_eq(jiffies, fepriv->release_jiffies +
|
||||
* dvb_shutdown_timeout * HZ))
|
||||
* return 1;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int task_should_wakeup(struct di_task *tsk)
|
||||
{
|
||||
if (tsk->wakeup) {
|
||||
tsk->wakeup = 0;
|
||||
/*dbg only dbg_tsk("wkg[%d]\n", di_dbg_task_flg);*/
|
||||
return 1;
|
||||
}
|
||||
return task_is_exiting(tsk);
|
||||
}
|
||||
|
||||
static void task_wakeup(struct di_task *tsk)
|
||||
{
|
||||
tsk->wakeup = 1;
|
||||
wake_up_interruptible(&tsk->wait_queue);
|
||||
/*dbg_tsk("wks[%d]\n", di_dbg_task_flg);*/
|
||||
}
|
||||
|
||||
static int di_test_thread(void *data)
|
||||
{
|
||||
struct di_task *tsk = data;
|
||||
bool semheld = false;
|
||||
|
||||
tsk->delay = HZ;
|
||||
tsk->status = 0;
|
||||
tsk->wakeup = 0;
|
||||
#if 0
|
||||
tsk->reinitialise = 0;
|
||||
tsk->needfinish = 0;
|
||||
tsk->finishflg = 0;
|
||||
#endif
|
||||
set_freezable();
|
||||
while (1) {
|
||||
up(&tsk->sem);/* is locked when we enter the thread... */
|
||||
restart:
|
||||
wait_event_interruptible_timeout(tsk->wait_queue,
|
||||
task_should_wakeup(tsk) ||
|
||||
kthread_should_stop() ||
|
||||
freezing(current),
|
||||
tsk->delay);
|
||||
di_dbg_task_flg = 1;
|
||||
|
||||
if (kthread_should_stop() || task_is_exiting(tsk)) {
|
||||
/* got signal or quitting */
|
||||
if (!down_interruptible(&tsk->sem))
|
||||
semheld = true;
|
||||
tsk->exit = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (try_to_freeze())
|
||||
goto restart;
|
||||
|
||||
if (down_interruptible(&tsk->sem))
|
||||
break;
|
||||
#if 0
|
||||
if (tsk->reinitialise) {
|
||||
/*dvb_frontend_init(fe);*/
|
||||
|
||||
tsk->reinitialise = 0;
|
||||
}
|
||||
#endif
|
||||
di_dbg_task_flg = 2;
|
||||
task_polling_cmd();
|
||||
di_dbg_task_flg = 3;
|
||||
dip_chst_process_ch();
|
||||
di_dbg_task_flg = 4;
|
||||
if (get_reg_flag_all())
|
||||
dip_hw_process();
|
||||
|
||||
di_dbg_task_flg = 0;
|
||||
}
|
||||
|
||||
tsk->thread = NULL;
|
||||
if (kthread_should_stop())
|
||||
tsk->exit = 1;
|
||||
else
|
||||
tsk->exit = 0;
|
||||
/*mb();*/
|
||||
|
||||
if (semheld)
|
||||
up(&tsk->sem);
|
||||
|
||||
task_wakeup(tsk);/*?*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void task_stop(void/*struct di_task *tsk*/)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
#if 1 /*not use cmd*/
|
||||
pr_info(".");
|
||||
/*--------------------*/
|
||||
/*cmd buf*/
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
/*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/
|
||||
spin_lock_init(&tsk->lock_cmd);
|
||||
tsk->err_cmd_cnt = 0;
|
||||
/*--------------------*/
|
||||
#endif
|
||||
tsk->exit = 1;
|
||||
/*mb();*/
|
||||
|
||||
if (!tsk->thread)
|
||||
return;
|
||||
|
||||
kthread_stop(tsk->thread);
|
||||
|
||||
sema_init(&tsk->sem, 1);
|
||||
tsk->status = 0;
|
||||
|
||||
/* paranoia check in case a signal arrived */
|
||||
if (tsk->thread)
|
||||
PR_ERR("warning: thread %p won't exit\n", tsk->thread);
|
||||
}
|
||||
|
||||
int task_start(void)
|
||||
{
|
||||
int ret;
|
||||
int flg_err;
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
struct task_struct *fe_thread;
|
||||
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
|
||||
|
||||
pr_info(".");
|
||||
flg_err = 0;
|
||||
#if 1 /*not use cmd*/
|
||||
/*--------------------*/
|
||||
/*cmd buf*/
|
||||
/*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/
|
||||
spin_lock_init(&tsk->lock_cmd);
|
||||
tsk->err_cmd_cnt = 0;
|
||||
ret = kfifo_alloc(&tsk->fifo_cmd,
|
||||
sizeof(unsigned int) * MAX_KFIFO_L_CMD_NUB,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
tsk->flg_cmd = false;
|
||||
PR_ERR("%s:can't get kfifo\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
tsk->flg_cmd = true;
|
||||
|
||||
#endif
|
||||
/*--------------------*/
|
||||
sema_init(&tsk->sem, 1);
|
||||
init_waitqueue_head(&tsk->wait_queue);
|
||||
|
||||
if (tsk->thread) {
|
||||
if (!tsk->exit)
|
||||
return 0;
|
||||
|
||||
task_stop();
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
return -EINTR;
|
||||
}
|
||||
if (down_interruptible(&tsk->sem)) {
|
||||
if (tsk->flg_cmd) {
|
||||
kfifo_free(&tsk->fifo_cmd);
|
||||
tsk->flg_cmd = 0;
|
||||
}
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
tsk->status = 0;
|
||||
tsk->exit = 0;
|
||||
tsk->thread = NULL;
|
||||
/*mb();*/
|
||||
|
||||
fe_thread = kthread_run(di_test_thread, tsk, "aml-ditest-0");
|
||||
if (IS_ERR(fe_thread)) {
|
||||
ret = PTR_ERR(fe_thread);
|
||||
PR_ERR(" failed to start kthread (%d)\n", ret);
|
||||
up(&tsk->sem);
|
||||
tsk->flg_init = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sched_setscheduler_nocheck(fe_thread, SCHED_FIFO, ¶m);
|
||||
tsk->flg_init = 1;
|
||||
tsk->thread = fe_thread;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbg_task(void)
|
||||
{
|
||||
struct di_task *tsk = get_task();
|
||||
|
||||
tsk->status = 1;
|
||||
task_wakeup(tsk);
|
||||
}
|
||||
36
drivers/amlogic/media/di_multi/di_task.h
Normal file
36
drivers/amlogic/media/di_multi/di_task.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_task.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_TASK_H__
|
||||
#define __DI_TASK_H__
|
||||
|
||||
extern unsigned int di_dbg_task_flg; /*debug only*/
|
||||
|
||||
enum eTSK_STATE {
|
||||
eTSK_STATE_IDLE,
|
||||
eTSK_STATE_WORKING,
|
||||
};
|
||||
|
||||
void task_stop(void);
|
||||
int task_start(void);
|
||||
|
||||
void dbg_task(void);
|
||||
|
||||
bool task_send_cmd(unsigned int cmd);
|
||||
void task_send_ready(void);
|
||||
|
||||
#endif /*__DI_TASK_H__*/
|
||||
556
drivers/amlogic/media/di_multi/di_vframe.c
Normal file
556
drivers/amlogic/media/di_multi/di_vframe.c
Normal file
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_vframe.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "deinterlace.h"
|
||||
#include "di_data_l.h"
|
||||
#include "di_pre.h"
|
||||
#include "di_prc.h"
|
||||
#include "di_dbg.h"
|
||||
|
||||
#include "di_vframe.h"
|
||||
|
||||
struct dev_vfram_t *get_dev_vframe(unsigned int ch)
|
||||
{
|
||||
if (ch < DI_CHANNEL_NUB)
|
||||
return &get_datal()->ch_data[ch].vfm;
|
||||
|
||||
pr_info("err:%s ch overflow %d\n", __func__, ch);
|
||||
return &get_datal()->ch_data[0].vfm;
|
||||
}
|
||||
|
||||
const char * const di_rev_name[4] = {
|
||||
"deinterlace",
|
||||
"dimulti.1",
|
||||
"dimulti.2",
|
||||
"dimulti.3",
|
||||
};
|
||||
|
||||
void dev_vframe_reg(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
if (pvfm->reg) {
|
||||
PR_WARN("duplicate reg\n");
|
||||
return;
|
||||
}
|
||||
vf_reg_provider(&pvfm->di_vf_prov);
|
||||
vf_notify_receiver(pvfm->name, VFRAME_EVENT_PROVIDER_START, NULL);
|
||||
pvfm->reg = 1;
|
||||
}
|
||||
|
||||
void dev_vframe_unreg(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
if (pvfm->reg) {
|
||||
vf_unreg_provider(&pvfm->di_vf_prov);
|
||||
pvfm->reg = 0;
|
||||
} else {
|
||||
PR_WARN("duplicate ureg\n");
|
||||
}
|
||||
}
|
||||
|
||||
void di_vframe_reg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
dev_vframe_reg(pvfm);
|
||||
}
|
||||
|
||||
void di_vframe_unreg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
dev_vframe_unreg(pvfm);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
const char * const di_receiver_event_cmd[] = {
|
||||
"",
|
||||
"_UNREG",
|
||||
"_LIGHT_UNREG",
|
||||
"_START",
|
||||
NULL, /* "_VFRAME_READY", */
|
||||
NULL, /* "_QUREY_STATE", */
|
||||
"_RESET",
|
||||
NULL, /* "_FORCE_BLACKOUT", */
|
||||
"_REG",
|
||||
"_LIGHT_UNREG_RETURN_VFRAME",
|
||||
NULL, /* "_DPBUF_CONFIG", */
|
||||
NULL, /* "_QUREY_VDIN2NR", */
|
||||
NULL, /* "_SET_3D_VFRAME_INTERLEAVE", */
|
||||
NULL, /* "_FR_HINT", */
|
||||
NULL, /* "_FR_END_HINT", */
|
||||
NULL, /* "_QUREY_DISPLAY_INFO", */
|
||||
NULL, /* "_PROPERTY_CHANGED", */
|
||||
};
|
||||
|
||||
#define VFRAME_EVENT_PROVIDER_CMD_MAX 16
|
||||
|
||||
static int di_receiver_event_fun(int type, void *data, void *arg)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
unsigned int ch;
|
||||
int ret = 0;
|
||||
|
||||
ch = *(int *)arg;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
if (type <= VFRAME_EVENT_PROVIDER_CMD_MAX &&
|
||||
di_receiver_event_cmd[type]) {
|
||||
dbg_ev("ch[%d]:%s,%d:%s\n", ch, __func__,
|
||||
type,
|
||||
di_receiver_event_cmd[type]);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VFRAME_EVENT_PROVIDER_UNREG:
|
||||
ret = di_ori_event_unreg(ch);
|
||||
/* task_send_cmd(LCMD1(eCMD_UNREG, 0));*/
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_REG:
|
||||
/*dev_vframe_reg(pvfm);*/
|
||||
ret = di_ori_event_reg(data, ch);
|
||||
/* task_send_cmd(LCMD1(eCMD_REG, 0));*/
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_START:
|
||||
break;
|
||||
|
||||
case VFRAME_EVENT_PROVIDER_LIGHT_UNREG:
|
||||
ret = di_ori_event_light_unreg(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_VFRAME_READY:
|
||||
ret = di_ori_event_ready(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_QUREY_STATE:
|
||||
ret = di_ori_event_qurey_state(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_RESET:
|
||||
ret = di_ori_event_reset(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME:
|
||||
ret = di_ori_event_light_unreg_revframe(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR:
|
||||
ret = di_ori_event_qurey_vdin2nr(ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE:
|
||||
di_ori_event_set_3D(type, data, ch);
|
||||
break;
|
||||
case VFRAME_EVENT_PROVIDER_FR_HINT:
|
||||
case VFRAME_EVENT_PROVIDER_FR_END_HINT:
|
||||
vf_notify_receiver(pvfm->name, type, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct vframe_receiver_op_s di_vf_receiver = {
|
||||
.event_cb = di_receiver_event_fun
|
||||
};
|
||||
|
||||
bool vf_type_is_prog(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_TYPEMASK) == 0 ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_interlace(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_INTERLACE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_top(unsigned int type)
|
||||
{
|
||||
bool ret = ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP)
|
||||
? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_bottom(unsigned int type)
|
||||
{
|
||||
bool ret = ((type & VIDTYPE_INTERLACE_BOTTOM)
|
||||
== VIDTYPE_INTERLACE_BOTTOM)
|
||||
? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_inter_first(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_INTERLACE_TOP) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_mvc(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_MVC) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_no_video_en(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_NO_VIDEO_ENABLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU422(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_422) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU_FIELD(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_FIELD) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU_SINGLE(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_SINGLE_PLANE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIU444(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_444) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_VIUNV21(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VIU_NV21) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_vscale_dis(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VSCALE_DISABLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_canvas_toggle(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_CANVAS_TOGGLE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_pre_interlace(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_PRE_INTERLACE) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_highrun(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_HIGHRUN) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_compress(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_COMPRESS) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_pic(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_PIC) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_scatter(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_SCATTER) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vf_type_is_vd2(unsigned int type)
|
||||
{
|
||||
bool ret = (type & VIDTYPE_VD2) ? true : false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_bypss_complete(struct dev_vfram_t *pvfm)
|
||||
{
|
||||
return pvfm->bypass_complete;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool is_reg(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
return pvfm->reg;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_bypass_complete(struct dev_vfram_t *pvfm, bool on)
|
||||
{
|
||||
if (on)
|
||||
pvfm->bypass_complete = true;
|
||||
else
|
||||
pvfm->bypass_complete = false;
|
||||
}
|
||||
|
||||
void set_bypass2_complete(unsigned int ch, bool on)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
set_bypass_complete(pvfm, on);
|
||||
}
|
||||
|
||||
bool is_bypss2_complete(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
return is_bypss_complete(pvfm);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void set_reg(unsigned int ch, int on)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
if (on)
|
||||
pvfm->reg = true;
|
||||
else
|
||||
pvfm->reg = false;
|
||||
}
|
||||
#endif
|
||||
static struct vframe_s *di_vf_peek(void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
/*dim_print("%s:ch[%d]\n",__func__,ch);*/
|
||||
if (di_is_pause(ch))
|
||||
return NULL;
|
||||
|
||||
if (is_bypss2_complete(ch))
|
||||
return pw_vf_peek(ch);
|
||||
else
|
||||
return di_vf_l_peek(ch);
|
||||
}
|
||||
|
||||
static struct vframe_s *di_vf_get(void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
/*struct vframe_s *vfm;*/
|
||||
|
||||
dim_tr_ops.post_get2(5);
|
||||
if (di_is_pause(ch))
|
||||
return NULL;
|
||||
|
||||
di_pause_step_done(ch);
|
||||
|
||||
/*pvfm = get_dev_vframe(ch);*/
|
||||
|
||||
if (is_bypss2_complete(ch))
|
||||
#if 0
|
||||
vfm = pw_vf_peek(ch);
|
||||
if (dim_bypass_detect(ch, vfm))
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
return pw_vf_get(ch);
|
||||
|
||||
return di_vf_l_get(ch);
|
||||
}
|
||||
|
||||
static void di_vf_put(struct vframe_s *vf, void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
if (is_bypss2_complete(ch)) {
|
||||
pw_vf_put(vf, ch);
|
||||
pw_vf_notify_provider(ch,
|
||||
VFRAME_EVENT_RECEIVER_PUT, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
di_vf_l_put(vf, ch);
|
||||
}
|
||||
|
||||
static int di_event_cb(int type, void *data, void *private_data)
|
||||
{
|
||||
if (type == VFRAME_EVENT_RECEIVER_FORCE_UNREG) {
|
||||
pr_info("%s: RECEIVER_FORCE_UNREG return\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int di_vf_states(struct vframe_states *states, void *arg)
|
||||
{
|
||||
unsigned int ch = *(int *)arg;
|
||||
|
||||
if (!states)
|
||||
return -1;
|
||||
|
||||
dim_print("%s:ch[%d]\n", __func__, ch);
|
||||
|
||||
di_vf_l_states(states, ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct vframe_operations_s deinterlace_vf_provider = {
|
||||
.peek = di_vf_peek,
|
||||
.get = di_vf_get,
|
||||
.put = di_vf_put,
|
||||
.event_cb = di_event_cb,
|
||||
.vf_states = di_vf_states,
|
||||
};
|
||||
|
||||
#if 1
|
||||
struct vframe_s *pw_vf_get(unsigned int ch)
|
||||
{
|
||||
sum_g_inc(ch);
|
||||
return vf_get(di_rev_name[ch]);
|
||||
}
|
||||
|
||||
struct vframe_s *pw_vf_peek(unsigned int ch)
|
||||
{
|
||||
return vf_peek(di_rev_name[ch]);
|
||||
}
|
||||
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int ch)
|
||||
{
|
||||
sum_p_inc(ch);
|
||||
vf_put(vf, di_rev_name[ch]);
|
||||
}
|
||||
|
||||
int pw_vf_notify_provider(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_provider(di_rev_name[channel], event_type, data);
|
||||
}
|
||||
|
||||
int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_receiver(di_rev_name[channel], event_type, data);
|
||||
}
|
||||
|
||||
void pw_vf_light_unreg_provider(unsigned int ch)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
struct vframe_provider_s *prov;
|
||||
|
||||
pvfm = get_dev_vframe(ch);
|
||||
|
||||
prov = &pvfm->di_vf_prov;
|
||||
vf_light_unreg_provider(prov);
|
||||
}
|
||||
|
||||
#else
|
||||
struct vframe_s *pw_vf_get(unsigned int channel)
|
||||
{
|
||||
return vf_get(VFM_NAME);
|
||||
}
|
||||
|
||||
struct vframe_s *pw_vf_peek(unsigned int channel)
|
||||
{
|
||||
return vf_peek(VFM_NAME);
|
||||
}
|
||||
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int channel)
|
||||
{
|
||||
vf_put(vf, VFM_NAME);
|
||||
}
|
||||
|
||||
int pw_vf_notify_provider(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_provider(VFM_NAME, event_type, data);
|
||||
}
|
||||
|
||||
int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data)
|
||||
{
|
||||
return vf_notify_receiver(VFM_NAME, event_type, data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void dev_vframe_exit(void)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
int ch;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
pvfm = get_dev_vframe(ch);
|
||||
vf_unreg_provider(&pvfm->di_vf_prov);
|
||||
vf_unreg_receiver(&pvfm->di_vf_recv);
|
||||
}
|
||||
pr_info("%s finish\n", __func__);
|
||||
}
|
||||
|
||||
void dev_vframe_init(void)
|
||||
{
|
||||
struct dev_vfram_t *pvfm;
|
||||
int ch;
|
||||
|
||||
for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
|
||||
pvfm = get_dev_vframe(ch);
|
||||
pvfm->name = di_rev_name[ch];
|
||||
pvfm->indx = ch;
|
||||
/*set_bypass_complete(pvfm, true);*/ /*test only*/
|
||||
|
||||
/*receiver:*/
|
||||
vf_receiver_init(&pvfm->di_vf_recv, pvfm->name,
|
||||
&di_vf_receiver, &pvfm->indx);
|
||||
vf_reg_receiver(&pvfm->di_vf_recv);
|
||||
|
||||
/*provider:*/
|
||||
vf_provider_init(&pvfm->di_vf_prov, pvfm->name,
|
||||
&deinterlace_vf_provider, &pvfm->indx);
|
||||
}
|
||||
pr_info("%s finish\n", __func__);
|
||||
}
|
||||
68
drivers/amlogic/media/di_multi/di_vframe.h
Normal file
68
drivers/amlogic/media/di_multi/di_vframe.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/di_vframe.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DI_VFRAME_H__
|
||||
#define __DI_VFRAME_H__
|
||||
|
||||
#include <linux/amlogic/media/vfm/vframe.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_provider.h>
|
||||
#include <linux/amlogic/media/vfm/vframe_receiver.h>
|
||||
|
||||
void dev_vframe_init(void);
|
||||
void dev_vframe_exit(void);
|
||||
void di_vframe_reg(unsigned int ch);
|
||||
void di_vframe_unreg(unsigned int ch);
|
||||
|
||||
bool vf_type_is_prog(unsigned int type);
|
||||
bool vf_type_is_interlace(unsigned int type);
|
||||
bool vf_type_is_top(unsigned int type);
|
||||
bool vf_type_is_bottom(unsigned int type);
|
||||
bool vf_type_is_inter_first(unsigned int type);
|
||||
bool vf_type_is_mvc(unsigned int type);
|
||||
bool vf_type_is_no_video_en(unsigned int type);
|
||||
bool vf_type_is_VIU422(unsigned int type);
|
||||
bool vf_type_is_VIU_FIELD(unsigned int type);
|
||||
bool vf_type_is_VIU_SINGLE(unsigned int type);
|
||||
bool vf_type_is_VIU444(unsigned int type);
|
||||
bool vf_type_is_VIUNV21(unsigned int type);
|
||||
bool vf_type_is_vscale_dis(unsigned int type);
|
||||
bool vf_type_is_canvas_toggle(unsigned int type);
|
||||
bool vf_type_is_pre_interlace(unsigned int type);
|
||||
bool vf_type_is_highrun(unsigned int type);
|
||||
bool vf_type_is_compress(unsigned int type);
|
||||
bool vf_type_is_pic(unsigned int type);
|
||||
bool vf_type_is_scatter(unsigned int type);
|
||||
bool vf_type_is_vd2(unsigned int type);
|
||||
|
||||
extern const char * const di_rev_name[4];
|
||||
|
||||
struct vframe_s *pw_vf_get(unsigned int ch);
|
||||
struct vframe_s *pw_vf_peek(unsigned int ch);
|
||||
void pw_vf_put(struct vframe_s *vf, unsigned int ch);
|
||||
int pw_vf_notify_provider(unsigned int channel,
|
||||
int event_type,
|
||||
void *data);
|
||||
int pw_vf_notify_receiver(unsigned int channel,
|
||||
int event_type,
|
||||
void *data);
|
||||
void pw_vf_light_unreg_provider(unsigned int ch);
|
||||
|
||||
void set_bypass2_complete(unsigned int ch, bool on);
|
||||
bool is_bypss_complete(struct dev_vfram_t *pvfm);
|
||||
bool is_bypss2_complete(unsigned int ch);
|
||||
|
||||
#endif /*__DI_VFRAME_H__*/
|
||||
71
drivers/amlogic/media/di_multi/dim_trace.h
Normal file
71
drivers/amlogic/media/di_multi/dim_trace.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/dim_trace.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM dim
|
||||
|
||||
#if !defined(_DIM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _DIM_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
/* single lifecycle events */
|
||||
DECLARE_EVENT_CLASS(di_event_class,
|
||||
TP_PROTO(const char *name, int field_cnt, unsigned long time),
|
||||
TP_ARGS(name, field_cnt, time),
|
||||
TP_STRUCT__entry(
|
||||
__string(name, name)
|
||||
__field(int, field_cnt)
|
||||
__field(unsigned long, time)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__assign_str(name, name);
|
||||
__entry->field_cnt = field_cnt;
|
||||
__entry->time = time;
|
||||
),
|
||||
TP_printk("[%s-%-4dth-%lums]", __get_str(name),
|
||||
__entry->field_cnt, __entry->time)
|
||||
);
|
||||
|
||||
#define DEFINE_DI_EVENT(name) \
|
||||
DEFINE_EVENT(di_event_class, name, \
|
||||
TP_PROTO(const char *name, int field_cnt, unsigned long time), \
|
||||
TP_ARGS(name, field_cnt, time))
|
||||
|
||||
DEFINE_DI_EVENT(dim_pre);
|
||||
DEFINE_DI_EVENT(dim_post);
|
||||
/*2019-06-18*/
|
||||
DEFINE_DI_EVENT(dim_pre_getxx);
|
||||
DEFINE_DI_EVENT(dim_pre_setxx);
|
||||
DEFINE_DI_EVENT(dim_pre_ready);
|
||||
DEFINE_DI_EVENT(dim_pst_ready);
|
||||
DEFINE_DI_EVENT(dim_pst_getxx);
|
||||
DEFINE_DI_EVENT(dim_pst_setxx);
|
||||
DEFINE_DI_EVENT(dim_pst_irxxx);
|
||||
DEFINE_DI_EVENT(dim_pst_doing);
|
||||
DEFINE_DI_EVENT(dim_pst_peekx);
|
||||
DEFINE_DI_EVENT(dim_pst_get2x);
|
||||
|
||||
#endif /* _DIM_TRACE_H */
|
||||
|
||||
#if 0
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE deinterlace_trace
|
||||
#include <trace/define_trace.h>
|
||||
#endif
|
||||
218
drivers/amlogic/media/di_multi/nr_downscale.c
Normal file
218
drivers/amlogic/media/di_multi/nr_downscale.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/nr_downscale.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/amlogic/iomap.h>
|
||||
#include <linux/amlogic/media/canvas/canvas.h>
|
||||
#include <linux/amlogic/media/canvas/canvas_mgr.h>
|
||||
#include "register.h"
|
||||
#include "nr_downscale.h"
|
||||
#include "deinterlace.h"
|
||||
|
||||
#include "di_data_l.h"
|
||||
#include "di_api.h"
|
||||
|
||||
static struct nr_ds_s nrds_dev;
|
||||
|
||||
static void nr_ds_hw_init(unsigned int width, unsigned int height)
|
||||
{
|
||||
unsigned char h_step = 0, v_step = 0;
|
||||
unsigned int width_out, height_out;
|
||||
|
||||
width_out = NR_DS_WIDTH;
|
||||
height_out = NR_DS_HEIGHT;
|
||||
|
||||
h_step = width / width_out;
|
||||
v_step = height / height_out;
|
||||
|
||||
/*Switch MIF to NR_DS*/
|
||||
dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 3, 5, 2);
|
||||
/* config dsbuf_ocol*/
|
||||
dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, width_out, 0, 8);
|
||||
/* config dsbuf_orow*/
|
||||
dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, height_out, 8, 8);
|
||||
|
||||
dim_RDMA_WR_BITS(NRDSWR_X, (width_out - 1), 0, 13);
|
||||
dim_RDMA_WR_BITS(NRDSWR_Y, (height_out - 1), 0, 13);
|
||||
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (height_out - 1), 0, 13);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (width_out - 1), 16, 13);
|
||||
/* little endian */
|
||||
dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, 1, 13, 1);
|
||||
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, v_step, 16, 6);
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, h_step, 24, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* init nr ds buffer
|
||||
*/
|
||||
void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start,
|
||||
struct device *dev)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
bool ret;
|
||||
struct dim_mm_s omm;
|
||||
|
||||
if (cma_flag == 0) {
|
||||
nrds_dev.nrds_addr = mem_start;
|
||||
} else {
|
||||
#if 0
|
||||
nrds_dev.nrds_pages = dma_alloc_from_contiguous(dev,
|
||||
NR_DS_PAGE_NUM, 0);
|
||||
if (nrds_dev.nrds_pages)
|
||||
nrds_dev.nrds_addr = page_to_phys(nrds_dev.nrds_pages);
|
||||
else
|
||||
PR_ERR("DI: alloc nr ds mem error.\n");
|
||||
#else
|
||||
ret = dim_mm_alloc(cma_flag, NR_DS_PAGE_NUM, &omm);
|
||||
if (ret) {
|
||||
nrds_dev.nrds_pages = omm.ppage;
|
||||
nrds_dev.nrds_addr = omm.addr;
|
||||
} else {
|
||||
PR_ERR("alloc nr ds mem error.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < NR_DS_BUF_NUM; i++)
|
||||
nrds_dev.buf[i] = nrds_dev.nrds_addr + (NR_DS_BUF_SIZE * i);
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (cma_flag == 0) {
|
||||
nrds_dev.nrds_addr = 0;
|
||||
} else {
|
||||
if (nrds_dev.nrds_pages) {
|
||||
#if 0
|
||||
dma_release_from_contiguous(dev,
|
||||
nrds_dev.nrds_pages,
|
||||
NR_DS_PAGE_NUM);
|
||||
#else
|
||||
dim_mm_release(cma_flag,
|
||||
nrds_dev.nrds_pages,
|
||||
NR_DS_PAGE_NUM,
|
||||
nrds_dev.nrds_addr);
|
||||
#endif
|
||||
nrds_dev.nrds_addr = 0;
|
||||
nrds_dev.nrds_pages = NULL;
|
||||
} else
|
||||
pr_info("DI: no release nr ds mem.\n");
|
||||
}
|
||||
for (i = 0; i < NR_DS_BUF_NUM; i++)
|
||||
nrds_dev.buf[i] = 0;
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* hw config, alloc canvas
|
||||
*/
|
||||
void dim_nr_ds_init(unsigned int width, unsigned int height)
|
||||
{
|
||||
nr_ds_hw_init(width, height);
|
||||
nrds_dev.field_num = 0;
|
||||
|
||||
if (nrds_dev.canvas_idx != 0)
|
||||
return;
|
||||
|
||||
if (ext_ops.canvas_pool_alloc_canvas_table("nr_ds",
|
||||
&nrds_dev.canvas_idx, 1, CANVAS_MAP_TYPE_1)) {
|
||||
PR_ERR("%s alloc nrds canvas error.\n", __func__);
|
||||
return;
|
||||
}
|
||||
pr_info("%s alloc nrds canvas %u.\n",
|
||||
__func__, nrds_dev.canvas_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* config nr ds mif, switch buffer
|
||||
*/
|
||||
void dim_nr_ds_mif_config(void)
|
||||
{
|
||||
unsigned long mem_addr = 0;
|
||||
|
||||
mem_addr = nrds_dev.buf[nrds_dev.cur_buf_idx];
|
||||
canvas_config(nrds_dev.canvas_idx, mem_addr,
|
||||
NR_DS_WIDTH, NR_DS_HEIGHT, 0, 0);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CTRL,
|
||||
nrds_dev.canvas_idx, 0, 8);
|
||||
dim_nr_ds_hw_ctrl(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* enable/disable nr ds mif&hw
|
||||
*/
|
||||
void dim_nr_ds_hw_ctrl(bool enable)
|
||||
{
|
||||
/*Switch MIF to NR_DS*/
|
||||
dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, enable ? 3 : 2, 5, 2);
|
||||
dim_RDMA_WR_BITS(NRDSWR_CTRL, enable ? 1 : 0, 12, 1);
|
||||
dim_RDMA_WR_BITS(NR_DS_CTRL, enable ? 1 : 0, 30, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* process in irq
|
||||
*/
|
||||
void dim_nr_ds_irq(void)
|
||||
{
|
||||
dim_nr_ds_hw_ctrl(false);
|
||||
nrds_dev.field_num++;
|
||||
nrds_dev.cur_buf_idx++;
|
||||
if (nrds_dev.cur_buf_idx >= NR_DS_BUF_NUM)
|
||||
nrds_dev.cur_buf_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get buf addr&size for dump
|
||||
*/
|
||||
void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size)
|
||||
{
|
||||
*addr = nrds_dev.nrds_addr;
|
||||
*size = NR_DS_BUF_SIZE;
|
||||
pr_info("%s addr 0x%lx, size 0x%lx.\n",
|
||||
__func__, *addr, *size);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x37f9 ~ 0x37fc 0x3740 ~ 0x3743 8 regs
|
||||
*/
|
||||
void dim_dump_nrds_reg(unsigned int base_addr)
|
||||
{
|
||||
unsigned int i = 0x37f9;
|
||||
|
||||
pr_info("-----nrds reg start-----\n");
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (0x2006 << 2), i, dim_RDMA_RD(0x2006));
|
||||
for (i = 0x37f9; i < 0x37fd; i++)
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2), i, dim_RDMA_RD(i));
|
||||
for (i = 0x3740; i < 0x3744; i++)
|
||||
pr_info("[0x%x][0x%x]=0x%x\n",
|
||||
base_addr + (i << 2), i, dim_RDMA_RD(i));
|
||||
pr_info("-----nrds reg end-----\n");
|
||||
}
|
||||
46
drivers/amlogic/media/di_multi/nr_downscale.h
Normal file
46
drivers/amlogic/media/di_multi/nr_downscale.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/nr_downscale.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NR_DS_H
|
||||
#define _NR_DS_H
|
||||
|
||||
#define NR_DS_WIDTH 128
|
||||
#define NR_DS_HEIGHT 96
|
||||
#define NR_DS_BUF_SIZE (96 << 7)
|
||||
#define NR_DS_BUF_NUM 6
|
||||
#define NR_DS_MEM_SIZE (NR_DS_BUF_SIZE * NR_DS_BUF_NUM)
|
||||
#define NR_DS_PAGE_NUM (NR_DS_MEM_SIZE >> PAGE_SHIFT)
|
||||
|
||||
struct nr_ds_s {
|
||||
unsigned int field_num;
|
||||
unsigned long nrds_addr;
|
||||
struct page *nrds_pages;
|
||||
unsigned int canvas_idx;
|
||||
unsigned char cur_buf_idx;
|
||||
unsigned long buf[NR_DS_BUF_NUM];
|
||||
};
|
||||
|
||||
void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start,
|
||||
struct device *dev);
|
||||
void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev);
|
||||
void dim_nr_ds_init(unsigned int width, unsigned int height);
|
||||
void dim_nr_ds_mif_config(void);
|
||||
void dim_nr_ds_hw_ctrl(bool enable);
|
||||
void dim_nr_ds_irq(void);
|
||||
void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size);
|
||||
void dim_dump_nrds_reg(unsigned int base_addr);
|
||||
#endif
|
||||
4416
drivers/amlogic/media/di_multi/register.h
Normal file
4416
drivers/amlogic/media/di_multi/register.h
Normal file
File diff suppressed because it is too large
Load Diff
149
drivers/amlogic/media/di_multi/register_nr4.h
Normal file
149
drivers/amlogic/media/di_multi/register_nr4.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* drivers/amlogic/media/di_multi/register_nr4.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define NR4_DRT_CTRL ((0x2da4))
|
||||
#define NR4_DRT_YSAD_GAIN ((0x2da5))
|
||||
#define NR4_DRT_CSAD_GAIN ((0x2da6))
|
||||
#define NR4_DRT_SAD_ALP_CORE ((0x2da7))
|
||||
#define NR4_DRT_ALP_MINMAX ((0x2da8))
|
||||
#define NR4_SNR_CTRL_REG ((0x2da9))
|
||||
#define NR4_SNR_ALPHA0_MAX_MIN ((0x2daa))
|
||||
#define NR4_ALP0C_ERR2CURV_LIMIT0 ((0x2dab))
|
||||
#define NR4_ALP0C_ERR2CURV_LIMIT1 ((0x2dac))
|
||||
#define NR4_ALP0Y_ERR2CURV_LIMIT0 ((0x2dad))
|
||||
#define NR4_ALP0Y_ERR2CURV_LIMIT1 ((0x2dae))
|
||||
#define NR4_SNR_ALPA1_RATE_AND_OFST ((0x2daf))
|
||||
#define NR4_SNR_ALPHA1_MAX_MIN ((0x2db0))
|
||||
#define NR4_ALP1C_ERR2CURV_LIMIT0 ((0x2db1))
|
||||
#define NR4_ALP1C_ERR2CURV_LIMIT1 ((0x2db2))
|
||||
#define NR4_ALP1Y_ERR2CURV_LIMIT0 ((0x2db3))
|
||||
#define NR4_ALP1Y_ERR2CURV_LIMIT1 ((0x2db4))
|
||||
#define NR4_MTN_CTRL ((0x2db5))
|
||||
#define NR4_MTN_REF_PAR0 ((0x2db6))
|
||||
#define NR4_MTN_REF_PAR1 ((0x2db7))
|
||||
#define NR4_MCNR_LUMA_ENH_CTRL ((0x2db8))
|
||||
#define NR4_MCNR_LUMA_STAT_LIMTX ((0x2db9))
|
||||
#define NR4_MCNR_LUMA_STAT_LIMTY ((0x2dba))
|
||||
#define NR4_MCNR_LUMA_DIF_CALC ((0x2dbb))
|
||||
#define NR4_MCNR_LUMAPRE_CAL_PRAM ((0x2dbc))
|
||||
#define NR4_MCNR_LUMACUR_CAL_PRAM ((0x2dbd))
|
||||
#define NR4_MCNR_MV_CTRL_REG ((0x2dbe))
|
||||
#define NR4_MCNR_MV_GAIN0 ((0x2dbf))
|
||||
#define NR4_MCNR_LMV_PARM ((0x2dc0))
|
||||
#define NR4_MCNR_ALP0_REG (0x2dc1)
|
||||
#define NR4_MCNR_ALP1_AND_BET0_REG (0x2dc2)
|
||||
#define NR4_MCNR_BET1_AND_BET2_REG (0x2dc3)
|
||||
#define NR4_MCNR_AC_DC_CRTL (0x2dc4)
|
||||
#define NR4_MCNR_CM_CTRL0 (0x2dc5)
|
||||
#define NR4_MCNR_CM_PRAM (0x2dc6)
|
||||
#define NR4_MCNR_CM_RSHFT_ALP0 (0x2dc7)
|
||||
#define NR4_MCNR_BLUE_CENT (0x2dc8)
|
||||
#define NR4_MCNR_BLUE_GAIN_PAR0 (0x2dc9)
|
||||
#define NR4_MCNR_BLUE_GAIN_PAR1 (0x2dca)
|
||||
#define NR4_MCNR_CM_BLUE_CLIP0 (0x2dcb)
|
||||
#define NR4_MCNR_CM_BLUE_CLIP1 (0x2dcc)
|
||||
#define NR4_MCNR_GREEN_CENT (0x2dcd)
|
||||
#define NR4_MCNR_GREEN_GAIN_PAR0 (0x2dce)
|
||||
#define NR4_MCNR_GREEN_GAIN_PAR1 (0x2dcf)
|
||||
#define NR4_MCNR_GREEN_CLIP0 (0x2dd0)
|
||||
#define NR4_MCNR_GREEN_CLIP2 (0x2dd1)
|
||||
#define NR4_MCNR_SKIN_CENT (0x2dd2)
|
||||
#define NR4_MCNR_SKIN_GAIN_PAR0 (0x2dd3)
|
||||
#define NR4_MCNR_SKIN_GAIN_PAR1 (0x2dd4)
|
||||
#define NR4_MCNR_SKIN_CLIP0 (0x2dd5)
|
||||
#define NR4_MCNR_SKIN_CLIP1 (0x2dd6)
|
||||
#define NR4_MCNR_ALP1_GLB_CTRL (0x2dd7)
|
||||
#define NR4_MCNR_DC2NORM_LUT0 (0x2dd8)
|
||||
#define NR4_MCNR_DC2NORM_LUT1 (0x2dd9)
|
||||
#define NR4_MCNR_DC2NORM_LUT2 (0x2dda)
|
||||
#define NR4_MCNR_AC2NORM_LUT0 (0x2ddb)
|
||||
#define NR4_MCNR_AC2NORM_LUT1 (0x2ddc)
|
||||
#define NR4_MCNR_AC2NORM_LUT2 (0x2ddd)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT0 (0x2dde)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT1 (0x2ddf)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT2 (0x2de0)
|
||||
#define NR4_MCNR_SAD2ALP0_LUT3 (0x2de1)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT0 (0x2de2)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT1 (0x2de3)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT2 (0x2de4)
|
||||
#define NR4_MCNR_SAD2ALP1_LUT3 (0x2de5)
|
||||
#define NR4_MCNR_SAD2BET0_LUT0 (0x2de6)
|
||||
#define NR4_MCNR_SAD2BET0_LUT1 (0x2de7)
|
||||
#define NR4_MCNR_SAD2BET0_LUT2 (0x2de8)
|
||||
#define NR4_MCNR_SAD2BET0_LUT3 (0x2de9)
|
||||
#define NR4_MCNR_SAD2BET1_LUT0 (0x2dea)
|
||||
#define NR4_MCNR_SAD2BET1_LUT1 (0x2deb)
|
||||
#define NR4_MCNR_SAD2BET1_LUT2 (0x2dec)
|
||||
#define NR4_MCNR_SAD2BET1_LUT3 (0x2ded)
|
||||
#define NR4_MCNR_SAD2BET2_LUT0 (0x2dee)
|
||||
#define NR4_MCNR_SAD2BET2_LUT1 (0x2def)
|
||||
#define NR4_MCNR_SAD2BET2_LUT2 (0x2df0)
|
||||
#define NR4_MCNR_SAD2BET2_LUT3 (0x2df1)
|
||||
#define NR4_MCNR_RO_U_SUM (0x2df2)
|
||||
#define NR4_MCNR_RO_V_SUM (0x2df3)
|
||||
#define NR4_MCNR_RO_GRDU_SUM (0x2df4)
|
||||
#define NR4_MCNR_RO_GRDV_SUM (0x2df5)
|
||||
#define NR4_TOP_CTRL (0x2dff)
|
||||
#define NR4_MCNR_SAD_GAIN (0x3700)
|
||||
#define NR4_MCNR_LPF_CTRL (0x3701)
|
||||
#define NR4_MCNR_BLD_VS3LUT0 (0x3702)
|
||||
#define NR4_MCNR_BLD_VS3LUT1 (0x3703)
|
||||
#define NR4_MCNR_BLD_VS3LUT2 (0x3704)
|
||||
#define NR4_MCNR_BLD_VS2LUT0 (0x3705)
|
||||
#define NR4_MCNR_BLD_VS2LUT1 (0x3706)
|
||||
#define NR4_COEFBLT_LUT10 (0x3707)
|
||||
#define NR4_COEFBLT_LUT11 (0x3708)
|
||||
#define NR4_COEFBLT_LUT12 (0x3709)
|
||||
#define NR4_COEFBLT_LUT20 (0x370a)
|
||||
#define NR4_COEFBLT_LUT21 (0x370b)
|
||||
#define NR4_COEFBLT_LUT22 (0x370c)
|
||||
#define NR4_COEFBLT_LUT30 (0x370d)
|
||||
#define NR4_COEFBLT_LUT31 (0x370e)
|
||||
#define NR4_COEFBLT_LUT32 (0x370f)
|
||||
#define NR4_COEFBLT_CONV (0x3710)
|
||||
#define NR4_DBGWIN_YX0 (0x3711)
|
||||
#define NR4_DBGWIN_YX1 (0x3712)
|
||||
#define NR4_NM_X_CFG (0x3713)
|
||||
#define NR4_NM_Y_CFG (0x3714)
|
||||
#define NR4_NM_SAD_THD (0x3715)
|
||||
#define NR4_MCNR_BANDSPLIT_PRAM (0x3716)
|
||||
#define NR4_MCNR_ALP1_SGN_COR (0x3717)
|
||||
#define NR4_MCNR_ALP1_SGN_PRAM (0x3718)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT1 (0x3719)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT2 (0x371a)
|
||||
#define NR4_MCNR_ALP1_MVX_LUT3 (0x371b)
|
||||
#define NR4_MCNR_ALP1_LP_PRAM (0x371c)
|
||||
#define NR4_MCNR_ALP1_SGN_LUT1 (0x371d)
|
||||
#define NR4_MCNR_ALP1_SGN_LUT2 (0x371e)
|
||||
#define NR4_RO_NM_SAD_SUM (0x371f)
|
||||
#define NR4_RO_NM_SAD_CNT (0x3720)
|
||||
#define NR4_RO_NM_VAR_SUM (0x3721)
|
||||
#define NR4_RO_NM_VAR_SCNT (0x3722)
|
||||
#define NR4_RO_NM_VAR_MIN_MAX (0x3723)
|
||||
#define NR4_RO_NR4_DBGPIX_NUM (0x3724)
|
||||
#define NR4_RO_NR4_BLDVS2_SUM (0x3725)
|
||||
#define NR4_BLDVS3_SUM (0x3726)
|
||||
#define NR4_COEF12_SUM (0x3727)
|
||||
#define NR4_COEF123_SUM (0x3728)
|
||||
#define NR_DB_FLT_CTRL (0x3738)
|
||||
#define NR_DB_FLT_YC_THRD (0x3739)
|
||||
#define NR_DB_FLT_RANDLUT (0x373a)
|
||||
#define NR_DB_FLT_PXI_THRD (0x373b)
|
||||
#define NR_DB_FLT_SEED_Y (0x373c)
|
||||
#define NR_DB_FLT_SEED_V (0x373e)
|
||||
#define NR_DB_FLT_SEED3 (0x373f)
|
||||
#define LBUF_TOP_CTRL (0x2fff)
|
||||
@@ -1204,23 +1204,23 @@ static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode)
|
||||
sys.demod_clk = Demod_Clk_200M;
|
||||
demod_status.tmp = Adc_mode;
|
||||
} else {
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
sys.demod_clk = Demod_Clk_72M;
|
||||
demod_status.tmp = Cry_mode;
|
||||
}
|
||||
|
||||
if (is_ic_ver(IC_VER_TL1)) {
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
/*for timeshift mosaic issue,already fixed with tm2*/
|
||||
sys.demod_clk = Demod_Clk_167M;
|
||||
demod_status.tmp = Cry_mode;
|
||||
} else if (is_ic_ver(IC_VER_TM2)) {
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
sys.demod_clk = Demod_Clk_250M;
|
||||
demod_status.tmp = Cry_mode;
|
||||
}
|
||||
|
||||
demod_status.ch_if = Si2176_5M_If * 1000;
|
||||
demod_status.ch_if = SI2176_5M_IF * 1000;
|
||||
PR_DBG("[%s]adc_clk is %d,demod_clk is %d\n", __func__, sys.adc_clk,
|
||||
sys.demod_clk);
|
||||
autoFlagsTrig = 0;
|
||||
@@ -1404,9 +1404,9 @@ int Gxtv_Demod_Dvbt_Init(void)
|
||||
|
||||
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
|
||||
demod_status.dvb_mode = Gxtv_Dvbt_Isdbt;
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
sys.demod_clk = Demod_Clk_60M;
|
||||
demod_status.ch_if = Si2176_5M_If * 1000;
|
||||
demod_status.ch_if = SI2176_5M_IF * 1000;
|
||||
|
||||
demod_set_sys(&demod_status, &sys);
|
||||
demod_mode_para = AML_DVBT;
|
||||
@@ -1742,7 +1742,7 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe)
|
||||
else
|
||||
atsc_write_reg_v4(ATSC_DEMOD_REG_0X56, 0x0);
|
||||
|
||||
if (demod_status.adc_freq == Adc_Clk_24M) {
|
||||
if (demod_status.adc_freq == ADC_CLK_24M) {
|
||||
atsc_write_reg_v4(ATSC_DEMOD_REG_0X54,
|
||||
0x1aaaaa);
|
||||
|
||||
@@ -2184,7 +2184,7 @@ int Gxtv_Demod_Atsc_Init(void/*struct aml_fe_dev *dev*/)
|
||||
memset(&demod_status, 0, sizeof(demod_status));
|
||||
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
|
||||
demod_status.dvb_mode = Gxtv_Atsc;
|
||||
sys.adc_clk = Adc_Clk_24M; /*Adc_Clk_26M;*/
|
||||
sys.adc_clk = ADC_CLK_24M; /*Adc_Clk_26M;*/
|
||||
if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2))
|
||||
sys.demod_clk = Demod_Clk_250M;
|
||||
else
|
||||
@@ -2551,6 +2551,11 @@ static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe)
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct aml_demod_dtmb param;
|
||||
int times;
|
||||
/*[0]: specturm inverse(1),normal(0); [1]:if_frequency*/
|
||||
unsigned int tuner_freq[2] = {0};
|
||||
|
||||
if (!demod_thread)
|
||||
return 0;
|
||||
|
||||
times = 2;
|
||||
PR_DBG("gxtv_demod_dtmb_set_frontend,freq is %d\n", c->frequency);
|
||||
@@ -2563,6 +2568,17 @@ static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe)
|
||||
msleep(100);
|
||||
/* demod_power_switch(PWR_ON); */
|
||||
|
||||
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
|
||||
if (fe->ops.tuner_ops.get_if_frequency)
|
||||
fe->ops.tuner_ops.get_if_frequency(fe, tuner_freq);
|
||||
if (tuner_freq[0] == 0)
|
||||
demod_status.spectrum = 0;
|
||||
else if (tuner_freq[0] == 1)
|
||||
demod_status.spectrum = 1;
|
||||
else
|
||||
pr_err("wrong specturm val get from tuner\n");
|
||||
}
|
||||
|
||||
dtmb_set_ch(&demod_status, /*&demod_i2c,*/ ¶m);
|
||||
|
||||
return 0;
|
||||
@@ -2596,10 +2612,10 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev)
|
||||
sys.adc_clk = Adc_Clk_25M;
|
||||
sys.demod_clk = Demod_Clk_225M;
|
||||
} else if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) {
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
sys.demod_clk = Demod_Clk_250M;
|
||||
} else {
|
||||
sys.adc_clk = Adc_Clk_24M;
|
||||
sys.adc_clk = ADC_CLK_24M;
|
||||
sys.demod_clk = Demod_Clk_225M;
|
||||
}
|
||||
} else {
|
||||
@@ -2607,7 +2623,7 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
demod_status.ch_if = Si2176_5M_If;
|
||||
demod_status.ch_if = SI2176_5M_IF;
|
||||
demod_status.tmp = Adc_mode;
|
||||
demod_status.spectrum = dev->spectrum;
|
||||
/*demod_set_sys(&demod_status, &i2c, &sys);*/
|
||||
|
||||
@@ -827,15 +827,14 @@ int cci_run(void)
|
||||
|
||||
int cfo_run(void)
|
||||
{
|
||||
int crRate0, crRate1, crRate2, crRate;
|
||||
int Fcent, Fs;
|
||||
int cfo_sta, cr_peak_sta;
|
||||
int i, j;
|
||||
int cr_rate0, cr_rate1, cr_rate2, cr_rate;
|
||||
int f_cent = SI2176_5M_IF * 1000;/* if */
|
||||
int fs = ADC_CLK_24M;/* crystal */
|
||||
int cfo_sta = UNLOCK, cr_peak_sta = UNLOCK;
|
||||
unsigned int i, j;
|
||||
int sys_state;
|
||||
int table_count;
|
||||
int max_count;
|
||||
int freq_table[] = {0, -50, 50, -100, 100, -150, 150};
|
||||
int scan_range;
|
||||
int Offset;
|
||||
int detec_cfo_times = 3;
|
||||
|
||||
@@ -846,34 +845,35 @@ int cfo_run(void)
|
||||
max_count = 5;
|
||||
else
|
||||
max_count = 7;
|
||||
/*for field test do 3 times*/
|
||||
|
||||
/* for field test do 3 times */
|
||||
if (field_test_version) {
|
||||
max_count = 1;
|
||||
detec_cfo_times = 20;
|
||||
}
|
||||
Fcent = Si2176_5M_If*1000;/*if*/
|
||||
Fs = Adc_Clk_24M;/*crystal*/
|
||||
cfo_sta = 0;
|
||||
cr_peak_sta = 0;
|
||||
table_count = 0;
|
||||
scan_range = 10;
|
||||
Offset = freq_table[table_count];
|
||||
PR_ATSC("Fcent[%d], Fs[%d]\n", Fcent, Fs);
|
||||
for (i = -(scan_range-1); i <= scan_range+1; i++) {
|
||||
|
||||
PR_ATSC("Fcent[%d], Fs[%d]\n", f_cent, fs);
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (i > (max_count - 1))
|
||||
return CFO_FAIL;
|
||||
|
||||
Offset = freq_table[i];
|
||||
atsc_reset();
|
||||
cfo_sta = UnLock;
|
||||
cr_peak_sta = UnLock;
|
||||
crRate = (1<<10)*(Fcent+Offset)/Fs;
|
||||
crRate *= (1<<13);
|
||||
crRate0 = crRate&0xff;
|
||||
crRate1 = (crRate>>8)&0xff;
|
||||
crRate2 = (crRate>>16)&0xff;
|
||||
cfo_sta = UNLOCK;
|
||||
cr_peak_sta = UNLOCK;
|
||||
cr_rate = (1 << 10) * (f_cent + Offset) / fs;
|
||||
cr_rate *= (1 << 13);
|
||||
cr_rate0 = cr_rate & 0xff;
|
||||
cr_rate1 = (cr_rate >> 8) & 0xff;
|
||||
cr_rate2 = (cr_rate >> 16) & 0xff;
|
||||
/*set ddc init*/
|
||||
atsc_write_reg(0x70e, crRate0);
|
||||
atsc_write_reg(0x70d, crRate1);
|
||||
atsc_write_reg(0x70c, crRate2);
|
||||
atsc_write_reg(0x70e, cr_rate0);
|
||||
atsc_write_reg(0x70d, cr_rate1);
|
||||
atsc_write_reg(0x70c, cr_rate2);
|
||||
PR_ATSC("[autoscan]crRate is %x, Offset is %dkhz\n ",
|
||||
crRate, Offset);
|
||||
cr_rate, Offset);
|
||||
|
||||
/*detec cfo signal*/
|
||||
for (j = 0; j < detec_cfo_times; j++) {
|
||||
sys_state = read_atsc_fsm();
|
||||
@@ -886,18 +886,18 @@ int cfo_run(void)
|
||||
}
|
||||
msleep(20);
|
||||
}
|
||||
PR_ATSC("fsm[%x]cfo_sta is %d\n",
|
||||
read_atsc_fsm(), cfo_sta);
|
||||
PR_ATSC("fsm[%x]cfo_sta is %d\n", read_atsc_fsm(), cfo_sta);
|
||||
|
||||
/*detec cr peak signal*/
|
||||
if (cfo_sta == Lock) {
|
||||
for (j = 0; j < cfo_times; j++) {
|
||||
sys_state = read_atsc_fsm();
|
||||
PR_ATSC("fsm[%x]in CR LOCK\n", read_atsc_fsm());
|
||||
PR_ATSC("fsm[%x]in CR LOCK\n",
|
||||
read_atsc_fsm());
|
||||
/*sys_state = (sys_state >> 4) & 0x0f;*/
|
||||
if (sys_state >= CR_Peak_Lock) {
|
||||
cr_peak_sta = Lock;
|
||||
PR_ATSC(
|
||||
"fsm[%x][autoscan]cr peak lock\n",
|
||||
PR_ATSC("fsm[0x%x]cr peak lock\n",
|
||||
read_atsc_fsm());
|
||||
break;
|
||||
} else if (sys_state <= 20) {
|
||||
@@ -906,13 +906,9 @@ int cfo_run(void)
|
||||
}
|
||||
msleep(20);
|
||||
}
|
||||
} else {
|
||||
if (table_count >= (max_count-1))
|
||||
break;
|
||||
table_count++;
|
||||
Offset = freq_table[table_count];
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
/*reset*/
|
||||
if (cr_peak_sta == Lock) {
|
||||
/*atsc_reset();*/
|
||||
@@ -920,17 +916,9 @@ int cfo_run(void)
|
||||
read_atsc_fsm());
|
||||
return Cfo_Ok;
|
||||
|
||||
} else {
|
||||
if (table_count >= (max_count-1)) {
|
||||
PR_ATSC("cfo not lock,will try again\n");
|
||||
return Cfo_Fail;
|
||||
|
||||
}
|
||||
table_count++;
|
||||
Offset = freq_table[table_count];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1124,7 +1112,7 @@ void atsc_thread(void)
|
||||
time_table[1] = (time[2] - time[1]);
|
||||
PR_ATSC("fsm[%x][atsc_time]cfo done,cost %d ms,\n",
|
||||
read_atsc_fsm(), time_table[1]);
|
||||
if (ret == Cfo_Fail)
|
||||
if (ret == CFO_FAIL)
|
||||
return;
|
||||
if (cci_enable)
|
||||
ret = cci_run();
|
||||
|
||||
@@ -133,7 +133,7 @@ void adc_dpll_setup(int clk_a, int clk_b, int clk_sys, int dvb_mode)
|
||||
int sts_pll;
|
||||
|
||||
if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) {
|
||||
if (clk_b == Adc_Clk_24M) {
|
||||
if (clk_b == ADC_CLK_24M) {
|
||||
dtvpll_init_flag(1);
|
||||
return;
|
||||
} else if (clk_b == Adc_Clk_25M) {
|
||||
|
||||
@@ -94,9 +94,87 @@ void dtmb_clk_set(unsigned int adc_clk)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dtmb_24m_coeff(void)
|
||||
{
|
||||
#if 0
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0xf230ee02);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x0be241ed);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x0306031d);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x051d191c);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x171a0308);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x0b071d);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x3d333703);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x33030f0a);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x140f3c2f);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x292d04);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x041c177c);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x247c5e64);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x2b);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xc8d104);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x0431fc);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x51);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x392004);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x372);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x1187fc);
|
||||
dtmb_write_reg(DTMB_FRONT_ACF_BYPASS,
|
||||
((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff)
|
||||
| 0x2af236));
|
||||
#else
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0xebd2530d);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x04dad364);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x181e0508);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x080a031a);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x0217161f);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x000c0c);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x0e3f3334);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x2e330310);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x08160f3c);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x352731);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x70101f11);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x2d126b5c);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x1f);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xd4c8ef);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x04e013);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x46);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x3883ee);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x37e);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x123013);
|
||||
dtmb_write_reg(DTMB_FRONT_ACF_BYPASS,
|
||||
((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff)
|
||||
| 0x29922b));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dtmb_25m_coeff(void)
|
||||
{
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0x242fde12);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x451dce);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x051f1a1b);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x181c0307);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x0809031b);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x15161f);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x060e0a3e);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x06363038);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x2d3e0f12);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x133c2b);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x5f700c1b);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x23270b6a);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x7e);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xf3cbd4);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x04f031);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x29);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x37f3cc);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x396);
|
||||
dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x131036);
|
||||
dtmb_write_reg(DTMB_FRONT_ACF_BYPASS,
|
||||
((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff)
|
||||
| 0x274217));
|
||||
}
|
||||
|
||||
void dtmb_all_reset(void)
|
||||
{
|
||||
int temp_data = 0;
|
||||
unsigned int reg_val;
|
||||
|
||||
if (is_ic_ver(IC_VER_TXL)) {
|
||||
/*fix bug 139044: DTMB lost sync*/
|
||||
@@ -139,22 +217,41 @@ void dtmb_all_reset(void)
|
||||
/*fix agc problem,skip warm_up status*/
|
||||
dtmb_write_reg(DTMB_FRONT_46_CONFIG, 0x1a000f0f);
|
||||
dtmb_write_reg(DTMB_FRONT_ST_FREQ, 0xf2400000);
|
||||
dtmb_clk_set(Adc_Clk_24M);
|
||||
dtmb_clk_set(ADC_CLK_24M);
|
||||
} else if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) {
|
||||
if (demod_get_adc_clk() == Adc_Clk_24M) {
|
||||
if (demod_get_adc_clk() == ADC_CLK_24M) {
|
||||
dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, 0x6aaaaa);
|
||||
dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, 0x13196596);
|
||||
dtmb_write_reg(0x5b << 2, 0x50a30a25);
|
||||
dtmb_24m_coeff();
|
||||
} else if (demod_get_adc_clk() == Adc_Clk_25M) {
|
||||
dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, 0x62c1a5);
|
||||
dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, 0x131a747d);
|
||||
dtmb_write_reg(0x5b << 2, 0x4d6a0a25);
|
||||
dtmb_25m_coeff();
|
||||
}
|
||||
|
||||
/*for timeshift mosaic issue*/
|
||||
dtmb_write_reg(0x4e << 2, 0x256cf604);
|
||||
/*delay fec lock to prevent eq is confused by signal*/
|
||||
dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x5680000);
|
||||
/*for timeshift mosaic issue
|
||||
*bit 30:ts_sync_sel,0=ts_sync,1=searched ts_sync
|
||||
*/
|
||||
dtmb_write_reg(DTMB_FRONT_4e_CONFIG, 0x656cf604);
|
||||
|
||||
/*delay fec lock & make fec lost faster
|
||||
*to prevent eq is confused by signal
|
||||
*/
|
||||
dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x5480000);
|
||||
/*reduce fec lost timeout*/
|
||||
dtmb_write_reg(DTMB_FRONT_19_CONFIG, 0x30);
|
||||
|
||||
reg_val = dtmb_read_reg(DTMB_TOP_CTRL_TPS);
|
||||
/* for Task 19:Switch mode and modulation parameters test
|
||||
* dtmb_spectrum: 0=normal, 1=inverted
|
||||
*/
|
||||
if (dtmb_spectrum == 0)
|
||||
reg_val |= 0x4;
|
||||
else if (dtmb_spectrum == 1)
|
||||
reg_val &= ~0x4;
|
||||
dtmb_write_reg(DTMB_TOP_CTRL_TPS, reg_val);
|
||||
} else {
|
||||
dtmb_write_reg(DTMB_FRONT_AGC_CONFIG1, 0x10127);
|
||||
dtmb_write_reg(DTMB_CHE_IBDFE_CONFIG6, 0x943228cc);
|
||||
|
||||
@@ -22,47 +22,48 @@
|
||||
|
||||
#define DTMB_FRONT_ADDR(x) (DTMB_DEMOD_BASE + (x << 2))
|
||||
|
||||
#define DTMB_FRONT_AFIFO_ADC DTMB_FRONT_ADDR(0x20)
|
||||
#define DTMB_FRONT_AGC_CONFIG1 DTMB_FRONT_ADDR(0x21)
|
||||
#define DTMB_FRONT_AGC_CONFIG2 DTMB_FRONT_ADDR(0x22)
|
||||
#define DTMB_FRONT_AGC_CONFIG3 DTMB_FRONT_ADDR(0x23)
|
||||
#define DTMB_FRONT_AGC_CONFIG4 DTMB_FRONT_ADDR(0x24)
|
||||
#define DTMB_FRONT_DDC_BYPASS DTMB_FRONT_ADDR(0x25)
|
||||
#define DTMB_FRONT_DC_HOLD DTMB_FRONT_ADDR(0x28)
|
||||
#define DTMB_FRONT_DAGC_TARGET_POWER DTMB_FRONT_ADDR(0x29)
|
||||
#define DTMB_FRONT_ACF_BYPASS DTMB_FRONT_ADDR(0x2a)
|
||||
#define DTMB_FRONT_COEF_SET1 DTMB_FRONT_ADDR(0x2b)
|
||||
#define DTMB_FRONT_COEF_SET2 DTMB_FRONT_ADDR(0x2c)
|
||||
#define DTMB_FRONT_COEF_SET3 DTMB_FRONT_ADDR(0x2d)
|
||||
#define DTMB_FRONT_COEF_SET4 DTMB_FRONT_ADDR(0x2e)
|
||||
#define DTMB_FRONT_COEF_SET5 DTMB_FRONT_ADDR(0x2f)
|
||||
#define DTMB_FRONT_COEF_SET6 DTMB_FRONT_ADDR(0x30)
|
||||
#define DTMB_FRONT_COEF_SET7 DTMB_FRONT_ADDR(0x31)
|
||||
#define DTMB_FRONT_COEF_SET8 DTMB_FRONT_ADDR(0x32)
|
||||
#define DTMB_FRONT_COEF_SET9 DTMB_FRONT_ADDR(0x33)
|
||||
#define DTMB_FRONT_COEF_SET10 DTMB_FRONT_ADDR(0x34)
|
||||
#define DTMB_FRONT_COEF_SET11 DTMB_FRONT_ADDR(0x35)
|
||||
#define DTMB_FRONT_COEF_SET12 DTMB_FRONT_ADDR(0x36)
|
||||
#define DTMB_FRONT_COEF_SET13 DTMB_FRONT_ADDR(0x37)
|
||||
#define DTMB_FRONT_COEF_SET14 DTMB_FRONT_ADDR(0x38)
|
||||
#define DTMB_FRONT_COEF_SET15 DTMB_FRONT_ADDR(0x39)
|
||||
#define DTMB_FRONT_COEF_SET16 DTMB_FRONT_ADDR(0x3a)
|
||||
#define DTMB_FRONT_COEF_SET17 DTMB_FRONT_ADDR(0x3b)
|
||||
#define DTMB_FRONT_COEF_SET18 DTMB_FRONT_ADDR(0x3c)
|
||||
#define DTMB_FRONT_COEF_SET19 DTMB_FRONT_ADDR(0x3d)
|
||||
#define DTMB_FRONT_SRC_CONFIG1 DTMB_FRONT_ADDR(0x3e)
|
||||
#define DTMB_FRONT_SRC_CONFIG2 DTMB_FRONT_ADDR(0x3f)
|
||||
#define DTMB_FRONT_SFIFO_OUT_LEN DTMB_FRONT_ADDR(0x40)
|
||||
#define DTMB_FRONT_DAGC_GAIN DTMB_FRONT_ADDR(0x41)
|
||||
#define DTMB_FRONT_IQIB_STEP DTMB_FRONT_ADDR(0x42)
|
||||
#define DTMB_FRONT_IQIB_CONFIG DTMB_FRONT_ADDR(0x43)
|
||||
#define DTMB_FRONT_ST_CONFIG DTMB_FRONT_ADDR(0x44)
|
||||
#define DTMB_FRONT_ST_FREQ DTMB_FRONT_ADDR(0x45)
|
||||
#define DTMB_FRONT_46_CONFIG DTMB_FRONT_ADDR(0x46)
|
||||
#define DTMB_FRONT_47_CONFIG DTMB_FRONT_ADDR(0x47)
|
||||
#define DTMB_FRONT_DEBUG_CFG DTMB_FRONT_ADDR(0x48)
|
||||
#define DTMB_FRONT_MEM_ADDR DTMB_FRONT_ADDR(0x49)
|
||||
#define DTMB_FRONT_19_CONFIG DTMB_FRONT_ADDR(0x19)
|
||||
#define DTMB_FRONT_4d_CONFIG DTMB_FRONT_ADDR(0x4d)
|
||||
#define DTMB_FRONT_19_CONFIG DTMB_FRONT_ADDR(0x19)
|
||||
#define DTMB_FRONT_AFIFO_ADC DTMB_FRONT_ADDR(0x20)
|
||||
#define DTMB_FRONT_AGC_CONFIG1 DTMB_FRONT_ADDR(0x21)
|
||||
#define DTMB_FRONT_AGC_CONFIG2 DTMB_FRONT_ADDR(0x22)
|
||||
#define DTMB_FRONT_AGC_CONFIG3 DTMB_FRONT_ADDR(0x23)
|
||||
#define DTMB_FRONT_AGC_CONFIG4 DTMB_FRONT_ADDR(0x24)
|
||||
#define DTMB_FRONT_DDC_BYPASS DTMB_FRONT_ADDR(0x25)
|
||||
#define DTMB_FRONT_DC_HOLD DTMB_FRONT_ADDR(0x28)
|
||||
#define DTMB_FRONT_DAGC_TARGET_POWER DTMB_FRONT_ADDR(0x29)
|
||||
#define DTMB_FRONT_ACF_BYPASS DTMB_FRONT_ADDR(0x2a)
|
||||
#define DTMB_FRONT_COEF_SET1 DTMB_FRONT_ADDR(0x2b)
|
||||
#define DTMB_FRONT_COEF_SET2 DTMB_FRONT_ADDR(0x2c)
|
||||
#define DTMB_FRONT_COEF_SET3 DTMB_FRONT_ADDR(0x2d)
|
||||
#define DTMB_FRONT_COEF_SET4 DTMB_FRONT_ADDR(0x2e)
|
||||
#define DTMB_FRONT_COEF_SET5 DTMB_FRONT_ADDR(0x2f)
|
||||
#define DTMB_FRONT_COEF_SET6 DTMB_FRONT_ADDR(0x30)
|
||||
#define DTMB_FRONT_COEF_SET7 DTMB_FRONT_ADDR(0x31)
|
||||
#define DTMB_FRONT_COEF_SET8 DTMB_FRONT_ADDR(0x32)
|
||||
#define DTMB_FRONT_COEF_SET9 DTMB_FRONT_ADDR(0x33)
|
||||
#define DTMB_FRONT_COEF_SET10 DTMB_FRONT_ADDR(0x34)
|
||||
#define DTMB_FRONT_COEF_SET11 DTMB_FRONT_ADDR(0x35)
|
||||
#define DTMB_FRONT_COEF_SET12 DTMB_FRONT_ADDR(0x36)
|
||||
#define DTMB_FRONT_COEF_SET13 DTMB_FRONT_ADDR(0x37)
|
||||
#define DTMB_FRONT_COEF_SET14 DTMB_FRONT_ADDR(0x38)
|
||||
#define DTMB_FRONT_COEF_SET15 DTMB_FRONT_ADDR(0x39)
|
||||
#define DTMB_FRONT_COEF_SET16 DTMB_FRONT_ADDR(0x3a)
|
||||
#define DTMB_FRONT_COEF_SET17 DTMB_FRONT_ADDR(0x3b)
|
||||
#define DTMB_FRONT_COEF_SET18 DTMB_FRONT_ADDR(0x3c)
|
||||
#define DTMB_FRONT_COEF_SET19 DTMB_FRONT_ADDR(0x3d)
|
||||
#define DTMB_FRONT_SRC_CONFIG1 DTMB_FRONT_ADDR(0x3e)
|
||||
#define DTMB_FRONT_SRC_CONFIG2 DTMB_FRONT_ADDR(0x3f)
|
||||
#define DTMB_FRONT_SFIFO_OUT_LEN DTMB_FRONT_ADDR(0x40)
|
||||
#define DTMB_FRONT_DAGC_GAIN DTMB_FRONT_ADDR(0x41)
|
||||
#define DTMB_FRONT_IQIB_STEP DTMB_FRONT_ADDR(0x42)
|
||||
#define DTMB_FRONT_IQIB_CONFIG DTMB_FRONT_ADDR(0x43)
|
||||
#define DTMB_FRONT_ST_CONFIG DTMB_FRONT_ADDR(0x44)
|
||||
#define DTMB_FRONT_ST_FREQ DTMB_FRONT_ADDR(0x45)
|
||||
#define DTMB_FRONT_46_CONFIG DTMB_FRONT_ADDR(0x46)
|
||||
#define DTMB_FRONT_47_CONFIG DTMB_FRONT_ADDR(0x47)
|
||||
#define DTMB_FRONT_DEBUG_CFG DTMB_FRONT_ADDR(0x48)
|
||||
#define DTMB_FRONT_MEM_ADDR DTMB_FRONT_ADDR(0x49)
|
||||
#define DTMB_FRONT_4d_CONFIG DTMB_FRONT_ADDR(0x4d)
|
||||
#define DTMB_FRONT_4e_CONFIG DTMB_FRONT_ADDR(0x4e)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,8 +29,8 @@ struct amlfe_config {
|
||||
int tuner_addr;
|
||||
};
|
||||
enum Gxtv_Demod_Tuner_If {
|
||||
Si2176_5M_If = 5,
|
||||
Si2176_6M_If = 6
|
||||
SI2176_5M_IF = 5,
|
||||
SI2176_6M_IF = 6
|
||||
};
|
||||
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC */
|
||||
enum Gxtv_Demod_Dvb_Mode {
|
||||
@@ -54,7 +54,7 @@ enum demod_md {
|
||||
#define Adc_Clk_35M 35714 /* adc clk dvbc */
|
||||
#define Demod_Clk_71M 71428 /* demod clk */
|
||||
|
||||
#define Adc_Clk_24M 24000
|
||||
#define ADC_CLK_24M 24000
|
||||
#define Demod_Clk_72M 72000
|
||||
#define Demod_Clk_60M 60000
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ enum atsc_performance {
|
||||
};
|
||||
|
||||
#define Lock 1
|
||||
#define UnLock 0
|
||||
#define UNLOCK 0
|
||||
#define Cfo_Ok 1
|
||||
#define Cfo_Fail 0
|
||||
#define CFO_FAIL 0
|
||||
#define Dagc_Open 1
|
||||
#define Dagc_Close 0
|
||||
#define Atsc_BandWidth (6000)
|
||||
|
||||
@@ -503,6 +503,7 @@ static int pts_checkin_offset_inline(u8 type, u32 offset, u32 val, u64 uS64)
|
||||
#ifdef CALC_CACHED_TIME
|
||||
pts_checkin_offset_calc_cached(offset, val, pTable);
|
||||
#endif
|
||||
timestamp_clac_pts_latency(type, val);
|
||||
|
||||
list_move_tail(&rec->list, &pTable->valid_list);
|
||||
|
||||
@@ -515,7 +516,7 @@ static int pts_checkin_offset_inline(u8 type, u32 offset, u32 val, u64 uS64)
|
||||
if (tsync_get_debug_apts() && (type == PTS_TYPE_AUDIO))
|
||||
pr_info("init apts[%d] at 0x%x\n", type, val);
|
||||
|
||||
if (type == PTS_TYPE_VIDEO)
|
||||
if (type == PTS_TYPE_VIDEO && !tsync_get_tunnel_mode())
|
||||
timestamp_vpts_set(val);
|
||||
else if (type == PTS_TYPE_AUDIO)
|
||||
timestamp_apts_set(val);
|
||||
@@ -566,7 +567,8 @@ int pts_checkin_wrptr(u8 type, u32 ptr, u32 val)
|
||||
get_wrpage_offset(type, &page, &cur_offset);
|
||||
|
||||
page_no = (offset > cur_offset) ? (page - 1) : page;
|
||||
|
||||
if (type == PTS_TYPE_VIDEO)
|
||||
val += tsync_get_vpts_adjust();
|
||||
return pts_checkin_offset(type,
|
||||
pts_table[type].buf_size * page_no + offset,
|
||||
val);
|
||||
|
||||
@@ -43,6 +43,8 @@ static u32 first_apts;
|
||||
static u32 pcrscr_lantcy = 200*90;
|
||||
static u32 video_pts;
|
||||
static u32 audio_pts;
|
||||
static u32 last_apts_gap;
|
||||
static u32 last_vpts_gap;
|
||||
|
||||
static u32 system_time_scale_base = 1;
|
||||
static u32 system_time_scale_remainder;
|
||||
@@ -123,7 +125,7 @@ EXPORT_SYMBOL(timestamp_apts_started);
|
||||
|
||||
u32 timestamp_pcrscr_get(void)
|
||||
{
|
||||
if (tsync_get_mode() == TSYNC_MODE_AMASTER)
|
||||
if (tsync_get_mode() != TSYNC_MODE_PCRMASTER)
|
||||
return system_time;
|
||||
|
||||
if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb()) {
|
||||
@@ -150,6 +152,8 @@ void timestamp_set_pcrlatency(u32 latency)
|
||||
{
|
||||
if (latency < 500 * 90)
|
||||
pcrscr_lantcy = latency;
|
||||
else
|
||||
pcrscr_lantcy = 500 * 90;
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_set_pcrlatency);
|
||||
|
||||
@@ -159,6 +163,102 @@ u32 timestamp_get_pcrlatency(void)
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_get_pcrlatency);
|
||||
|
||||
void timestamp_clac_pts_latency(u8 type, u32 pts)
|
||||
{
|
||||
u32 demux_pcr = 0;
|
||||
u32 t1, t2, pts_diff;
|
||||
|
||||
if (tsync_get_mode() != TSYNC_MODE_PCRMASTER)
|
||||
return;
|
||||
if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb()
|
||||
&& tsync_pcr_demux_pcr_used()) {
|
||||
if (tsdemux_pcrscr_get_cb)
|
||||
demux_pcr = tsdemux_pcrscr_get_cb();
|
||||
else
|
||||
return;
|
||||
if (demux_pcr == 0 ||
|
||||
demux_pcr == 0xffffffff) {
|
||||
last_apts_gap = 0;
|
||||
last_vpts_gap = 0;
|
||||
return;
|
||||
}
|
||||
if (type == 0) {
|
||||
if (demux_pcr > pts) {
|
||||
last_vpts_gap = 0;
|
||||
return;
|
||||
}
|
||||
pts_diff = pts - demux_pcr;
|
||||
if (pts_diff > 500 * 90)
|
||||
return;
|
||||
t1 = ((last_vpts_gap >> 16) & 0xff);
|
||||
if (t1 > 5)
|
||||
t1 = 0;
|
||||
t2 = (last_vpts_gap & 0xffff);
|
||||
if (t2 == 0) {
|
||||
last_vpts_gap = pts_diff;
|
||||
return;
|
||||
}
|
||||
if (abs(t2 - pts_diff) < 30 * 90) {
|
||||
last_vpts_gap = t2;
|
||||
return;
|
||||
}
|
||||
t1++;
|
||||
if (t1 >= 5)
|
||||
last_vpts_gap = pts_diff;
|
||||
else
|
||||
last_vpts_gap = ((t1 << 16) | t2);
|
||||
} else if (type == 1) {
|
||||
if (demux_pcr > pts) {
|
||||
last_apts_gap = 0;
|
||||
return;
|
||||
}
|
||||
pts_diff = pts - demux_pcr;
|
||||
if (pts_diff > 500 * 90)
|
||||
return;
|
||||
t1 = ((last_apts_gap >> 16) & 0xff);
|
||||
if (t1 > 5)
|
||||
t1 = 0;
|
||||
t2 = (last_apts_gap & 0xffff);
|
||||
if (t2 == 0) {
|
||||
last_apts_gap = pts_diff;
|
||||
return;
|
||||
}
|
||||
if (abs(t2 - pts_diff) < 30 * 90) {
|
||||
last_apts_gap = t2;
|
||||
return;
|
||||
}
|
||||
t1++;
|
||||
if (t1 >= 5)
|
||||
last_apts_gap = pts_diff;
|
||||
else
|
||||
last_apts_gap = ((t1 << 16) | t2);
|
||||
}
|
||||
} else {
|
||||
last_apts_gap = 0;
|
||||
last_vpts_gap = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_clac_pts_latency);
|
||||
|
||||
u32 timestamp_get_pts_latency(u8 type)
|
||||
{
|
||||
if (type == 0)
|
||||
return (last_vpts_gap & 0xffff);
|
||||
else if (type == 1)
|
||||
return (last_apts_gap & 0xffff);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_get_pts_latency);
|
||||
|
||||
void timestamp_clean_pts_latency(u8 type)
|
||||
{
|
||||
if (type == 0)
|
||||
last_vpts_gap = 0;
|
||||
else if (type == 1)
|
||||
last_apts_gap = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_clean_pts_latency);
|
||||
|
||||
u32 timestamp_tsdemux_pcr_get(void)
|
||||
{
|
||||
if (tsdemux_pcrscr_get_cb)
|
||||
@@ -193,6 +293,7 @@ void timestamp_checkin_firstvpts_set(u32 pts)
|
||||
{
|
||||
first_checkin_vpts = pts;
|
||||
pr_info("video first checkin pts = %x\n", first_checkin_vpts);
|
||||
timestamp_clean_pts_latency(0);
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_checkin_firstvpts_set);
|
||||
|
||||
@@ -200,6 +301,7 @@ void timestamp_checkin_firstapts_set(u32 pts)
|
||||
{
|
||||
first_checkin_apts = pts;
|
||||
pr_info("audio first checkin pts =%x\n", first_checkin_apts);
|
||||
timestamp_clean_pts_latency(1);
|
||||
}
|
||||
EXPORT_SYMBOL(timestamp_checkin_firstapts_set);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user