blob: 67d61c0045e5bd8b5a32113e207ea7b6326cbc3b [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* drivers/amlogic/media/video_processor/ppmgr/decontour.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/amlogic/iomap.h>
#include <linux/amlogic/media/registers/cpu_version.h>
#include "decontour.h"
#define uint32_t unsigned int
#define Wr(adr, val) aml_write_vcbus(adr, val)
#define Rd(adr) aml_read_vcbus(adr)
void ini_dcntr_pre(int hsize, int vsize, int grd_num_mode, u32 ratio)
{
int xsize = hsize;
int ysize = vsize;
int reg_in_ds_rate_x;
int reg_in_ds_rate_y;
int ds_r_sft_x;
int ds_r_sft_y;
int in_ds_r_x;
int in_ds_r_y;
int xds;
int yds;
u32 grd_num;
u32 reg_grd_xnum;
u32 reg_grd_ynum;
u32 reg_grd_xsize_ds = 0;
u32 reg_grd_ysize_ds = 0;
u32 reg_grd_xnum_use;
u32 reg_grd_ynum_use;
u32 reg_grd_xsize;
u32 reg_grd_ysize;
int grd_path;
int reg_grd_vbin_gb_0 = 24 + 48 * 0;
int reg_grd_vbin_gb_1 = 24 + 48 * 1;
int reg_grd_vbin_gb_2 = 24 + 48 * 2;
int reg_grd_vbin_gb_3 = 24 + 48 * 3;
int reg_grd_vbin_gb_4 = 24 + 48 * 4;
int reg_grd_vbin_gb_5 = 24 + 48 * 5;
int reg_grd_vbin_gb_6 = 24 + 48 * 6;
int reg_grd_vbin_gb_7 = 24 + 48 * 7;
int reg_grd_vbin_gb_8 = 24 + 48 * 8;
int reg_grd_vbin_gb_9 = 24 + 48 * 9;
int reg_grd_vbin_gb_10 = 24 + 48 * 10;
int reg_grd_vbin_gb_11 = 24 + 48 * 11;
int reg_grd_vbin_gb_12 = 24 + 48 * 12;
int reg_grd_vbin_gb_13 = 24 + 48 * 13;
int reg_grd_vbin_gb_14 = 24 + 48 * 14;
int reg_grd_vbin_gb_15 = 24 + 48 * 15;
int reg_grd_vbin_gb_16 = 24 + 48 * 16;
int reg_grd_vbin_gb_17 = 24 + 48 * 17;
int reg_grd_vbin_gb_18 = 24 + 48 * 18;
int reg_grd_vbin_gb_19 = 24 + 48 * 19;
int reg_grd_vbin_gb_20 = 24 + 48 * 20;
int reg_grd_vbin_gb_21 = 24 + 48 * 21;
Wr(DCTR_BGRID_TOP_FSIZE, (hsize << 13) | (vsize));
Wr(DCNTR_GRID_GEN_REG, 1 << 29);
Wr(DCTR_BGRID_TOP_CTRL0, (1 << 30) |
(1 << 29) |
(2 << 16) |
(0 << 4) |
(1 << 2) |
(1 << 1) |
(1 << 0));
/*reg_in_ds_rate_x = (hsize > 1920) ? 2 : (hsize > 960) ? 1 : 0;*/
/*reg_in_ds_rate_y = (vsize > 1080) ? 2 : (vsize > 540) ? 1 : 0;*/
reg_in_ds_rate_x = ratio;
reg_in_ds_rate_y = ratio;
ds_r_sft_x = reg_in_ds_rate_x;
ds_r_sft_y = reg_in_ds_rate_y;
in_ds_r_x = 1 << ds_r_sft_x;
in_ds_r_y = 1 << ds_r_sft_y;
xds = (hsize + in_ds_r_x - 1) >> ds_r_sft_x;
yds = (vsize + in_ds_r_y - 1) >> ds_r_sft_y;
grd_num = Rd(DCTR_BGRID_PARAM1_PRE);
reg_grd_xnum = grd_num_mode == 0 ? 40 : grd_num_mode == 1 ? 60 : 80;
reg_grd_ynum = grd_num_mode == 0 ? 23 : grd_num_mode == 1 ? 34 : 45;
grd_path = reg_in_ds_rate_x == 0 && reg_in_ds_rate_y == 0;
if (grd_path == 0) {
reg_grd_xsize_ds = (xds + reg_grd_xnum - 1) / (reg_grd_xnum);
reg_grd_ysize_ds = (yds + reg_grd_ynum - 1) / (reg_grd_ynum);
reg_grd_xnum_use = ((xds - reg_grd_xsize_ds / 2)
+ reg_grd_xsize_ds - 1)
/ (reg_grd_xsize_ds) + 1;
reg_grd_ynum_use = ((yds - reg_grd_ysize_ds / 2)
+ reg_grd_ysize_ds - 1)
/ (reg_grd_ysize_ds) + 1;
reg_grd_xsize = reg_grd_xsize_ds * in_ds_r_x;
reg_grd_ysize = reg_grd_ysize_ds * in_ds_r_y;
} else {
reg_grd_xsize = (xsize + reg_grd_xnum - 1) / (reg_grd_xnum);
reg_grd_ysize = (ysize + reg_grd_ynum - 1) / (reg_grd_ynum);
reg_grd_xnum_use = ((xsize - reg_grd_xsize / 2)
+ reg_grd_xsize - 1) / (reg_grd_xsize) + 1;
reg_grd_ynum_use = ((ysize - reg_grd_ysize / 2)
+ reg_grd_ysize - 1) / (reg_grd_ysize) + 1;
}
Wr(DCTR_BGRID_PATH_PRE, (grd_path << 4));
Wr(DCTR_DS_PRE,
(0 << 11) |
(0 << 9) |
(8 << 5) |
(0 << 4) |
(reg_in_ds_rate_x << 2) |
reg_in_ds_rate_y);
Wr(DCTR_BGRID_PARAM2_PRE, (reg_grd_xsize << 24) |
(reg_grd_ysize << 16) |
(48 << 8) |
(22));
Wr(DCTR_BGRID_PARAM3_PRE, (reg_grd_xnum_use << 16) |
(reg_grd_ynum_use));
Wr(DCTR_BGRID_PARAM4_PRE, (reg_grd_xsize_ds << 16) |
(reg_grd_ysize_ds));
Wr(DCTR_BGRID_WRAP_CTRL, 1);
Wr(DCTR_BGRID_PARAM5_PRE_0,
(reg_grd_vbin_gb_0 << 16) | reg_grd_vbin_gb_1);
Wr(DCTR_BGRID_PARAM5_PRE_1,
(reg_grd_vbin_gb_2 << 16) | reg_grd_vbin_gb_3);
Wr(DCTR_BGRID_PARAM5_PRE_2,
(reg_grd_vbin_gb_4 << 16) | reg_grd_vbin_gb_5);
Wr(DCTR_BGRID_PARAM5_PRE_3,
(reg_grd_vbin_gb_6 << 16) | reg_grd_vbin_gb_7);
Wr(DCTR_BGRID_PARAM5_PRE_4,
(reg_grd_vbin_gb_8 << 16) | reg_grd_vbin_gb_9);
Wr(DCTR_BGRID_PARAM5_PRE_5,
(reg_grd_vbin_gb_10 << 16) | reg_grd_vbin_gb_11);
Wr(DCTR_BGRID_PARAM5_PRE_6,
(reg_grd_vbin_gb_12 << 16) | reg_grd_vbin_gb_13);
Wr(DCTR_BGRID_PARAM5_PRE_7,
(reg_grd_vbin_gb_14 << 16) | reg_grd_vbin_gb_15);
Wr(DCTR_BGRID_PARAM5_PRE_8,
(reg_grd_vbin_gb_16 << 16) | reg_grd_vbin_gb_17);
Wr(DCTR_BGRID_PARAM5_PRE_9,
(reg_grd_vbin_gb_18 << 16) | reg_grd_vbin_gb_19);
Wr(DCTR_BGRID_PARAM5_PRE_10,
(reg_grd_vbin_gb_20 << 16) | reg_grd_vbin_gb_21);
}
void set_dcntr_grid_mif(u32 x_start,
u32 x_end,
u32 y_start,
u32 y_end,
u32 mode,
u32 canvas_addr0,
u32 canvas_addr1,
u32 canvas_addr2,
u32 pic_struct,
u32 h_avg)
{
u32 demux_mode = (mode > 1) ? 0 : mode;
u32 bytes_per_pixel = (mode > 1) ? 0 : ((mode == 1) ? 2 : 1);
u32 burst_size_cr = 0;
u32 burst_size_cb = 0;
u32 burst_size_y = 3;
u32 st_separate_en = (mode > 1);
u32 value = 0;
Wr(DCNTR_GRID_GEN_REG,
(4 << 19) |
(0 << 18) |
(demux_mode << 16) |
(bytes_per_pixel << 14) |
(burst_size_cr << 12) |
(burst_size_cb << 10) |
(burst_size_y << 8) |
(0 << 6) |
(h_avg << 2) |
(st_separate_en << 1) |
(0 << 0)
);
Wr(DCNTR_GRID_CANVAS0,
(canvas_addr2 << 16) |
(canvas_addr1 << 8) |
(canvas_addr0 << 0)
);
Wr(DCNTR_GRID_LUMA_X0, (x_end << 16) |
(x_start << 0)
);
Wr(DCNTR_GRID_LUMA_Y0, (y_end << 16) |
(y_start << 0)
);
if (mode > 1) {
Wr(DCNTR_GRID_CHROMA_X0, ((((x_end + 1) >> 1) - 1) << 16) |
((x_start + 1) >> 1));
Wr(DCNTR_GRID_CHROMA_Y0, ((((y_end + 1) >> 1) - 1) << 16) |
((y_start + 1) >> 1));
}
if (pic_struct == 0) {
Wr(DCNTR_GRID_RPT_LOOP, (0 << 24) |
(0 << 16) |
(0 << 8) |
(0 << 0));
Wr(DCNTR_GRID_LUMA0_RPT_PAT, 0x0);
Wr(DCNTR_GRID_CHROMA0_RPT_PAT, 0x0);
} else if ((pic_struct == 3) || (pic_struct == 6)) {
Wr(DCNTR_GRID_RPT_LOOP, (0 << 24) |
(0 << 16) |
(0 << 8) |
(0 << 0));
if (pic_struct == 6)
value = 0xa;
else if (pic_struct == 3)
value = 0x8;
Wr(DCNTR_GRID_LUMA0_RPT_PAT, value);/*0x8:2 line read 1; 0xa:4 line read 1*/
Wr(DCNTR_GRID_CHROMA0_RPT_PAT, value);
} else if ((pic_struct == 2) || (pic_struct == 5)) {
Wr(DCNTR_GRID_RPT_LOOP, (0 << 24) |
(0 << 16) |
(0x11 << 8) |
(0x11 << 0));
if (pic_struct == 5)
value = 0xa0;
else if (pic_struct == 2)
value = 0x80;
Wr(DCNTR_GRID_LUMA0_RPT_PAT, value);/*0x80:2 line read 1; 0xa0:4 line read 1*/
Wr(DCNTR_GRID_CHROMA0_RPT_PAT, value);
} else if (pic_struct == 4) {
Wr(DCNTR_GRID_RPT_LOOP, (0 << 24) |
(0 << 16) |
(0x0 << 8) |
(0x11 << 0));
Wr(DCNTR_GRID_LUMA0_RPT_PAT, 0x80);
Wr(DCNTR_GRID_CHROMA0_RPT_PAT, 0x0);
}
Wr(DCNTR_GRID_DUMMY_PIXEL, 0x00808000);
if (mode == 2)
Wr(DCNTR_GRID_GEN_REG2, 1);/*0:NOT NV12 or NV21;1:NV12 (CbCr);2:NV21 (CrCb)*/
else
Wr(DCNTR_GRID_GEN_REG2, 0);
Wr(DCNTR_GRID_GEN_REG3, 5);
Wr(DCNTR_GRID_GEN_REG, Rd(DCNTR_GRID_GEN_REG) | (1 << 0));
}
void set_dcntr_grid_fmt(u32 hfmt_en,
u32 hz_yc_ratio,
u32 hz_ini_phase,
u32 vfmt_en,
u32 vt_yc_ratio,
u32 vt_ini_phase,
u32 y_length)
{
u32 vt_phase_step = (16 >> vt_yc_ratio);
u32 vfmt_w = (y_length >> hz_yc_ratio);
Wr(DCNTR_GRID_FMT_CTRL,
(0 << 28) |
(hz_ini_phase << 24) |
(0 << 23) |
(hz_yc_ratio << 21) |
(hfmt_en << 20) |
(1 << 17) |
(0 << 16) |
(0 << 12) |
(vt_ini_phase << 8) |
(vt_phase_step << 1) |
(vfmt_en << 0));
Wr(DCNTR_GRID_FMT_W, (y_length << 16) | (vfmt_w << 0));
}
void dcntr_grid_rdmif(int canvas_id0,
int canvas_id1,
int canvas_id2,
int canvas_baddr0,
int canvas_baddr1,
int canvas_baddr2,
int src_hsize,
int src_vsize,
int src_fmt, /*1=RGB/YCBCR, 0=422 (2 bytes/pixel) 2:420,two canvas(nv21) 3:420,three*/
int mif_x_start,
int mif_x_end,
int mif_y_start,
int mif_y_end,
int mif_reverse,
int pic_struct,
int h_avg)
{
int hfmt_en;
int hz_yc_ratio;
int vfmt_en;
int vt_yc_ratio;
int fmt_hsize;
int canvas_w;
int stride_mif_y;
int stride_mif_c;
if (src_fmt == 0)
canvas_w = 2;
else if (src_fmt == 1)
canvas_w = 3;
else if (src_fmt == 2)
canvas_w = 1;
else
canvas_w = 1;
if (get_cpu_type() > MESON_CPU_MAJOR_ID_T5) {
Wr(DCNTR_GRID_BADDR_Y, canvas_baddr0 >> 4);
Wr(DCNTR_GRID_BADDR_CB, canvas_baddr1 >> 4);
Wr(DCNTR_GRID_BADDR_CR, canvas_baddr2 >> 4);
if (src_fmt == 0)
stride_mif_y = (src_hsize * 8 * 2 + 127) >> 7; /*422 one plane*/
else if (src_fmt == 1)
stride_mif_y = (src_hsize * 8 * 3 + 127) >> 7; /*444 one plane*/
else if (src_fmt == 2)
stride_mif_y = (src_hsize * 8 + 127) >> 7; /*420 two planes, nv21/nv12*/
else
stride_mif_y = (src_hsize * 8 + 127) >> 7; /*444 three planes*/
if (src_fmt == 0)
stride_mif_c = stride_mif_y; /*422 one plane*/
else if (src_fmt == 1)
stride_mif_c = stride_mif_y; /*444 one plane*/
else if (src_fmt == 2)
stride_mif_c = stride_mif_y; /*420 two planes*/
else
stride_mif_c = stride_mif_y; /*444 three planes*/
Wr(DCNTR_GRID_STRIDE_0, (stride_mif_c << 16) | stride_mif_y);
Wr(DCNTR_GRID_STRIDE_1, (1 << 16) | stride_mif_c);
}
if (src_fmt == 0) {
hfmt_en = h_avg == 1 ? 0 : 1;
hz_yc_ratio = 1;
vfmt_en = 0;
vt_yc_ratio = 0;
} else if (src_fmt > 1) {
hfmt_en = h_avg == 1 ? 0 : 1;
hz_yc_ratio = 1;
vfmt_en = pic_struct == 4 ? 0 : 1;
vt_yc_ratio = 1;
} else {
hfmt_en = 0;
hz_yc_ratio = 0;
vfmt_en = 0;
vt_yc_ratio = 0;
}
fmt_hsize = mif_x_end - mif_x_start + 1;
if (pic_struct == 4)
fmt_hsize = fmt_hsize >> h_avg;
set_dcntr_grid_mif(mif_x_start,
mif_x_end,
mif_y_start,
mif_y_end,
src_fmt,
canvas_id0,
canvas_id1,
canvas_id2,
pic_struct,
h_avg);
set_dcntr_grid_fmt(hfmt_en,
hz_yc_ratio,
0,
vfmt_en,
vt_yc_ratio,
0,
fmt_hsize);
}
void dcntr_grid_wrmif(int mif_index,
int mem_mode,
int src_fmt,
int canvas_id,
int mif_x_start,
int mif_x_end,
int mif_y_start,
int mif_y_end,
int swap_64bit,
int mif_reverse,
int linear_baddr,
int linear_length)
{
u32 INT_WMIF_CTRL1;
u32 INT_WMIF_CTRL2;
u32 INT_WMIF_CTRL3;
u32 INT_WMIF_CTRL4;
u32 INT_WMIF_SCOPE_X;
u32 INT_WMIF_SCOPE_Y;
if (mif_index == 0) {
INT_WMIF_CTRL1 = DCNTR_CDS_WMIF_CTRL1;
INT_WMIF_CTRL2 = DCNTR_CDS_WMIF_CTRL2;
INT_WMIF_CTRL3 = DCNTR_CDS_WMIF_CTRL3;
INT_WMIF_CTRL4 = DCNTR_CDS_WMIF_CTRL4;
INT_WMIF_SCOPE_X = DCNTR_CDS_WMIF_SCOPE_X;
INT_WMIF_SCOPE_Y = DCNTR_CDS_WMIF_SCOPE_Y;
} else if (mif_index == 1) {
INT_WMIF_CTRL1 = DCNTR_GRD_WMIF_CTRL1;
INT_WMIF_CTRL2 = DCNTR_GRD_WMIF_CTRL2;
INT_WMIF_CTRL3 = DCNTR_GRD_WMIF_CTRL3;
INT_WMIF_CTRL4 = DCNTR_GRD_WMIF_CTRL4;
INT_WMIF_SCOPE_X = DCNTR_GRD_WMIF_SCOPE_X;
INT_WMIF_SCOPE_Y = DCNTR_GRD_WMIF_SCOPE_Y;
} else {
INT_WMIF_CTRL1 = DCNTR_YDS_WMIF_CTRL1;
INT_WMIF_CTRL2 = DCNTR_YDS_WMIF_CTRL2;
INT_WMIF_CTRL3 = DCNTR_YDS_WMIF_CTRL3;
INT_WMIF_CTRL4 = DCNTR_YDS_WMIF_CTRL4;
INT_WMIF_SCOPE_X = DCNTR_YDS_WMIF_SCOPE_X;
INT_WMIF_SCOPE_Y = DCNTR_YDS_WMIF_SCOPE_Y;
}
Wr(INT_WMIF_CTRL1,
(0 << 24) |
(canvas_id << 16) |
(1 << 12) |
(1 << 10) |
(2 << 8) |
(swap_64bit << 7) |
(mif_reverse << 6) |
(0 << 5) |
(0 << 4) |
(src_fmt << 0));
Wr(INT_WMIF_CTRL3,
((mem_mode == 0) << 16) |
(linear_length << 0));
if (get_cpu_type() > MESON_CPU_MAJOR_ID_T5)
Wr(INT_WMIF_CTRL4, linear_baddr >> 4);
else
Wr(INT_WMIF_CTRL4, linear_baddr);
Wr(INT_WMIF_SCOPE_X, (mif_x_end << 16) | mif_x_start);
Wr(INT_WMIF_SCOPE_Y, (mif_y_end << 16) | mif_y_start);
}