935 lines
30 KiB
C
935 lines
30 KiB
C
/*
|
|
* Copyright (C) 2014-2018, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* This software is licensed under the terms of the GNU General Public
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
* may be copied, distributed, and modified under those terms.
|
|
*
|
|
* 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/clk.h>
|
|
|
|
#include <asm/io.h>
|
|
|
|
#include <linux/platform/tegra/latency_allowance.h>
|
|
#include <linux/platform/tegra/mc-regs-t21x.h>
|
|
#include <linux/platform/tegra/mc.h>
|
|
#include <soc/tegra/chip-id.h>
|
|
|
|
#include "la_priv.h"
|
|
|
|
#define ON_LPDDR4() (tegra_emc_get_dram_type() == DRAM_TYPE_LPDDR4)
|
|
|
|
#define LA_ST_LA_MINUS_SNAP_ARB_TO_ROW_SRT_EMCCLKS_FP 70000
|
|
#define LA_DRAM_WIDTH_BITS 64
|
|
#define LA_DISP_CATCHUP_FACTOR_FP 1100
|
|
#define MC_MAX_FREQ_MHZ 533
|
|
#define MAX_GRANT_DEC 511
|
|
|
|
#define EXP_TIME_EMCCLKS_FP 88000
|
|
#define MAX_LA_NSEC 7650
|
|
#define DDA_BW_MARGIN_FP 1100
|
|
#define ONE_DDA_FRAC_FP 10
|
|
#define CPU_RD_BW_PERC 9
|
|
#define CPU_WR_BW_PERC 1
|
|
#define MIN_CYCLES_PER_GRANT 2
|
|
#define EMEM_PTSA_MINMAX_WIDTH 5
|
|
#define RING1_FEEDER_SISO_ALLOC_DIV 2
|
|
|
|
static struct la_client_info t21x_la_info_array[] = {
|
|
LA(0, 0, AFI_0, 23 : 16, AFIW, false, 128, 800),
|
|
LA(0, 0, AFI_0, 7 : 0, AFIR, false, 59, 400),
|
|
LA(0, 0, AVPC_0, 7 : 0, AVPC_ARM7R, false, 4, 0),
|
|
LA(0, 0, AVPC_0, 23 : 16, AVPC_ARM7W, false, 128, 800),
|
|
LA(0, 0, DC_0, 7 : 0, DISPLAY_0A, true, 80, 0),
|
|
LA(0, 0, DCB_0, 7 : 0, DISPLAY_0AB, true, 80, 0),
|
|
LA(0, 0, DC_0, 23 : 16, DISPLAY_0B, true, 80, 0),
|
|
LA(0, 0, DCB_0, 23 : 16, DISPLAY_0BB, true, 80, 0),
|
|
LA(0, 0, DC_1, 7 : 0, DISPLAY_0C, true, 80, 0),
|
|
LA(0, 0, DCB_1, 7 : 0, DISPLAY_0CB, true, 80, 0),
|
|
LA(0, 0, DC_3, 7 : 0, DISPLAYD, false, 80, 0),
|
|
LA(0, 0, DC_2, 7 : 0, DISPLAY_HC, false, 80, 0),
|
|
LA(0, 0, DCB_2, 7 : 0, DISPLAY_HCB, false, 80, 0),
|
|
LA(0, 0, DC_2, 23 : 16, DISPLAY_T, false, 80, 0),
|
|
LA(0, 0, GPU_0, 7 : 0, GPUSRD, false, 25, 800),
|
|
LA(0, 0, GPU_0, 23 : 16, GPUSWR, false, 128, 800),
|
|
LA(0, 0, HDA_0, 7 : 0, HDAR, false, 36, 0),
|
|
LA(0, 0, HDA_0, 23 : 16, HDAW, false, 128, 800),
|
|
LA(0, 0, TSEC_0, 7 : 0, TSECSRD, false, 157, 200),
|
|
LA(0, 0, TSEC_0, 23 : 16, TSECSWR, false, 128, 800),
|
|
LA(0, 0, TSECB_0, 7 : 0, TSECBSRD, false, 157, 200),
|
|
LA(0, 0, TSECB_0, 23 : 16, TSECBSWR, false, 128, 800),
|
|
LA(0, 0, HC_0, 7 : 0, HOST1X_DMAR, false, 28, 800),
|
|
LA(0, 0, HC_0, 23 : 16, HOST1XR, false, 80, 0),
|
|
LA(0, 0, HC_1, 7 : 0, HOST1XW, false, 128, 800),
|
|
LA(0, 0, ISP2_0, 7 : 0, ISP_RA, false, 51, 300),
|
|
LA(0, 0, ISP2_1, 7 : 0, ISP_WA, false, 128, 800),
|
|
LA(0, 0, ISP2_1, 23 : 16, ISP_WB, false, 128, 800),
|
|
LA(0, 0, ISP2B_0, 7 : 0, ISP_RAB, false, 54, 300),
|
|
LA(0, 0, ISP2B_1, 7 : 0, ISP_WAB, false, 128, 800),
|
|
LA(0, 0, ISP2B_1, 23 : 16, ISP_WBB, false, 128, 800),
|
|
LA(0, 0, MPCORE_0, 7 : 0, MPCORER, false, 4, 0),
|
|
LA(0, 0, MPCORE_0, 23 : 16, MPCOREW, false, 128, 800),
|
|
LA(0, 0, NVDEC_0, 7 : 0, NVDECR, false, 4, 0),
|
|
LA(0, 0, NVDEC_0, 23 : 16, NVDECW, false, 128, 800),
|
|
/* No entries for nvenc and nvjpg ?? */
|
|
/* LA(0, 0, PPCS_1, 7 : 0, PPCS_AHBDMAW, true, 128, 800), */
|
|
LA(0, 0, PPCS_0, 23 : 16, PPCS_AHBSLVR, false, 89, 408),
|
|
LA(0, 0, PPCS_1, 23 : 16, PPCS_AHBSLVW, false, 128, 800),
|
|
LA(0, 0, PTC_0, 7 : 0, PTCR, false, 0, 0),
|
|
LA(0, 0, SATA_0, 7 : 0, SATAR, false, 104, 400),
|
|
LA(0, 0, SATA_0, 23 : 16, SATAW, false, 128, 800),
|
|
LA(0, 0, SDMMC_0, 7 : 0, SDMMCR, false, 150, 248),
|
|
LA(0, 0, SDMMCA_0, 7 : 0, SDMMCRA, false, 150, 248),
|
|
LA(0, 0, SDMMCAA_0, 7 : 0, SDMMCRAA, false, 88, 248),
|
|
LA(0, 0, SDMMCAB_0, 7 : 0, SDMMCRAB, false, 88, 248),
|
|
LA(0, 0, SDMMC_0, 23 : 16, SDMMCW, false, 128, 800),
|
|
LA(0, 0, SDMMCA_0, 23 : 16, SDMMCWA, false, 128, 800),
|
|
LA(0, 0, SDMMCAA_0, 23 : 16, SDMMCWAA, false, 128, 800),
|
|
LA(0, 0, SDMMCAB_0, 23 : 16, SDMMCWAB, false, 128, 800),
|
|
LA(0, 0, VIC_0, 7 : 0, VICSRD, false, 29, 800),
|
|
LA(0, 0, VIC_0, 23 : 16, VICSWR, false, 128, 800),
|
|
LA(0, 0, VI2_0, 7 : 0, VI_W, false, 128, 800),
|
|
LA(0, 0, XUSB_1, 7 : 0, XUSB_DEVR, false, 59, 400),
|
|
LA(0, 0, XUSB_1, 23 : 16, XUSB_DEVW, false, 128, 800),
|
|
LA(0, 0, XUSB_0, 7 : 0, XUSB_HOSTR, false, 66, 400),
|
|
LA(0, 0, XUSB_0, 23 : 16, XUSB_HOSTW, false, 128, 800),
|
|
|
|
/* end of list */
|
|
LA(0, 0, DC_3, 0 : 0, MAX_ID, false, 0, 0)
|
|
};
|
|
|
|
static unsigned int emc_min_freq_mhz_fp;
|
|
static unsigned int emc_min_freq_mhz;
|
|
static unsigned int emc_max_freq_mhz;
|
|
static unsigned int hi_gd_fp;
|
|
static unsigned int lo_gd_fp;
|
|
static unsigned int hi_gd_fpa;
|
|
static unsigned int lo_gd_fpa;
|
|
static unsigned int low_freq_bw;
|
|
static unsigned int dda_div;
|
|
|
|
static struct la_chip_specific *cs;
|
|
const struct disp_client *tegra_la_disp_clients_info;
|
|
static unsigned int total_dc0_bw;
|
|
static unsigned int total_dc1_bw;
|
|
static DEFINE_MUTEX(disp_and_camera_ptsa_lock);
|
|
|
|
static void program_ptsa(void)
|
|
{
|
|
struct ptsa_info *p = &cs->ptsa_info;
|
|
|
|
mc_writel(p->ptsa_grant_dec, MC_PTSA_GRANT_DECREMENT);
|
|
mc_writel(1, MC_TIMING_CONTROL);
|
|
mc_writel(p->dis_extra_snap_level, MC_DIS_EXTRA_SNAP_LEVELS);
|
|
|
|
WRITE_PTSA_MIN_MAX_RATE(p, dis, DIS);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, disb, DISB);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, ve, VE);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, ve2, VE2);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, ring2, RING2);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, mpcorer, MLL_MPCORER);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, smmu, SMMU_SMMU);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, ring1, RING1);
|
|
WRITE_PTSA_MIN_MAX_RATE(p, isp, ISP);
|
|
|
|
WRITE_PTSA_MIN_MAX(p, a9avppc, A9AVPPC);
|
|
WRITE_PTSA_MIN_MAX(p, avp, AVP);
|
|
WRITE_PTSA_MIN_MAX(p, mse, MSE);
|
|
WRITE_PTSA_MIN_MAX(p, gk, GK);
|
|
WRITE_PTSA_MIN_MAX(p, vicpc, VICPC);
|
|
WRITE_PTSA_MIN_MAX(p, apb, APB);
|
|
WRITE_PTSA_MIN_MAX(p, pcx, PCX);
|
|
WRITE_PTSA_MIN_MAX(p, host, HOST);
|
|
WRITE_PTSA_MIN_MAX(p, ahb, AHB);
|
|
WRITE_PTSA_MIN_MAX(p, sax, SAX);
|
|
WRITE_PTSA_MIN_MAX(p, aud, AUD);
|
|
WRITE_PTSA_MIN_MAX(p, sd, SD);
|
|
WRITE_PTSA_MIN_MAX(p, usbx, USBX);
|
|
WRITE_PTSA_MIN_MAX(p, usbd, USBD);
|
|
WRITE_PTSA_MIN_MAX(p, ftop, FTOP);
|
|
}
|
|
|
|
static void save_ptsa(void)
|
|
{
|
|
struct ptsa_info *p = &cs->ptsa_info;
|
|
|
|
p->ptsa_grant_dec = mc_readl(MC_PTSA_GRANT_DECREMENT);
|
|
p->dis_extra_snap_level = mc_readl(MC_DIS_EXTRA_SNAP_LEVELS);
|
|
|
|
READ_PTSA_MIN_MAX_RATE(p, dis, DIS);
|
|
READ_PTSA_MIN_MAX_RATE(p, disb, DISB);
|
|
READ_PTSA_MIN_MAX_RATE(p, ve, VE);
|
|
READ_PTSA_MIN_MAX_RATE(p, ve2, VE2);
|
|
READ_PTSA_MIN_MAX_RATE(p, ring2, RING2);
|
|
READ_PTSA_MIN_MAX_RATE(p, mpcorer, MLL_MPCORER);
|
|
READ_PTSA_MIN_MAX_RATE(p, smmu, SMMU_SMMU);
|
|
READ_PTSA_MIN_MAX_RATE(p, ring1, RING1);
|
|
READ_PTSA_MIN_MAX_RATE(p, isp, ISP);
|
|
|
|
READ_PTSA_MIN_MAX(p, a9avppc, A9AVPPC);
|
|
READ_PTSA_MIN_MAX(p, avp, AVP);
|
|
READ_PTSA_MIN_MAX(p, mse, MSE);
|
|
READ_PTSA_MIN_MAX(p, gk, GK);
|
|
READ_PTSA_MIN_MAX(p, vicpc, VICPC);
|
|
READ_PTSA_MIN_MAX(p, apb, APB);
|
|
READ_PTSA_MIN_MAX(p, apb, APB);
|
|
READ_PTSA_MIN_MAX(p, host, HOST);
|
|
READ_PTSA_MIN_MAX(p, ahb, AHB);
|
|
READ_PTSA_MIN_MAX(p, sax, SAX);
|
|
READ_PTSA_MIN_MAX(p, aud, AUD);
|
|
READ_PTSA_MIN_MAX(p, sd, SD);
|
|
READ_PTSA_MIN_MAX(p, usbx, USBX);
|
|
READ_PTSA_MIN_MAX(p, usbd, USBD);
|
|
READ_PTSA_MIN_MAX(p, ftop, FTOP);
|
|
}
|
|
|
|
/*
|
|
* Gets the memory BW in MBps. @emc_freq should be in MHz.
|
|
*/
|
|
static u32 get_mem_bw_mbps(u32 dram_freq)
|
|
{
|
|
return dram_freq * 16;
|
|
}
|
|
|
|
static bool is_t210b01_soc(void)
|
|
{
|
|
u32 chipid, major;
|
|
|
|
chipid = tegra_hidrev_get_chipid(tegra_read_chipid());
|
|
major = tegra_hidrev_get_majorrev(tegra_read_chipid());
|
|
|
|
if (chipid == TEGRA210B01 && major >= 2)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* EMC frequency is actually DRAM frequency. Normally they are one in the same;
|
|
* however, with LPDDR4 DRAM, the DRAM clock goes to 1600MHz which the EMC clock
|
|
* cannot. Thus the EMC is actually running at DRAM clk / 2.
|
|
*/
|
|
static void t21x_init_ptsa(void)
|
|
{
|
|
struct clk *emc_clk;
|
|
unsigned int emc_freq_mhz;
|
|
unsigned int mc_freq_mhz;
|
|
unsigned int same_freq;
|
|
struct ptsa_info *p = &cs->ptsa_info;
|
|
unsigned int cpu_rd_bw, cpu_wr_bw;
|
|
unsigned int gd_int, gd_frac_fp;
|
|
int gd_fpa;
|
|
|
|
/* get emc frequency */
|
|
emc_clk = clk_get_sys("tegra_emc", "emc");
|
|
if (IS_ERR(emc_clk))
|
|
return;
|
|
|
|
emc_freq_mhz = clk_get_rate(emc_clk) /
|
|
LA_HZ_TO_MHZ_FACTOR;
|
|
la_debug("emc clk_rate = %u MHz", emc_freq_mhz);
|
|
|
|
/* get mc frequency */
|
|
same_freq = mc_readl(MC_EMEM_ARB_MISC0) &
|
|
MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_BIT;
|
|
mc_freq_mhz = same_freq ? emc_freq_mhz : emc_freq_mhz / 2;
|
|
la_debug("mc clk_rate = %u MHz", mc_freq_mhz);
|
|
|
|
/* compute initial value for grant dec */
|
|
gd_fpa = (LA_FP_TO_FPA(lo_gd_fp) * emc_freq_mhz) / emc_min_freq_mhz;
|
|
if (gd_fpa >= LA_REAL_TO_FPA(1)) {
|
|
gd_int = 1;
|
|
gd_fpa -= LA_REAL_TO_FPA(1);
|
|
} else {
|
|
gd_int = 0;
|
|
}
|
|
|
|
gd_frac_fp = __fraction2dda_fp(gd_fpa, 1,
|
|
MC_PTSA_RATE_DEFAULT_MASK);
|
|
p->ptsa_grant_dec = (gd_int << 12) | gd_frac_fp;
|
|
|
|
/* initialize PTSA reg values */
|
|
MC_SET_INIT_PTSA(p, ve, -5, 31);
|
|
MC_SET_INIT_PTSA(p, isp, -5, 31); /* Same for T210 and T210b01 */
|
|
if (is_t210b01_soc())
|
|
MC_SET_INIT_PTSA(p, ve2, -2, 0);
|
|
else
|
|
MC_SET_INIT_PTSA(p, ve2, -5, 31);
|
|
MC_SET_INIT_PTSA(p, a9avppc, -5, 16);
|
|
MC_SET_INIT_PTSA(p, ring2, -2, 0);
|
|
MC_SET_INIT_PTSA(p, dis, -5, 31);
|
|
MC_SET_INIT_PTSA(p, disb, -5, 31);
|
|
MC_SET_INIT_PTSA(p, ring1, -5, 31);
|
|
MC_SET_INIT_PTSA(p, mpcorer, -4, 4);
|
|
MC_SET_INIT_PTSA(p, smmu, 1, 1);
|
|
MC_SET_INIT_PTSA(p, mse, -2, 0);
|
|
MC_SET_INIT_PTSA(p, gk, -2, 0);
|
|
MC_SET_INIT_PTSA(p, vicpc, -2, 0);
|
|
MC_SET_INIT_PTSA(p, apb, -2, 0);
|
|
MC_SET_INIT_PTSA(p, pcx, -2, 0);
|
|
MC_SET_INIT_PTSA(p, host, -2, 0);
|
|
MC_SET_INIT_PTSA(p, ahb, -2, 0);
|
|
MC_SET_INIT_PTSA(p, sax, -2, 0);
|
|
MC_SET_INIT_PTSA(p, sd, -2, 0);
|
|
MC_SET_INIT_PTSA(p, usbx, -2, 0);
|
|
MC_SET_INIT_PTSA(p, usbd, -2, 0);
|
|
MC_SET_INIT_PTSA(p, ftop, -2, 0);
|
|
MC_SET_INIT_PTSA(p, avp, -2, 0);
|
|
MC_SET_INIT_PTSA(p, aud, -5, 31);
|
|
MC_SET_INIT_PTSA(p, jpg, -2, 0);
|
|
MC_SET_INIT_PTSA(p, gk2, -2, 0);
|
|
|
|
p->ring2_ptsa_rate = (unsigned int)(12) & MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
/* mpcorer */
|
|
cpu_rd_bw = (get_mem_bw_mbps(emc_freq_mhz) * CPU_RD_BW_PERC) / 100;
|
|
if (ON_LPDDR4())
|
|
cpu_rd_bw /= 2;
|
|
|
|
p->mpcorer_ptsa_rate = __fraction2dda_fp(lo_gd_fpa * cpu_rd_bw /
|
|
low_freq_bw,
|
|
dda_div,
|
|
MC_PTSA_RATE_DEFAULT_MASK);
|
|
|
|
/* FTOP (mpcorew it seems)*/
|
|
cpu_wr_bw = (get_mem_bw_mbps(emc_freq_mhz) * CPU_WR_BW_PERC) / 100;
|
|
if (ON_LPDDR4())
|
|
cpu_rd_bw /= 2;
|
|
|
|
p->ftop_ptsa_rate = __fraction2dda_fp(lo_gd_fpa * cpu_wr_bw /
|
|
low_freq_bw,
|
|
dda_div,
|
|
MC_PTSA_RATE_DEFAULT_MASK);
|
|
|
|
/* Ring1 */
|
|
p->ring1_ptsa_rate = p->mpcorer_ptsa_rate + p->ftop_ptsa_rate;
|
|
p->ring1_ptsa_rate += p->dis_ptsa_rate + p->disb_ptsa_rate;
|
|
p->ring1_ptsa_rate += p->ve_ptsa_rate + p->ring2_ptsa_rate;
|
|
|
|
program_ptsa();
|
|
}
|
|
|
|
/*
|
|
* This now also includes ring1 since that needs to have its PTSA updated
|
|
* based on freq and usecase.
|
|
*/
|
|
static void t21x_calc_disp_and_camera_ptsa(void)
|
|
{
|
|
struct ptsa_info *p = &cs->ptsa_info;
|
|
unsigned int ve_bw_fp = cs->camera_bw_array[CAMERA_IDX(VI_W)] *
|
|
DDA_BW_MARGIN_FP;
|
|
unsigned int ve2_bw_fp = 0;
|
|
unsigned int isp_bw_fp = 0;
|
|
unsigned int total_dc0_bw_fp = total_dc0_bw * DDA_BW_MARGIN_FP;
|
|
unsigned int total_dc1_bw_fp = total_dc1_bw * DDA_BW_MARGIN_FP;
|
|
unsigned int low_freq_bw_fp = la_real_to_fp(low_freq_bw);
|
|
unsigned int dis_frac_fp = LA_FPA_TO_FP(lo_gd_fpa * total_dc0_bw_fp /
|
|
low_freq_bw_fp);
|
|
unsigned int disb_frac_fp = LA_FPA_TO_FP(lo_gd_fpa * total_dc1_bw_fp /
|
|
low_freq_bw_fp);
|
|
unsigned int total_iso_bw_fp = total_dc0_bw_fp + total_dc1_bw_fp;
|
|
int max_max = (1 << EMEM_PTSA_MINMAX_WIDTH) - 1;
|
|
int i = 0;
|
|
|
|
if (cs->agg_camera_array[AGG_CAMERA_ID(VE2)].is_hiso) {
|
|
ve2_bw_fp = (cs->camera_bw_array[CAMERA_IDX(ISP_RAB)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WAB)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WBB)]) *
|
|
DDA_BW_MARGIN_FP;
|
|
} else {
|
|
ve2_bw_fp = LA_REAL_TO_FP(
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_RAB)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WAB)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WBB)]);
|
|
}
|
|
|
|
if (cs->agg_camera_array[AGG_CAMERA_ID(ISP)].is_hiso) {
|
|
isp_bw_fp = (cs->camera_bw_array[CAMERA_IDX(ISP_RA)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WA)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WB)]) *
|
|
DDA_BW_MARGIN_FP;
|
|
} else {
|
|
isp_bw_fp = LA_REAL_TO_FP(
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_RA)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WA)] +
|
|
cs->camera_bw_array[CAMERA_IDX(ISP_WB)]);
|
|
}
|
|
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE)].bw_fp = ve_bw_fp;
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE2)].bw_fp = ve2_bw_fp;
|
|
cs->agg_camera_array[AGG_CAMERA_ID(ISP)].bw_fp = isp_bw_fp;
|
|
|
|
for (i = 0; i < TEGRA_LA_AGG_CAMERA_NUM_CLIENTS; i++) {
|
|
struct agg_camera_client_info *agg_client =
|
|
&cs->agg_camera_array[i];
|
|
|
|
if (agg_client->is_hiso) {
|
|
agg_client->frac_fp = LA_FPA_TO_FP(
|
|
lo_gd_fpa * agg_client->bw_fp /
|
|
low_freq_bw_fp);
|
|
agg_client->ptsa_min = (unsigned int)(-5) &
|
|
MC_PTSA_MIN_DEFAULT_MASK;
|
|
agg_client->ptsa_max = (unsigned int)(max_max) &
|
|
MC_PTSA_MAX_DEFAULT_MASK;
|
|
|
|
total_iso_bw_fp += agg_client->bw_fp;
|
|
} else {
|
|
agg_client->frac_fp = ONE_DDA_FRAC_FP;
|
|
agg_client->ptsa_min = (unsigned int)(-2) &
|
|
MC_PTSA_MIN_DEFAULT_MASK;
|
|
agg_client->ptsa_max = (unsigned int)(0) &
|
|
MC_PTSA_MAX_DEFAULT_MASK;
|
|
}
|
|
}
|
|
|
|
MC_SET_INIT_PTSA(p, dis, -5, max_max);
|
|
p->dis_ptsa_rate = fraction2dda_fp(
|
|
dis_frac_fp,
|
|
4,
|
|
MC_PTSA_RATE_DEFAULT_MASK) &
|
|
MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
MC_SET_INIT_PTSA(p, disb, -5, max_max);
|
|
p->disb_ptsa_rate = fraction2dda_fp(
|
|
disb_frac_fp,
|
|
4,
|
|
MC_PTSA_RATE_DEFAULT_MASK) &
|
|
MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
p->ve_ptsa_min = cs->agg_camera_array[AGG_CAMERA_ID(VE)].ptsa_min &
|
|
MC_PTSA_MIN_DEFAULT_MASK;
|
|
p->ve_ptsa_max = cs->agg_camera_array[AGG_CAMERA_ID(VE)].ptsa_max &
|
|
MC_PTSA_MAX_DEFAULT_MASK;
|
|
p->ve_ptsa_rate = fraction2dda_fp(
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE)].frac_fp,
|
|
4,
|
|
MC_PTSA_RATE_DEFAULT_MASK) &
|
|
MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
p->ve2_ptsa_min = cs->agg_camera_array[AGG_CAMERA_ID(VE2)].ptsa_min &
|
|
MC_PTSA_MIN_DEFAULT_MASK;
|
|
p->ve2_ptsa_max = cs->agg_camera_array[AGG_CAMERA_ID(VE2)].ptsa_max &
|
|
MC_PTSA_MAX_DEFAULT_MASK;
|
|
if (is_t210b01_soc())
|
|
p->ve2_ptsa_rate = 1;
|
|
else
|
|
p->ve2_ptsa_rate = fraction2dda_fp(
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE2)].frac_fp,
|
|
4,
|
|
MC_PTSA_RATE_DEFAULT_MASK) &
|
|
MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
p->isp_ptsa_min = cs->agg_camera_array[AGG_CAMERA_ID(ISP)].ptsa_min &
|
|
MC_PTSA_MIN_DEFAULT_MASK;
|
|
p->isp_ptsa_max = cs->agg_camera_array[AGG_CAMERA_ID(ISP)].ptsa_max &
|
|
MC_PTSA_MAX_DEFAULT_MASK;
|
|
if (is_t210b01_soc())
|
|
p->isp_ptsa_rate = 50;
|
|
else
|
|
p->isp_ptsa_rate = fraction2dda_fp(
|
|
cs->agg_camera_array[AGG_CAMERA_ID(ISP)].frac_fp,
|
|
4,
|
|
MC_PTSA_RATE_DEFAULT_MASK) &
|
|
MC_PTSA_RATE_DEFAULT_MASK;
|
|
|
|
MC_SET_INIT_PTSA(p, ring1, -5, max_max);
|
|
|
|
|
|
p->ring1_ptsa_rate = p->dis_ptsa_rate + p->disb_ptsa_rate +
|
|
p->ve_ptsa_rate;
|
|
p->ring1_ptsa_rate += cs->agg_camera_array[AGG_CAMERA_ID(VE2)].is_hiso ?
|
|
p->ve2_ptsa_rate : 0;
|
|
p->ring1_ptsa_rate += cs->agg_camera_array[AGG_CAMERA_ID(ISP)].is_hiso ?
|
|
p->isp_ptsa_rate : 0;
|
|
|
|
if (ON_LPDDR4())
|
|
p->ring1_ptsa_rate /= 2;
|
|
|
|
/* These need to be read from the registers since the MC/EMC clock may
|
|
be different than last time these were read into *p. */
|
|
p->ring1_ptsa_rate += mc_readl(MC_MLL_MPCORER_PTSA_RATE) +
|
|
mc_readl(MC_FTOP_PTSA_RATE);
|
|
|
|
if (p->ring1_ptsa_rate == 0)
|
|
p->ring1_ptsa_rate = 0x1;
|
|
}
|
|
|
|
static void t21x_update_display_ptsa_rate(unsigned int *disp_bw_array)
|
|
{
|
|
struct ptsa_info *p = &cs->ptsa_info;
|
|
|
|
t21x_calc_disp_and_camera_ptsa();
|
|
|
|
mc_writel(p->ring1_ptsa_min, MC_RING1_PTSA_MIN);
|
|
mc_writel(p->ring1_ptsa_max, MC_RING1_PTSA_MAX);
|
|
mc_writel(p->ring1_ptsa_rate, MC_RING1_PTSA_RATE);
|
|
|
|
mc_writel(p->dis_ptsa_min, MC_DIS_PTSA_MIN);
|
|
mc_writel(p->dis_ptsa_max, MC_DIS_PTSA_MAX);
|
|
mc_writel(p->dis_ptsa_rate, MC_DIS_PTSA_RATE);
|
|
|
|
mc_writel(p->disb_ptsa_min, MC_DISB_PTSA_MIN);
|
|
mc_writel(p->disb_ptsa_max, MC_DISB_PTSA_MAX);
|
|
mc_writel(p->disb_ptsa_rate, MC_DISB_PTSA_RATE);
|
|
}
|
|
|
|
static int t21x_update_camera_ptsa_rate(enum tegra_la_id id,
|
|
unsigned int bw_mbps,
|
|
int is_hiso)
|
|
{
|
|
struct ptsa_info *p = NULL;
|
|
int ret_code = 0;
|
|
|
|
mutex_lock(&disp_and_camera_ptsa_lock);
|
|
|
|
if (!is_camera_client(id)) {
|
|
/* Non-camera clients should be handled by t21x_set_la(...) or
|
|
t21x_set_disp_la(...). */
|
|
pr_err("%s: Ignoring request from a non-camera client.\n",
|
|
__func__);
|
|
pr_err("%s: Non-camera clients should be handled by "
|
|
"t21x_set_la(...) or t21x_set_disp_la(...).\n",
|
|
__func__);
|
|
ret_code = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if ((id == ID(VI_W)) &&
|
|
(!is_hiso)) {
|
|
pr_err("%s: VI is stating that its not HISO.\n", __func__);
|
|
pr_err("%s: Ignoring and assuming that VI is HISO because VI "
|
|
"is always supposed to be HISO.\n",
|
|
__func__);
|
|
is_hiso = 1;
|
|
}
|
|
|
|
|
|
p = &cs->ptsa_info;
|
|
|
|
if (id == ID(VI_W)) {
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE)].is_hiso = is_hiso;
|
|
} else if ((id == ID(ISP_RAB)) ||
|
|
(id == ID(ISP_WAB)) ||
|
|
(id == ID(ISP_WBB))) {
|
|
cs->agg_camera_array[AGG_CAMERA_ID(VE2)].is_hiso = is_hiso;
|
|
} else {
|
|
cs->agg_camera_array[AGG_CAMERA_ID(ISP)].is_hiso = is_hiso;
|
|
}
|
|
|
|
cs->camera_bw_array[CAMERA_LA_IDX(id)] = bw_mbps;
|
|
|
|
t21x_calc_disp_and_camera_ptsa();
|
|
|
|
mc_writel(p->ring1_ptsa_min, MC_RING1_PTSA_MIN);
|
|
mc_writel(p->ring1_ptsa_max, MC_RING1_PTSA_MAX);
|
|
mc_writel(p->ring1_ptsa_rate, MC_RING1_PTSA_RATE);
|
|
|
|
mc_writel(p->ve_ptsa_min, MC_VE_PTSA_MIN);
|
|
mc_writel(p->ve_ptsa_max, MC_VE_PTSA_MAX);
|
|
mc_writel(p->ve_ptsa_rate, MC_VE_PTSA_RATE);
|
|
|
|
mc_writel(p->ve2_ptsa_min, MC_VE2_PTSA_MIN);
|
|
mc_writel(p->ve2_ptsa_max, MC_VE2_PTSA_MAX);
|
|
mc_writel(p->ve2_ptsa_rate, MC_VE2_PTSA_RATE);
|
|
|
|
mc_writel(p->isp_ptsa_min, MC_ISP_PTSA_MIN);
|
|
mc_writel(p->isp_ptsa_max, MC_ISP_PTSA_MAX);
|
|
mc_writel(p->isp_ptsa_rate, MC_ISP_PTSA_RATE);
|
|
|
|
exit:
|
|
mutex_unlock(&disp_and_camera_ptsa_lock);
|
|
|
|
return ret_code;
|
|
}
|
|
|
|
static int t21x_set_la(enum tegra_la_id id,
|
|
unsigned int bw_mbps)
|
|
{
|
|
int idx = cs->id_to_index[id];
|
|
struct la_client_info *ci = &cs->la_info_array[idx];
|
|
unsigned int la_to_set = 0;
|
|
|
|
if (is_display_client(id)) {
|
|
/* Display clients should be handled by
|
|
t21x_set_disp_la(...). */
|
|
return -1;
|
|
} else if (id == ID(MSENCSRD)) {
|
|
/* This is a special case. */
|
|
struct clk *emc_clk = clk_get_sys("tegra_emc", "emc");
|
|
unsigned int emc_freq_mhz;
|
|
unsigned int val_1 = 53;
|
|
unsigned int val_2 = 24;
|
|
|
|
if (IS_ERR(emc_clk))
|
|
return 0;
|
|
|
|
emc_freq_mhz = clk_get_rate(emc_clk) /
|
|
LA_HZ_TO_MHZ_FACTOR;
|
|
if (!emc_freq_mhz)
|
|
return 0;
|
|
|
|
if (210 > emc_freq_mhz)
|
|
val_1 = val_1 * 210 / emc_freq_mhz;
|
|
|
|
if (574 > emc_freq_mhz)
|
|
val_2 = val_2 * 574 / emc_freq_mhz;
|
|
|
|
la_to_set = min3((unsigned int)MC_LA_MAX_VALUE,
|
|
val_1,
|
|
val_2);
|
|
} else if (ci->la_ref_clk_mhz != 0) {
|
|
/* In this case we need to scale LA with emc frequency. */
|
|
struct clk *emc_clk = clk_get_sys("tegra_emc", "emc");
|
|
unsigned long emc_freq_mhz;
|
|
|
|
if (IS_ERR(emc_clk))
|
|
return 0;
|
|
|
|
emc_freq_mhz = clk_get_rate(emc_clk) /
|
|
(unsigned long)LA_HZ_TO_MHZ_FACTOR;
|
|
if (!emc_freq_mhz) {
|
|
pr_err("emc_freq_mhz is zero!!\n");
|
|
return 0;
|
|
}
|
|
|
|
if (ci->la_ref_clk_mhz <= emc_freq_mhz) {
|
|
la_to_set = min(ci->init_la,
|
|
(unsigned int)MC_LA_MAX_VALUE);
|
|
} else {
|
|
la_to_set = min((unsigned int)(ci->init_la *
|
|
ci->la_ref_clk_mhz / emc_freq_mhz),
|
|
(unsigned int)MC_LA_MAX_VALUE);
|
|
}
|
|
} else {
|
|
/* In this case we have a client with a static LA value. */
|
|
la_to_set = ci->init_la;
|
|
}
|
|
|
|
program_la(ci, la_to_set);
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int t21x_min_la(struct dc_to_la_params *disp_params)
|
|
{
|
|
unsigned int min_la_fp = disp_params->drain_time_usec_fp *
|
|
1000 /
|
|
cs->ns_per_tick;
|
|
|
|
/* round up */
|
|
if (min_la_fp % LA_FP_FACTOR != 0)
|
|
min_la_fp += LA_FP_FACTOR;
|
|
|
|
return LA_FP_TO_REAL(min_la_fp);
|
|
}
|
|
|
|
static int t21x_handle_disp_la(enum tegra_la_id id,
|
|
unsigned long emc_freq_hz,
|
|
unsigned int bw_mbps,
|
|
struct dc_to_la_params disp_params,
|
|
int write_la)
|
|
{
|
|
int idx = 0;
|
|
struct la_client_info *ci = NULL;
|
|
long long la_to_set = 0;
|
|
unsigned int dvfs_time_nsec = 0;
|
|
unsigned int dvfs_buffering_reqd_bytes = 0;
|
|
unsigned int thresh_dvfs_bytes = 0;
|
|
unsigned int total_buf_sz_bytes = 0;
|
|
int effective_mccif_buf_sz = 0;
|
|
long long la_bw_upper_bound_nsec_fp = 0;
|
|
long long la_bw_upper_bound_nsec = 0;
|
|
long long la_nsec = 0;
|
|
|
|
if (!is_display_client(id)) {
|
|
/* Non-display clients should be handled by t21x_set_la(...). */
|
|
return -1;
|
|
}
|
|
|
|
mutex_lock(&disp_and_camera_ptsa_lock);
|
|
total_dc0_bw = disp_params.total_dc0_bw;
|
|
total_dc1_bw = disp_params.total_dc1_bw;
|
|
cs->update_display_ptsa_rate(cs->disp_bw_array);
|
|
mutex_unlock(&disp_and_camera_ptsa_lock);
|
|
|
|
idx = cs->id_to_index[id];
|
|
ci = &cs->la_info_array[idx];
|
|
la_to_set = 0;
|
|
dvfs_time_nsec =
|
|
tegra_get_dvfs_clk_change_latency_nsec(emc_freq_hz / 1000);
|
|
dvfs_buffering_reqd_bytes = bw_mbps *
|
|
dvfs_time_nsec /
|
|
LA_USEC_TO_NSEC_FACTOR;
|
|
|
|
thresh_dvfs_bytes =
|
|
disp_params.thresh_lwm_bytes +
|
|
dvfs_buffering_reqd_bytes +
|
|
disp_params.spool_up_buffering_adj_bytes;
|
|
total_buf_sz_bytes =
|
|
cs->disp_clients[DISP_CLIENT_LA_ID(id)].line_buf_sz_bytes +
|
|
cs->disp_clients[DISP_CLIENT_LA_ID(id)].mccif_size_bytes;
|
|
effective_mccif_buf_sz =
|
|
(cs->disp_clients[DISP_CLIENT_LA_ID(id)].line_buf_sz_bytes >
|
|
thresh_dvfs_bytes) ?
|
|
cs->disp_clients[DISP_CLIENT_LA_ID(id)].mccif_size_bytes :
|
|
total_buf_sz_bytes - thresh_dvfs_bytes;
|
|
|
|
if (effective_mccif_buf_sz < 0)
|
|
return -1;
|
|
|
|
la_bw_upper_bound_nsec_fp = (long long)effective_mccif_buf_sz *
|
|
LA_FP_FACTOR /
|
|
bw_mbps;
|
|
la_bw_upper_bound_nsec_fp = la_bw_upper_bound_nsec_fp *
|
|
LA_FP_FACTOR /
|
|
LA_DISP_CATCHUP_FACTOR_FP;
|
|
la_bw_upper_bound_nsec_fp =
|
|
la_bw_upper_bound_nsec_fp -
|
|
(LA_ST_LA_MINUS_SNAP_ARB_TO_ROW_SRT_EMCCLKS_FP +
|
|
EXP_TIME_EMCCLKS_FP) /
|
|
(emc_freq_hz / LA_HZ_TO_MHZ_FACTOR);
|
|
la_bw_upper_bound_nsec_fp *= LA_USEC_TO_NSEC_FACTOR;
|
|
la_bw_upper_bound_nsec = LA_FP_TO_REAL(la_bw_upper_bound_nsec_fp);
|
|
|
|
|
|
la_nsec = min(la_bw_upper_bound_nsec,
|
|
(long long)MAX_LA_NSEC);
|
|
|
|
la_to_set = min((long long)(la_nsec/cs->ns_per_tick),
|
|
(long long)MC_LA_MAX_VALUE);
|
|
|
|
if ((la_to_set < t21x_min_la(&disp_params))
|
|
|| (la_to_set > MC_LA_MAX_VALUE))
|
|
return -1;
|
|
|
|
if (write_la)
|
|
program_la(ci, la_to_set);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int t21x_set_disp_la(enum tegra_la_id id,
|
|
unsigned long emc_freq_hz,
|
|
unsigned int bw_mbps,
|
|
struct dc_to_la_params disp_params)
|
|
{
|
|
return t21x_handle_disp_la(id, emc_freq_hz, bw_mbps, disp_params, 1);
|
|
}
|
|
|
|
static int t21x_check_disp_la(enum tegra_la_id id,
|
|
unsigned long emc_freq_hz,
|
|
unsigned int bw_mbps,
|
|
struct dc_to_la_params disp_params)
|
|
{
|
|
return t21x_handle_disp_la(id, emc_freq_hz, bw_mbps, disp_params, 0);
|
|
}
|
|
|
|
void program_scaled_la_t21x(struct la_client_info *ci, int la)
|
|
{
|
|
unsigned long reg_write;
|
|
|
|
if (ci->id == ID(DISPLAY_0A)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A,
|
|
(u32)reg_write);
|
|
} else if (ci->id == ID(DISPLAY_0AB)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB,
|
|
(u32)reg_write);
|
|
} else if (ci->id == ID(DISPLAY_0B)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B,
|
|
(u32)reg_write);
|
|
} else if (ci->id == ID(DISPLAY_0BB)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB,
|
|
(u32)reg_write);
|
|
} else if (ci->id == ID(DISPLAY_0C)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C,
|
|
(u32)reg_write);
|
|
} else if (ci->id == ID(DISPLAY_0CB)) {
|
|
reg_write =
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB_LOW_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB_LOW_MASK) |
|
|
((la << MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB_HIGH_SHIFT) &
|
|
MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB_HIGH_MASK);
|
|
mc_writel(reg_write, MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB);
|
|
la_debug("reg_addr=0x%x, write=0x%x",
|
|
(u32)(uintptr_t)MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB,
|
|
(u32)reg_write);
|
|
}
|
|
}
|
|
|
|
void tegra_la_get_t21x_specific(struct la_chip_specific *cs_la)
|
|
{
|
|
int i = 0;
|
|
|
|
if (is_t210b01_soc()) {
|
|
/* Fixup t21x_la_info_array for t210b01 */
|
|
for (i = 0; i < ARRAY_SIZE(t21x_la_info_array); i++) {
|
|
if (t21x_la_info_array[i].id == ID(ISP_RA))
|
|
t21x_la_info_array[i].la_ref_clk_mhz = 600;
|
|
else if (t21x_la_info_array[i].id == ID(ISP_RAB))
|
|
t21x_la_info_array[i].la_ref_clk_mhz = 248;
|
|
}
|
|
}
|
|
|
|
cs_la->ns_per_tick = 30;
|
|
cs_la->atom_size = 64;
|
|
cs_la->la_max_value = MC_LA_MAX_VALUE;
|
|
cs_la->la_info_array = t21x_la_info_array;
|
|
cs_la->la_info_array_size = ARRAY_SIZE(t21x_la_info_array);
|
|
|
|
cs_la->la_params.fp_factor = LA_FP_FACTOR;
|
|
cs_la->la_params.la_real_to_fp = la_real_to_fp;
|
|
cs_la->la_params.la_fp_to_real = la_fp_to_real;
|
|
cs_la->la_params.static_la_minus_snap_arb_to_row_srt_emcclks_fp =
|
|
LA_ST_LA_MINUS_SNAP_ARB_TO_ROW_SRT_EMCCLKS_FP;
|
|
cs_la->la_params.dram_width_bits = LA_DRAM_WIDTH_BITS;
|
|
cs_la->la_params.disp_catchup_factor_fp = LA_DISP_CATCHUP_FACTOR_FP;
|
|
|
|
cs_la->init_ptsa = t21x_init_ptsa;
|
|
cs_la->update_display_ptsa_rate = t21x_update_display_ptsa_rate;
|
|
cs_la->update_camera_ptsa_rate = t21x_update_camera_ptsa_rate;
|
|
cs_la->set_init_la = t21x_set_la;
|
|
cs_la->set_dynamic_la = t21x_set_la;
|
|
cs_la->set_disp_la = t21x_set_disp_la;
|
|
cs_la->check_disp_la = t21x_check_disp_la;
|
|
cs_la->save_ptsa = save_ptsa;
|
|
cs_la->program_ptsa = program_ptsa;
|
|
cs_la->suspend = la_suspend;
|
|
cs_la->resume = la_resume;
|
|
cs = cs_la;
|
|
|
|
if (ON_LPDDR4()) {
|
|
emc_min_freq_mhz_fp = 25000;
|
|
emc_min_freq_mhz = 25;
|
|
emc_max_freq_mhz = 2132;
|
|
hi_gd_fp = 1500;
|
|
lo_gd_fp = 18;
|
|
hi_gd_fpa = 14998;
|
|
lo_gd_fpa = 176;
|
|
dda_div = 1;
|
|
} else {
|
|
emc_min_freq_mhz_fp = 12500;
|
|
emc_min_freq_mhz = 12;
|
|
emc_max_freq_mhz = 1200;
|
|
hi_gd_fp = 2000;
|
|
lo_gd_fp = 21;
|
|
hi_gd_fpa = 19998;
|
|
lo_gd_fpa = 208;
|
|
dda_div = 2;
|
|
}
|
|
|
|
low_freq_bw = emc_min_freq_mhz_fp * 2 * LA_DRAM_WIDTH_BITS / 8;
|
|
low_freq_bw /= 1000;
|
|
tegra_la_disp_clients_info = cs_la->disp_clients;
|
|
|
|
/* set some entries to zero */
|
|
for (i = 0; i < NUM_CAMERA_CLIENTS; i++)
|
|
cs_la->camera_bw_array[i] = 0;
|
|
for (i = 0; i < TEGRA_LA_AGG_CAMERA_NUM_CLIENTS; i++) {
|
|
cs_la->agg_camera_array[i].bw_fp = 0;
|
|
cs_la->agg_camera_array[i].frac_fp = 0;
|
|
cs_la->agg_camera_array[i].ptsa_min = 0;
|
|
cs_la->agg_camera_array[i].ptsa_max = 0;
|
|
cs_la->agg_camera_array[i].is_hiso = false;
|
|
}
|
|
|
|
/* set mccif_size_bytes values */
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0A)].mccif_size_bytes = 6144;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0B)].mccif_size_bytes = 6144;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0C)].mccif_size_bytes =
|
|
11520;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAYD)].mccif_size_bytes = 4672;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_T)].mccif_size_bytes = 4672;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HC)].mccif_size_bytes = 4992;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0AB)].mccif_size_bytes =
|
|
11520;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0BB)].mccif_size_bytes =
|
|
6144;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0CB)].mccif_size_bytes =
|
|
6144;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HCB)].mccif_size_bytes =
|
|
4992;
|
|
|
|
/* set line_buf_sz_bytes values */
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0A)].line_buf_sz_bytes =
|
|
151552;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0B)].line_buf_sz_bytes =
|
|
112640;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0C)].line_buf_sz_bytes =
|
|
112640;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAYD)].line_buf_sz_bytes = 18432;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_T)].line_buf_sz_bytes =
|
|
18432;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HC)].line_buf_sz_bytes = 320;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0AB)].line_buf_sz_bytes =
|
|
112640;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0BB)].line_buf_sz_bytes =
|
|
112640;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0CB)].line_buf_sz_bytes =
|
|
112640;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HCB)].line_buf_sz_bytes =
|
|
320;
|
|
|
|
/* set win_type values */
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0A)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULL;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0B)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULLA;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0C)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULLA;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAYD)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_SIMPLE;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HC)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_CURSOR;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_T)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_SIMPLE;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0AB)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULLB;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0BB)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULLB;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_0CB)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_FULLB;
|
|
cs_la->disp_clients[DISP_CLIENT_ID(DISPLAY_HCB)].win_type =
|
|
TEGRA_LA_DISP_WIN_TYPE_CURSOR;
|
|
}
|