blob: 49d97a4ee1eb59a081ca2b665eb3f015fdeb609b [file] [log] [blame]
/*
* drivers/amlogic/media/deinterlace/film_mode_fmw/flm_mod_xx.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/module.h>
#include "film_vof_soft.h"
/* dif02 < (size >> sft) => static */
int flm2224_stl_sft = 7; /*10*/
module_param(flm2224_stl_sft, int, 0644);
MODULE_PARM_DESC(flm2224_stl_sft, "flm2224_stl_sft");
int aMax02[15]; /* maximum 4 */
int aXId02[15];
int aMin02[15]; /* minimum 4 */
int aNId02[15];
int aXMI02[15];
int GetMaxNIdx(int *nMax4, int *nXId4, int N, int *nQt01, int nLen)
{
int nT1 = 0;
int nT3 = 0;
int nT4 = 0;
int nTmp = 0;
for (nT1 = 0; nT1 < N; nT1++) {
nMax4[nT1] = 0;
nXId4[nT1] = 0;
}
for (nT1 = 0; nT1 < nLen; nT1++) {
nTmp = nQt01[nT1];
/* maximum */
for (nT3 = 0; nT3 < N; nT3++) {
if (nTmp > nMax4[nT3]) {
for (nT4 = 3; nT4 >= nT3+1; nT4--) {
nMax4[nT4] = nMax4[nT4-1];
nXId4[nT4] = nXId4[nT4-1];
}
nMax4[nT3] = nTmp;
nXId4[nT3] = nT1;
break;
}
}
}
return 0;
}
int GetMinNIdx(int *nMax4, int *nXId4, int N, int *nQt01, int nLen)
{
int nT1 = 0;
int nT3 = 0;
int nT4 = 0;
int nTmp = 0;
for (nT1 = 0; nT1 < N; nT1++) {
nMax4[nT1] = 17;
nXId4[nT1] = 0;
}
for (nT1 = 0; nT1 < nLen; nT1++) {
nTmp = nQt01[nT1];
/* minimum */
for (nT3 = 0; nT3 < N; nT3++) {
if (nTmp < nMax4[nT3]) {
for (nT4 = 3; nT4 >= nT3+1; nT4--) {
nMax4[nT4] = nMax4[nT4-1];
nXId4[nT4] = nXId4[nT4-1];
}
nMax4[nT3] = nTmp;
nXId4[nT3] = nT1;
break;
}
}
}
return 0;
}
/* 15: 8-7 */
/* 12: 3-2-3-2-2 */
/* 10: 6-4 */
/* 10: 5-5 */
/* 10: 2-2-2-4 */
/* 10: 2-3-3-2 */
/* 10: 3-2-3-2 */
/* pulldown pattern number */
int FlmModsDet(struct sFlmDatSt *pRDat, int nDif01, int nDif02)
{
int iWidth = pRDat->iWidth;
int iHeight = pRDat->iHeight;
int iSIZE = (iWidth * iHeight);
int iMxDif = (iSIZE >> 6);
int nPrtLog[PDXX_PT_NUM] = {87, 32322, 64, 55, 2224, 2332, 3232};
/* HISDETNUM hist */
UINT8 *pModXx = pRDat->pModXx;
UINT8 *pFlgXx = pRDat->pFlgXx; /* pre-1, nxt-0 */
UINT8 *pLvlXx = pRDat->pLvlXx; /* mode level */
static unsigned int sModFlg01[PDXX_PT_NUM]; /* flags */
static unsigned int sModFlg02[PDXX_PT_NUM]; /* flags */
static int nModCnt[PDXX_PT_NUM]; /* mode counter */
unsigned int tModFlg01[PDXX_PT_NUM]; /* current flags */
unsigned int tModFlg02[PDXX_PT_NUM]; /* current flags */
int nMxMn[PDXX_PT_NUM][2] = { {2, 4}, {-2, -2}, {2, 4},
{2, 4}, {4, -2}, {4, -2}, {4, -2} };
int nModLvl[PDXX_PT_NUM] = {0, 0, 0, 0, 0, 0, 0}; /* mode level */
int nQt01[15];
int nQt02[15];
int aMax01[15]; /* maximum 4 */
int aXId01[15];
int aMin01[15]; /* minimum 4 */
int aNId01[15];
int aXMI01[15];
int nT0 = 0;
int nT1 = 0;
int nT2 = 0;
int nT3 = 0;
int nT4 = 0;
int tT0 = 0;
int tT1 = 0;
int tT2 = 0;
int tT3 = 0;
unsigned int uT01 = 0;
unsigned int uT02 = 0;
unsigned int uT03 = 0;
int nS01[PDXX_PT_NUM] = {0, 0, 0, 0, 0, 0, 0};
int nS02[PDXX_PT_NUM] = {0, 0, 0, 0, 0, 0, 0};
int nStp[PDXX_PT_NUM] = {15, 12, 10, 10, 10, 10};
static int pDif01[30];
static int pDif02[30];
int nLen1 = 0;
int nLen2 = 0;
int nMin01 = 0;
int nMax01 = 0;
int nMin02 = 0;
int nMax02 = 0;
int tModLvl = 0;
iMxDif = (iMxDif >> 4) + 1;
prt_flg = ((pr_pd >> 4) & 0x1);
if (prt_flg)
sprintf(debug_str, "#DbgXx:\n");
for (nT0 = 1; nT0 < HISDETNUM; nT0++) {
pFlgXx[nT0 - 1] = pFlgXx[nT0];
pLvlXx[nT0 - 1] = pLvlXx[nT0];
pModXx[nT0 - 1] = pModXx[nT0];
}
for (nT0 = 0; nT0 < 29; nT0++) {
pDif01[nT0] = pDif01[nT0 + 1];
pDif02[nT0] = pDif02[nT0 + 1];
}
pDif01[29] = (nDif01 >> 6);
pDif02[29] = (nDif02 >> 6);
for (nT0 = 0; nT0 < 3; nT0++) {
nT2 = nStp[nT0];
nT3 = pDif01[29];
nT4 = pDif02[29];
nMin01 = nT3;
nMax01 = nT3;
nMin02 = nT4;
nMax02 = nT4;
nT3 = pDif01[29] - pDif01[29 - nT2];
nT4 = pDif02[29] - pDif02[29 - nT2];
if (nT3 < 0)
nT3 = -nT3;
if (nT4 < 0)
nT4 = -nT4;
nS01[nT0] = nT3;
nS02[nT0] = nT4;
/* nS01, nS02: sum of difference */
for (nT1 = 1; nT1 < nT2; nT1++) {
nT3 = pDif01[29 - nT1];
nT4 = pDif02[29 - nT1];
if (nT3 > nMax01)
nMax01 = nT3;
if (nT3 < nMin01)
nMin01 = nT3;
if (nT4 > nMax02)
nMax02 = nT4;
if (nT4 < nMin02)
nMin02 = nT4;
/* diff max */
nT3 = pDif01[29 - nT1] - pDif01[29 - nT1 - nT2];
nT4 = pDif02[29 - nT1] - pDif02[29 - nT1 - nT2];
if (nT3 < 0)
nT3 = -nT3;
if (nT4 < 0)
nT4 = -nT4;
if (nT3 > nS01[nT0])
nS01[nT0] = nT3;
if (nT4 > nS02[nT0])
nS02[nT0] = nT4;
}
for (nT1 = 0; nT1 < nT2; nT1++) {
nT3 = pDif01[29 - nT1] - nMin01;
nT4 = nMax01 - nMin01 + 32;
nT3 = (16 * nT3) + (nT4 / 2);
nQt01[nT1] = (nT3 / nT4);
nT3 = pDif02[29 - nT1] - nMin02;
nT4 = nMax02 - nMin02 + 32;
nT3 = (16 * nT3) + (nT4 / 2);
nQt02[nT1] = (nT3 / nT4);
}
if (nT0 == 2)
tT2 = PDXX_PT_NUM - 2;
else
tT2 = 1;
for (tT1 = 0; tT1 < tT2; tT1++) {
tT0 = nT0 + tT1;
tModLvl = ((nModCnt[tT0] + 2) >> 2);
if (tModLvl > 64)
tModLvl = 64;
if (nS01[nT0] > nMax01)
nT3 = 8;
else {
nT3 = (nS01[nT0] << 3);
nT3 = nT3 + (nMax01 >> 1);
nT3 = nT3 / (nMax01 + 1);
if (nT3 > 8)
nT3 = 8;
}
tModLvl -= nT3;
if (nS02[nT0] > nMax02)
nT4 = 8;
else {
nT4 = (nS02[nT0] << 3);
nT4 = nT4 + (nMax02 >> 1);
nT4 = nT4 / (nMax02 + 1);
if (nT4 > 8)
nT4 = 8;
}
tModLvl -= nT4;
if (nMxMn[tT0][0] > 0) {
nLen1 = nMxMn[tT0][0];
GetMaxNIdx(aMax01, aXId01, nLen1, nQt01, nT2);
nT4 = 0;
for (tT3 = 0; tT3 < nLen1; tT3++) {
aXMI01[tT3] = aXId01[tT3];
nT4 += (16 - aMax01[tT3]);
}
nT4 /= nLen1;
tModLvl -= nT4;
} else {
nLen1 = -nMxMn[tT0][0];
GetMinNIdx(aMin01, aNId01, nLen1, nQt01, nT2);
nT4 = 0;
for (tT3 = 0; tT3 < nLen1; tT3++) {
aXMI01[tT3] = aNId01[tT3];
nT4 += aMin01[tT3];
}
nT4 /= nLen1;
tModLvl -= nT4;
}
if (nMxMn[tT0][1] > 0) {
nLen2 = nMxMn[tT0][1];
GetMaxNIdx(aMax02, aXId02, nLen2, nQt02, nT2);
nT4 = 0;
for (tT3 = 0; tT3 < nLen2; tT3++) {
aXMI02[tT3] = aXId02[tT3];
nT4 += (16 - aMax02[tT3]);
}
nT4 /= nLen2;
tModLvl -= nT4;
} else {
nLen2 = -nMxMn[tT0][1];
GetMinNIdx(aMin02, aNId02, nLen2, nQt02, nT2);
nT3 = 0;
nT4 = 0;
for (tT3 = 0; tT3 < nLen2; tT3++) {
aXMI02[tT3] = aNId02[tT3];
nT4 += aMin02[tT3];
nT3 = pDif02[29 - aNId02[tT3]];
if (nT3 > iMxDif)
nT4 += 8;
else {
nT3 = (nT3 << 3) +
(iMxDif >> 1);
nT3 /= (iMxDif + 1);
nT4 += nT3;
}
}
nT4 /= (2 * nLen2);
tModLvl -= nT4;
}
tModFlg01[tT0] = 0;
for (tT3 = 0; tT3 < nLen1; tT3++)
tModFlg01[tT0] |= (1 << aXMI01[tT3]);
tModFlg02[tT0] = 0;
for (tT3 = 0; tT3 < nLen2; tT3++)
tModFlg02[tT0] |= (1 << aXMI02[tT3]);
uT03 = (1 << nT2) - 1;
tModFlg01[tT0] &= uT03;
tModFlg02[tT0] &= uT03;
uT01 = (sModFlg01[tT0] << 1);
uT01 |= (uT01 >> nT2);
uT01 &= uT03;
uT02 = (sModFlg02[tT0] << 1);
uT02 |= (uT02 >> nT2);
uT02 &= uT03;
/* minimum check */
nLen2 = 0;
if (tT0 == 0) { /* 8-7 */
nLen2 = 11;
} else if (tT0 == 2) { /* 6-4 */
nLen2 = 6;
} else if (tT0 == 3) { /* 5-5 */
nLen2 = 6;
}
if (nLen2 > 0) {
GetMinNIdx(aMin02, aNId02, nLen2, nQt02, nT2);
nT4 = 0;
for (tT3 = 0; tT3 < nLen2; tT3++) {
nT3 = pDif02[29 - aNId02[tT3]];
if (nT3 > iMxDif)
nT4 += 8;
else {
nT3 = (nT3 << 3)
+ (iMxDif >> 1);
nT3 /= (iMxDif + 1);
nT4 += nT3;
}
}
nT4 /= nLen2;
tModLvl -= nT4;
}
if (nMin02 > iMxDif) {
tModLvl -= 16;
nModCnt[tT0] = 0;
} else {
nT4 = (nMin02 << 4);
nT4 = nT4 / iMxDif;
tModLvl -= nT4;
}
/*
* nT4 = (nMin02 << 6) + (iMxDif >> 1);
* nT4 = nT4 / iMxDif;
* if (nModCnt[tT0] > nT4)
* nModCnt[tT0] -= nT4;
* else
* nModCnt[tT0] = 0;
*/
/* Distance between maximum-2 dif01*/
if (aXMI01[1] > aXMI01[0])
nT3 = aXMI01[1] - aXMI01[0];
else
nT3 = aXMI01[0] - aXMI01[1];
/* Distance between minimium-2 dif02 */
if (aXMI02[1] > aXMI02[0])
nT4 = aXMI02[1] - aXMI02[0];
else
nT4 = aXMI02[0] - aXMI02[1];
if ((uT01 == tModFlg01[tT0]) &&
(uT02 == tModFlg02[tT0]) &&
(nT3 > 0) && (uT01 > 0) &&
(uT02 > 0)) {
if (tT0 == 0) {
if (nT3 == 7 || nT3 == 8) {
nModCnt[tT0] += 1;
tModLvl += 2;
} else
nModCnt[tT0] = 0;
} else if (tT0 == 2) {
if (nT3 == 4 || nT3 == 6) {
nModCnt[tT0] += 1;
tModLvl += 2;
} else
nModCnt[tT0] = 0;
} else if (tT0 == 3) {
if (nT3 == 5) {
nModCnt[tT0] += 1;
tModLvl += 2;
} else
nModCnt[tT0] = 0;
}
}
if ((uT02 == tModFlg02[tT0]) &&
(nT4 > 0) && (uT02 > 0)) {
if ((uT01 == tModFlg01[tT0]) && (uT01 > 0))
tModLvl += 1;
if (tT0 == 1) {
if (nT4 == 5 || nT4 == 7) {
nModCnt[tT0] += 1;
tModLvl += 1;
} else
nModCnt[tT0] = 0;
} else if (tT0 == 4) {
if (nT4 == 1 || nT4 == 9) {
nModCnt[tT0] += 1;
tModLvl += 1;
} else
nModCnt[tT0] = 0;
} else if (tT0 == 5) {
if (nT4 == 3 || nT4 == 7) {
nModCnt[tT0] += 1;
tModLvl += 1;
} else
nModCnt[tT0] = 0;
} else if (tT0 == 6) {
if (nT4 == 5) {
nModCnt[tT0] += 1;
tModLvl += 1;
} else
nModCnt[tT0] = 0;
}
}
if (nModCnt[tT0] > 254)
nModCnt[tT0] = 254;
if (tModLvl < 0)
tModLvl = 0;
nModLvl[tT0] = tModLvl;
sModFlg01[tT0] = tModFlg01[tT0];
sModFlg02[tT0] = tModFlg02[tT0];
} /* 2-3-4-5*/
}
tModLvl = nModLvl[0];
nT1 = 0;
for (nT0 = 1; nT0 < PDXX_PT_NUM; nT0++) {
if (nModLvl[nT0] > tModLvl) {
tModLvl = nModLvl[nT0];
nT1 = nT0;
}
}
if (prt_flg)
sprintf(debug_str + strlen(debug_str),
"nMax02(10)=%4d < (%4d)\n",
nMax02, (iSIZE >> flm2224_stl_sft));
if ((nT1 == 4) &&
(nMax02 <= (iSIZE >> flm2224_stl_sft)))
nModCnt[nT1] = 0;
pModXx[HISDETNUM - 1] = nT1;
pLvlXx[HISDETNUM - 1] = tModLvl;
pFlgXx[HISDETNUM - 1] = (pDif01[29] < pDif01[28]);
/* recheck */
if ((pFlgXx[HISDETNUM - 2] == 0) &&
(pDif01[29] > pDif01[28]))
pFlgXx[HISDETNUM - 2] = 1;
if (prt_flg && tModLvl > 0) {
sprintf(debug_str + strlen(debug_str),
"#FM%5d detected ct(%3d) lvl(%2d)\n",
nPrtLog[nT1], nModCnt[nT1], nModLvl[nT1]);
if (pDif01[29] < pDif01[28])
sprintf(debug_str + strlen(debug_str),
"#Pre: A<-A\n");
else
sprintf(debug_str + strlen(debug_str),
"#Nxt: A B->\n");
}
if (prt_flg) {
sprintf(debug_str + strlen(debug_str),
"Mod=%5d, Flg=%d, Lvl=%3d\n",
nT1, pFlgXx[HISDETNUM - 1],
tModLvl);
pr_info("%s", debug_str);
}
return nT1;
}