hdmitx21: update to use hdmitx_common api [1/1]

PD#SWPL-138534

Problem:
tx20/tx21 have different valid mode flow and api

Solution:
use common api instead

Verify:
verify on T7

Test:
DRM-TX-19, DRM-TX-20,DRM-TX-22, DRM-TX-25, DRM-TX-27

Change-Id: I008e5931adb223391e79149f908d5ad1cb186889
Signed-off-by: sky zhou <sky.zhou@amlogic.com>
This commit is contained in:
sky zhou
2023-09-01 17:21:43 +08:00
committed by Luan Yuan
parent 7677a3e073
commit abbc625178
17 changed files with 306 additions and 1145 deletions
+17 -221
View File
@@ -7,183 +7,11 @@
#include <linux/string.h>
#include <linux/amlogic/media/vout/hdmi_tx21/hdmi_tx_module.h>
struct hdmi_format_para *para;
static struct hdmi_format_para fmt_para_non_hdmi_fmt = {
.timing = {
.vic = HDMI_0_UNKNOWN,
.name = "invalid",
.sname = "invalid",
.pixel_repetition_factor = 0,
.pi_mode = 1,
.h_pict = 16,
.v_pict = 9,
},
};
static struct parse_cd parse_cd_[] = {
{COLORDEPTH_24B, "8bit",},
{COLORDEPTH_30B, "10bit"},
{COLORDEPTH_36B, "12bit"},
{COLORDEPTH_48B, "16bit"},
};
static struct parse_cs parse_cs_[] = {
{HDMI_COLORSPACE_RGB, "rgb",},
{HDMI_COLORSPACE_YUV422, "422",},
{HDMI_COLORSPACE_YUV444, "444",},
{HDMI_COLORSPACE_YUV420, "420",},
};
static struct parse_cr parse_cr_[] = {
{HDMI_QUANTIZATION_RANGE_LIMITED, "limit",},
{HDMI_QUANTIZATION_RANGE_FULL, "full",},
};
/* parse the name string to cs/cd/cr */
static void _parse_hdmi_attr(char const *name,
enum hdmi_colorspace *cs,
enum hdmi_color_depth *cd,
enum hdmi_quantization_range *cr)
{
int i;
if (!cs || !cd || !cr)
return;
if (!name) {
/* assign defalut value*/
*cs = HDMI_COLORSPACE_RGB;
*cd = COLORDEPTH_24B;
*cr = HDMI_QUANTIZATION_RANGE_FULL;
return;
}
/* parse color depth */
for (i = 0; i < sizeof(parse_cd_) / sizeof(struct parse_cd); i++) {
if (strstr(name, parse_cd_[i].name)) {
*cd = parse_cd_[i].cd;
break;
}
}
/* set default value */
if (i == sizeof(parse_cd_) / sizeof(struct parse_cd))
*cd = COLORDEPTH_24B;
/* parse color space */
for (i = 0; i < sizeof(parse_cs_) / sizeof(struct parse_cs); i++) {
if (strstr(name, parse_cs_[i].name)) {
*cs = parse_cs_[i].cs;
break;
}
}
/* set default value */
if (i == sizeof(parse_cs_) / sizeof(struct parse_cs))
*cs = HDMI_COLORSPACE_RGB;
/* parse color range */
for (i = 0; i < sizeof(parse_cr_) / sizeof(struct parse_cr); i++) {
if (strstr(name, parse_cr_[i].name)) {
*cr = parse_cr_[i].cr;
break;
}
}
/* set default value */
if (i == sizeof(parse_cr_) / sizeof(struct parse_cr))
*cr = HDMI_QUANTIZATION_RANGE_FULL;
}
static u32 _calc_tmds_clk(u32 pixel_freq, enum hdmi_colorspace cs,
enum hdmi_color_depth cd)
{
u32 tmds_clk = pixel_freq;
if (cs == HDMI_COLORSPACE_YUV420)
tmds_clk = tmds_clk / 2;
if (cs != HDMI_COLORSPACE_YUV422) {
switch (cd) {
case COLORDEPTH_48B:
tmds_clk *= 2;
break;
case COLORDEPTH_36B:
tmds_clk = tmds_clk * 3 / 2;
break;
case COLORDEPTH_30B:
tmds_clk = tmds_clk * 5 / 4;
break;
case COLORDEPTH_24B:
default:
break;
}
}
return tmds_clk;
}
struct hdmi_format_para *hdmitx21_get_vesa_paras(struct vesa_standard_timing *t)
{
return NULL;
}
static int hdmitx21_construct_format_para_from_timing(const struct hdmi_timing *timing,
struct hdmi_format_para *para)
{
para->vic = timing->vic;
para->name = timing->name;
para->sname = timing->sname;
para->timing = *timing;
para->tmds_clk = _calc_tmds_clk(para->timing.pixel_freq, para->cs, para->cd);
if (timing->vic == HDMIV_2560x1600p60hz) {
para->tmds_clk_div40 = 0;
para->scrambler_en = 0;
} else {
if (timing->pixel_freq > 340000) {
para->tmds_clk_div40 = 1;
para->scrambler_en = 1;
} else {
para->tmds_clk_div40 = 0;
para->scrambler_en = 0;
}
}
para->frac_mode = 0;
return 0;
}
/*
* Parameter 'name' can should be full name as 1920x1080p60hz,
* 3840x2160p60hz, etc
* attr strings likes as '444,8bit'
*/
int hdmi21_get_fmt_para(enum hdmi_vic vic,
const char *attr, struct hdmi_format_para *para)
{
const struct hdmi_timing *timing = NULL;
memcpy(para, &fmt_para_non_hdmi_fmt, sizeof(struct hdmi_format_para));
if (!attr)
return -EINVAL;
if (!para) {
pr_err("%s should pass valid para pointer to save\n", __func__);
return -EINVAL;
}
timing = hdmitx_mode_vic_to_hdmi_timing(vic);
if (!timing) {
pr_err("%s: get timing from vic (%d) fail\n", __func__, vic);
return -EINVAL;
}
_parse_hdmi_attr(attr, &para->cs, &para->cd, &para->cr);
hdmitx21_construct_format_para_from_timing(timing, para);
return 0;
}
/* Recommended N and Expected CTS for 32kHz */
static const struct hdmi_audio_fs_ncts aud_32k_para = {
.array[0] = {
@@ -602,55 +430,23 @@ u32 hdmi21_get_aud_n_paras(enum hdmi_audio_fs fs,
return n * N_multiples;
}
bool _is_hdmi14_4k(enum hdmi_vic vic)
{
bool ret = 0;
int i;
enum hdmi_vic hdmi14_4k[] = {
HDMI_93_3840x2160p24_16x9,
HDMI_94_3840x2160p25_16x9,
HDMI_95_3840x2160p30_16x9,
HDMI_98_4096x2160p24_256x135,
};
/* for csc coef */
static const u8 coef_yc444_rgb_24bit_601[] = {
0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e,
0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a,
0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b
};
for (i = 0; i < ARRAY_SIZE(hdmi14_4k); i++) {
if (vic == hdmi14_4k[i]) {
ret = 1;
break;
}
}
static const u8 coef_yc444_rgb_24bit_709[] = {
0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7,
0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d,
0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25
};
return ret;
}
static const struct hdmi_csc_coef_table hdmi_csc_coef[] = {
{HDMI_COLORSPACE_YUV444, HDMI_COLORSPACE_RGB, COLORDEPTH_24B, 0,
sizeof(coef_yc444_rgb_24bit_601), coef_yc444_rgb_24bit_601},
{HDMI_COLORSPACE_YUV444, HDMI_COLORSPACE_RGB, COLORDEPTH_24B, 1,
sizeof(coef_yc444_rgb_24bit_709), coef_yc444_rgb_24bit_709},
};
bool _is_y420_vic(enum hdmi_vic vic)
{
int i;
enum hdmi_vic y420_vic[] = {
HDMI_96_3840x2160p50_16x9,
HDMI_97_3840x2160p60_16x9,
HDMI_101_4096x2160p50_256x135,
HDMI_102_4096x2160p60_256x135,
HDMI_106_3840x2160p50_64x27,
HDMI_107_3840x2160p60_64x27,
};
const struct hdmi_timing *timing;
for (i = 0; i < ARRAY_SIZE(y420_vic); i++) {
if (vic == y420_vic[i]) {
return 1;
}
}
/* In Spec2.1 Table 7-34, greater than 2160p30hz will support y420 */
timing = hdmitx_mode_vic_to_hdmi_timing(vic);
if (!timing)
return 0;
if (timing->v_active >= 2160 && timing->v_freq > 30000)
return 1;
if (timing->v_active >= 4320)
return 1;
return 0;
}
+1 -14
View File
@@ -83,7 +83,7 @@ void hdmitx21_disable_clk(struct hdmitx_dev *hdev);
u32 hdcp21_rd_hdcp22_ver(void);
void hdmitx_infoframe_send(u16 info_type, u8 *body);
/* there are 2 ways to send out infoframes
/* there are 2 ways to send out infoframe
* xxx_infoframe_set() will take use of struct xxx_infoframe_set
* xxx_infoframe_rawset() will directly send with rawdata
* if info, hb, or pb == NULL, disable send infoframe
@@ -260,18 +260,6 @@ enum vrr_component_conf {
CONF_BASE_REFRESH_RATE,
};
/* CONF_AVI_BT2020 */
#define CLR_AVI_BT2020 0x0
#define SET_AVI_BT2020 0x1
/* CONF_AVI_Q01 */
#define RGB_RANGE_DEFAULT 0
#define RGB_RANGE_LIM 1
#define RGB_RANGE_FUL 2
#define RGB_RANGE_RSVD 3
/* CONF_AVI_YQ01 */
#define YCC_RANGE_LIM 0
#define YCC_RANGE_FUL 1
#define YCC_RANGE_RSVD 2
void hdmi_avi_infoframe_config(enum avi_component_conf conf, u8 val);
int hdmitx_infoframe_rawget(u16 info_type, u8 *body);
@@ -423,7 +411,6 @@ void hdmitx_setupirqs(struct hdmitx_dev *phdev);
void ddc_toggle_sw_tpi(void);
bool hdmitx_ddcm_read(u8 seg_index, u8 slave_addr, u8 reg_addr, u8 *p_buf, u16 len);
bool hdmitx_ddcm_write(u8 seg_index, u8 slave_addr, u8 reg_addr, u8 data);
bool is_cur_mode_hdmi(void);
extern unsigned long hdcp_reauth_dbg;
extern unsigned long streamtype_dbg;
@@ -230,7 +230,6 @@ int hdmitx21_set_audio(struct hdmitx_dev *hdev,
struct hdmitx_audpara *audio_param)
{
int i, ret = -1;
/* struct hdmi_audio_infoframe *info = &hdev->infoframes.aud.audio; */
u8 CHAN_STAT_BUF[24 * 2];
u32 hdmi_ch = hdev->hdmi_ch;
+2 -279
View File
@@ -1126,7 +1126,7 @@ static int edid_parsingy420vdb(struct rx_cap *prxcap, u8 *buf)
pos++;
while (pos < data_end) {
if (_is_y420_vic(buf[pos])) {
if (hdmitx_edid_check_y420_support(prxcap, buf[pos])) {
store_cea_idx(prxcap, buf[pos]);
store_y420_idx(prxcap, buf[pos]);
}
@@ -1426,7 +1426,7 @@ static int edid_y420cmdb_postprocess(struct hdmitx_dev *hdev)
for (j = 0; j < 8; j++) {
valid = ((*p >> j) & 0x1);
vic = prxcap->VIC[i * 8 + j];
if (valid != 0 && _is_y420_vic(vic)) {
if (valid != 0 && hdmitx_edid_check_y420_support(prxcap, vic)) {
store_cea_idx(prxcap, vic);
store_y420_idx(prxcap, vic);
}
@@ -2798,283 +2798,6 @@ int hdmitx21_edid_parse(struct hdmitx_dev *hdmitx_device)
return 0;
}
enum hdmi_vic hdmitx21_edid_vic_tab_map_vic(const char *disp_mode)
{
const struct hdmi_timing *timing = NULL;
enum hdmi_vic vic = HDMI_0_UNKNOWN;
timing = hdmitx_mode_match_timing_name(disp_mode);
if (timing)
vic = timing->vic;
return vic;
}
const char *hdmitx21_edid_vic_to_string(enum hdmi_vic vic)
{
const struct hdmi_timing *timing = NULL;
const char *disp_str = NULL;
timing = hdmitx_mode_vic_to_hdmi_timing(vic);
if (timing)
disp_str = timing->name;
return disp_str;
}
static bool is_rx_support_y420(struct hdmitx_dev *hdev, enum hdmi_vic vic)
{
int i;
struct rx_cap *prxcap = &hdev->tx_comm.rxcap;
const struct hdmi_timing *timing;
for (i = 0; i < Y420_VIC_MAX_NUM; i++) {
if (prxcap->y420_vic[i] == vic)
return 1;
}
/* In Spec2.1 Table 7-34, greater than 2160p30hz will support y420 */
timing = hdmitx_mode_vic_to_hdmi_timing(vic);
if (!timing)
return 0;
if (timing->v_active >= 2160 && timing->v_freq > 30000)
return 1;
if (timing->v_active >= 4320)
return 1;
return 0;
}
static bool hdmitx_check_4x3_16x9_mode(struct hdmitx_dev *hdev,
enum hdmi_vic vic)
{
bool flag = 0;
int j;
struct rx_cap *prxcap = NULL;
prxcap = &hdev->tx_comm.rxcap;
if (vic == HDMI_2_720x480p60_4x3 ||
vic == HDMI_6_720x480i60_4x3 ||
vic == HDMI_17_720x576p50_4x3 ||
vic == HDMI_21_720x576i50_4x3) {
for (j = 0; (j < prxcap->VIC_count) && (j < VIC_MAX_NUM); j++) {
if ((vic + 1) == (prxcap->VIC[j] & 0xff)) {
flag = 1;
break;
}
}
} else if (vic == HDMI_3_720x480p60_16x9 ||
vic == HDMI_7_720x480i60_16x9 ||
vic == HDMI_18_720x576p50_16x9 ||
vic == HDMI_22_720x576i50_16x9) {
for (j = 0; (j < prxcap->VIC_count) && (j < VIC_MAX_NUM); j++) {
if ((vic - 1) == (prxcap->VIC[j] & 0xff)) {
flag = 1;
break;
}
}
}
return flag;
}
/* For some TV's EDID, there maybe exist some information ambiguous.
* Such as EDID declare support 2160p60hz(Y444 8bit), but no valid
* Max_TMDS_Clock2 to indicate that it can support 5.94G signal.
*/
bool hdmitx21_edid_check_valid_mode(struct hdmitx_dev *hdev,
struct hdmi_format_para *para)
{
bool valid = 0;
struct rx_cap *prxcap = NULL;
const struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
u32 rx_max_tmds_clk = 0;
u32 calc_tmds_clk = 0;
int i = 0;
int svd_flag = 0;
/* Default max color depth is 24 bit */
enum hdmi_color_depth rx_y444_max_dc = COLORDEPTH_24B;
enum hdmi_color_depth rx_rgb_max_dc = COLORDEPTH_24B;
u32 rx_frl_bandwidth = 0;
u32 tx_frl_bandwidth = 0;
const struct hdmi_timing *timing;
if (!hdev || !para)
return 0;
/* if current limits to 1080p, here will check the freshrate and
* 4k resolution
*/
if (hdmitx21_limited_1080p()) {
if (hdmitx21_is_vic_over_limited_1080p(para->timing.vic)) {
pr_err("over limited vic%d in %s\n", para->timing.vic,
__func__);
return 0;
}
}
prxcap = &hdev->tx_comm.rxcap;
/* exclude such as: 2160p60hz YCbCr444 10bit */
if (hdev->data->chip_type < MESON_CPU_ID_S5) //todo, not in parse
prxcap->max_frl_rate = 0; //t7 not support frl
switch (para->timing.vic) {
case HDMI_96_3840x2160p50_16x9:
case HDMI_97_3840x2160p60_16x9:
case HDMI_101_4096x2160p50_256x135:
case HDMI_102_4096x2160p60_256x135:
case HDMI_106_3840x2160p50_64x27:
case HDMI_107_3840x2160p60_64x27:
if (para->cs == HDMI_COLORSPACE_RGB ||
para->cs == HDMI_COLORSPACE_YUV444)
if (para->cd != COLORDEPTH_24B && !prxcap->max_frl_rate)
return 0;
break;
case HDMI_7_720x480i60_16x9:
case HDMI_22_720x576i50_16x9:
if (para->cs == HDMI_COLORSPACE_YUV422)
return 0;
default:
break;
}
/* DVI case, only 8bit */
if (prxcap->ieeeoui != HDMI_IEEE_OUI) {
if (para->cd != COLORDEPTH_24B)
return 0;
}
/* target mode is not contained at RX SVD */
for (i = 0; (i < prxcap->VIC_count) && (i < VIC_MAX_NUM); i++) {
if ((para->timing.vic & 0xff) == (prxcap->VIC[i] & 0xff)) {
svd_flag = 1;
break;
} else if (hdmitx_check_4x3_16x9_mode(hdev, para->timing.vic & 0xff)) {
svd_flag = 1;
break;
}
}
if (svd_flag == 0)
return 0;
/* Get RX Max_TMDS_Clock */
if (prxcap->Max_TMDS_Clock2) {
rx_max_tmds_clk = prxcap->Max_TMDS_Clock2 * 5;
} else {
/* Default min is 74.25 / 5 */
if (prxcap->Max_TMDS_Clock1 < 0xf)
prxcap->Max_TMDS_Clock1 = 0x1e;
rx_max_tmds_clk = prxcap->Max_TMDS_Clock1 * 5;
}
/* if current status already limited to 1080p, so here also needs to
* limit the rx_max_tmds_clk as 150 * 1.5 = 225 to make the valid mode
* checking works
*/
if (hdmitx21_limited_1080p()) {
if (rx_max_tmds_clk > 225)
rx_max_tmds_clk = 225;
}
calc_tmds_clk = para->tmds_clk / 1000;
if (hdev->data->chip_type < MESON_CPU_ID_S5) //todo, not in parse
rx_frl_bandwidth = 0;
else
rx_frl_bandwidth = get_frl_bandwidth(prxcap->max_frl_rate);
timing = hdmitx_mode_vic_to_hdmi_timing(para->timing.vic);
if (!timing)
return 0;
/* tx_frl_bandwidth = timing->pixel_freq / 1000 * 24 * 1.122 */
if (hdev->data->chip_type < MESON_CPU_ID_S5) { //todo, not in parse
tx_frl_bandwidth = 0;
} else {
tx_frl_bandwidth = calc_frl_bandwidth(timing->pixel_freq / 1000,
para->cs, para->cd);
if (tx_frl_bandwidth > get_frl_bandwidth(hdev->tx_max_frl_rate))
return 0;
}
if (calc_tmds_clk < rx_max_tmds_clk || tx_frl_bandwidth <= rx_frl_bandwidth)
valid = 1;
else
return 0;
if (para->cs == HDMI_COLORSPACE_YUV444) {
/* Rx may not support Y444 */
if (!(prxcap->native_Mode & (1 << 5)))
return 0;
if (prxcap->dc_y444 && (prxcap->dc_30bit ||
dv->sup_10b_12b_444 == 0x1))
rx_y444_max_dc = COLORDEPTH_30B;
if (prxcap->dc_y444 && (prxcap->dc_36bit ||
dv->sup_10b_12b_444 == 0x2))
rx_y444_max_dc = COLORDEPTH_36B;
if (para->cd <= rx_y444_max_dc)
valid = 1;
else
valid = 0;
return valid;
}
if (para->cs == HDMI_COLORSPACE_YUV422) {
/* Rx may not support Y422 */
if (!(prxcap->native_Mode & (1 << 4)))
return 0;
return 1;
}
if (para->cs == HDMI_COLORSPACE_RGB) {
/* Always assume RX supports RGB444 */
if (prxcap->dc_30bit || dv->sup_10b_12b_444 == 0x1)
rx_rgb_max_dc = COLORDEPTH_30B;
if (prxcap->dc_36bit || dv->sup_10b_12b_444 == 0x2)
rx_rgb_max_dc = COLORDEPTH_36B;
if (para->cd <= rx_rgb_max_dc)
valid = 1;
else
valid = 0;
return valid;
}
if (para->cs == HDMI_COLORSPACE_YUV420) {
if (!is_rx_support_y420(hdev, para->timing.vic))
return 0;
if (!prxcap->dc_30bit_420)
if (para->cd == COLORDEPTH_30B)
return 0;
if (!prxcap->dc_36bit_420)
if (para->cd == COLORDEPTH_36B)
return 0;
valid = 1;
}
return valid;
}
/* force_flag: 0 means check with RX's edid */
/* 1 means no check which RX's edid */
enum hdmi_vic hdmitx21_edid_get_VIC(struct hdmitx_dev *hdev,
const char *disp_mode,
char force_flag)
{
struct rx_cap *prxcap = &hdev->tx_comm.rxcap;
int j;
enum hdmi_vic vic = hdmitx21_edid_vic_tab_map_vic(disp_mode);
enum hdmi_vic vesa_vic;
if (vic >= HDMITX_VESA_OFFSET)
vesa_vic = vic;
else
vesa_vic = HDMI_0_UNKNOWN;
if (vic != HDMI_0_UNKNOWN) {
if (force_flag == 0) {
for (j = 0; j < prxcap->VIC_count; j++) {
if (prxcap->VIC[j] == vic)
break;
}
if (j >= prxcap->VIC_count)
vic = HDMI_0_UNKNOWN;
}
}
return vic;
}
/* Clear HDMI Hardware Module EDID RAM and EDID Buffer */
void hdmitx21_edid_ram_buffer_clear(struct hdmitx_dev *hdmitx_device)
{
+2 -16
View File
@@ -81,27 +81,13 @@ EXPORT_SYMBOL(get_hdmitx_phy_addr);
void get_attr(char attr[16])
{
#if defined(CONFIG_AMLOGIC_HDMITX)
if (get_hdmitx20_init() == 1)
pr_err("Not support tx20 %s anymore.\n", __func__);
#endif
#if defined(CONFIG_AMLOGIC_HDMITX21)
if (get_hdmitx21_init() == 1)
get21_attr(attr);
#endif
pr_err("Not support tx20 %s anymore.\n", __func__);
}
EXPORT_SYMBOL(get_attr);
void setup_attr(const char *buf)
{
#if defined(CONFIG_AMLOGIC_HDMITX)
if (get_hdmitx20_init() == 1)
pr_err("Not support tx20 %s anymore.\n", __func__);
#endif
#if defined(CONFIG_AMLOGIC_HDMITX21)
if (get_hdmitx21_init() == 1)
setup21_attr(buf);
#endif
pr_err("Not support tx20 %s anymore.\n", __func__);
}
EXPORT_SYMBOL(setup_attr);
@@ -29,8 +29,6 @@ int hdmitx20_event_notifier_unregist(struct notifier_block *nb);
int get_hdmitx20_init(void);
int get20_hpd_state(void);
struct vsdb_phyaddr *get_hdmitx20_phy_addr(void);
void setup20_attr(const char *buf);
void get20_attr(char attr[16]);
void hdmitx20_audio_mute_op(unsigned int flag);
void hdmitx20_video_mute_op(unsigned int flag);
void hdmitx20_ext_set_audio_output(int enable);
@@ -46,8 +44,6 @@ int hdmitx21_event_notifier_unregist(struct notifier_block *nb);
int get_hdmitx21_init(void);
int get21_hpd_state(void);
struct vsdb_phyaddr *get_hdmitx21_phy_addr(void);
void get21_attr(char attr[16]);
void setup21_attr(const char *buf);
void hdmitx21_video_mute_op(u32 flag, unsigned int path);
void hdmitx21_audio_mute_op(u32 flag, unsigned int path);
void hdmitx21_ext_set_audio_output(int enable);
+2 -55
View File
@@ -24,59 +24,6 @@ ulong g_flt_1_e; /* record the clear time of FLT_UPDATE */
static bool frl_schedule_work(struct frl_train_t *p, u32 delay_ms, u32 period_ms);
static bool frl_stop_work(struct frl_train_t *p);
/* get the corresponding bandwidth of current FRL_RATE, Unit: MHz */
u32 get_frl_bandwidth(const enum frl_rate_enum rate)
{
const u32 frl_bandwidth[] = {
[FRL_NONE] = 0,
[FRL_3G3L] = 9000,
[FRL_6G3L] = 18000,
[FRL_6G4L] = 24000,
[FRL_8G4L] = 32000,
[FRL_10G4L] = 40000,
[FRL_12G4L] = 48000,
};
if (rate > FRL_12G4L)
return 0;
return frl_bandwidth[rate];
}
u32 calc_frl_bandwidth(u32 pixel_freq, enum hdmi_colorspace cs,
enum hdmi_color_depth cd)
{
u32 bandwidth;
bandwidth = calc_tmds_bandwidth(pixel_freq, cs, cd);
/* bandwidth = tmds_bandwidth * 24 * 1.122 */
bandwidth = bandwidth * 24;
bandwidth = bandwidth * 561 / 500;
return bandwidth;
}
u32 calc_tmds_bandwidth(u32 pixel_freq, enum hdmi_colorspace cs,
enum hdmi_color_depth cd)
{
u32 bandwidth = pixel_freq;
if (cs == HDMI_COLORSPACE_YUV420)
bandwidth /= 2;
if (cs != HDMI_COLORSPACE_YUV422) {
if (cd == COLORDEPTH_48B)
bandwidth = bandwidth * 2;
else if (cd == COLORDEPTH_36B)
bandwidth = bandwidth * 3 / 2;
else if (cd == COLORDEPTH_30B)
bandwidth = bandwidth * 5 / 4;
else
bandwidth = bandwidth * 1;
}
return bandwidth;
}
/* for legacy HDMI2.0 or earlier modes, still select TMDS */
/* TODO DSC modes */
enum frl_rate_enum hdmitx21_select_frl_rate(bool dsc_en, enum hdmi_vic vic,
@@ -92,7 +39,7 @@ enum frl_rate_enum hdmitx21_select_frl_rate(bool dsc_en, enum hdmi_vic vic,
if (!timing)
return FRL_NONE;
tx_tmds_bandwidth = calc_tmds_bandwidth(timing->pixel_freq / 1000, cs, cd);
tx_tmds_bandwidth = hdmitx_calc_tmds_clk(timing->pixel_freq / 1000, cs, cd);
pr_info("Hactive=%d Vactive=%d Vfreq=%d TMDS_BandWidth=%d\n",
timing->h_active, timing->v_active,
timing->v_freq, tx_tmds_bandwidth);
@@ -106,7 +53,7 @@ enum frl_rate_enum hdmitx21_select_frl_rate(bool dsc_en, enum hdmi_vic vic,
tx_frl_bandwidth = tx_tmds_bandwidth * 24;
tx_frl_bandwidth = tx_frl_bandwidth * 561 / 500;
for (rate = FRL_3G3L; rate < FRL_12G4L + 1; rate++) {
if (tx_frl_bandwidth <= get_frl_bandwidth(rate)) {
if (tx_frl_bandwidth <= hdmitx_get_frl_bandwidth(rate)) {
pr_info("select frl_rate as %d\n", rate);
return rate;
}
+117 -399
View File
@@ -63,6 +63,7 @@
#include <hdmitx_drm_hook.h>
#include <hdmitx_sysfs_common.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_format_para.h>
#define HDMI_TX_COUNT 32
#define HDMI_TX_POOL_NUM 6
@@ -88,14 +89,9 @@ static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data);
static void hdmitx_set_emp_pkt(u8 *data, u32 type, u32 size);
static int check_fbc_special(u8 *edid_dat);
static void clear_rx_vinfo(struct hdmitx_dev *hdev);
static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev);
static void edidinfo_detach_to_vinfo(struct hdmitx_dev *hdev);
static int hdmi21_get_valid_fmt_para(struct hdmitx_dev *hdev,
char const *name, char const *attr, struct hdmi_format_para *para);
static void hdmitx21_reset_format_para(struct hdmi_format_para *para);
static void update_current_para(struct hdmitx_dev *hdev);
static void update_vinfo_from_formatpara(void);
static void hdmi_tx_enable_ll_mode(bool enable);
static int hdmitx_hook_drm(struct device *device);
static int hdmitx_unhook_drm(struct device *device);
@@ -103,8 +99,8 @@ static void tee_comm_dev_reg(struct hdmitx_dev *hdev);
static void tee_comm_dev_unreg(struct hdmitx_dev *hdev);
static bool is_cur_tmds_div40(struct hdmitx_dev *hdev);
static void hdmitx_resend_div40(struct hdmitx_dev *hdev);
static int hdmitx_check_vic(int vic);
static unsigned int hdmitx_get_frame_duration(void);
const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name);
/*
* Normally, after the HPD in or late resume, there will reading EDID, and
@@ -200,8 +196,8 @@ static struct vout_device_s hdmitx_vdev = {
.fresh_tx_cuva_hdr_vsif = hdmitx_set_cuva_hdr_vsif,
.fresh_tx_cuva_hdr_vs_emds = hdmitx_set_cuva_hdr_vs_emds,
.fresh_tx_emp_pkt = hdmitx_set_emp_pkt,
.get_attr = get21_attr,
.setup_attr = setup21_attr,
.get_attr = NULL,
.setup_attr = NULL,
/* .video_mute = hdmitx21_video_mute_op, */
};
@@ -377,7 +373,6 @@ static void hdmitx_early_suspend(struct early_suspend *h)
hdev->output_blank_flag = 0;
hdmitx_set_vsif_pkt(0, 0, NULL, true);
hdmitx_set_hdr10plus_pkt(0, NULL);
clear_rx_vinfo(hdev);
hdmitx21_edid_clear(hdev);
hdmitx21_edid_ram_buffer_clear(hdev);
hdmitx_edid_done = false;
@@ -392,19 +387,8 @@ static void hdmitx_early_suspend(struct early_suspend *h)
mutex_unlock(&hdev->hdmimode_mutex);
}
static int hdmitx_is_hdmi_vmode(char *mode_name)
{
enum hdmi_vic vic = hdmitx21_edid_vic_tab_map_vic(mode_name);
if (vic == HDMI_0_UNKNOWN)
return 0;
return 1;
}
static void hdmitx_late_resume(struct early_suspend *h)
{
const struct vinfo_s *info = hdmitx_get_current_vinfo(NULL);
struct hdmitx_dev *hdev = (struct hdmitx_dev *)h->param;
if (hdev->aon_output) {
@@ -413,8 +397,6 @@ static void hdmitx_late_resume(struct early_suspend *h)
}
mutex_lock(&hdev->hdmimode_mutex);
if (info && info->name && (hdmitx_is_hdmi_vmode(info->name) == 1))
hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_HPLL_FAKE, 0);
hdev->hpd_lock = 0;
@@ -529,37 +511,19 @@ static void restore_mute(void)
}
}
int get21_cur_vout_index(void)
/*
* return value: 1, vout; 2, vout2;
*/
{
int vout_index = 1;
return vout_index;
}
static int set_disp_mode(const char *mode)
{
int ret = -1;
enum hdmi_vic vic;
struct hdmitx_dev *hdev = get_hdmitx21_device();
const struct hdmi_timing *timing = NULL;
vic = hdmitx21_edid_get_VIC(hdev, mode, 1);
if (strncmp(mode, "2160p30hz", strlen("2160p30hz")) == 0)
vic = HDMI_95_3840x2160p30_16x9;
else if (strncmp(mode, "2160p25hz", strlen("2160p25hz")) == 0)
vic = HDMI_94_3840x2160p25_16x9;
else if (strncmp(mode, "2160p24hz", strlen("2160p24hz")) == 0)
vic = HDMI_93_3840x2160p24_16x9;
else if (strncmp(mode, "smpte24hz", strlen("smpte24hz")) == 0)
vic = HDMI_98_4096x2160p24_256x135;
else
;/* nothing */
/*function for debug, only get vic and check if ip can support*/
timing = hdmitx_mode_match_timing_name(mode);
if (!timing)
return 0;
if (strncmp(mode, "1080p60hz", strlen("1080p60hz")) == 0)
vic = HDMI_16_1920x1080p60_16x9;
if (strncmp(mode, "1080p50hz", strlen("1080p50hz")) == 0)
vic = HDMI_31_1920x1080p50_16x9;
vic = timing->vic;
if (vic != HDMI_0_UNKNOWN) {
hdev->mux_hpd_if_pin_high_flag = 1;
@@ -595,16 +559,10 @@ static int set_disp_mode(const char *mode)
return ret;
}
static void hdmi_physical_size_update(struct hdmitx_dev *hdev)
static void hdmi_physical_size_to_vinfo(struct hdmitx_dev *hdev)
{
u32 width, height;
struct vinfo_s *info = NULL;
info = hdmitx_get_current_vinfo(NULL);
if (!info || !info->name) {
pr_info("cann't get valid mode\n");
return;
}
struct vinfo_s *info = &hdmitx21_device.tx_comm.hdmitx_vinfo;
if (info->mode == VMODE_HDMI) {
width = hdev->tx_comm.rxcap.physical_width;
@@ -639,19 +597,9 @@ static void rxlatency_to_vinfo(struct vinfo_s *info, struct rx_cap *rx)
static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = NULL;
struct vinfo_s *info = &hdmitx21_device.tx_comm.hdmitx_vinfo;
struct hdmi_format_para *para = &hdev->tx_comm.fmt_para;
/* get current vinfo */
info = hdmitx_get_current_vinfo(NULL);
if (!info || !info->name)
return;
if (strncmp(info->name, "480cvbs", 7) == 0 ||
strncmp(info->name, "576cvbs", 7) == 0 ||
strncmp(info->name, "null", 4) == 0)
return;
mutex_lock(&getedid_mutex);
hdrinfo_to_vinfo(&info->hdr_info, hdev);
memcpy(&ext_dvinfo, &hdev->tx_comm.rxcap.dv_info, sizeof(ext_dvinfo));
@@ -659,21 +607,20 @@ static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev)
memset(&info->hdr_info, 0, sizeof(struct hdr_info));
rxlatency_to_vinfo(info, &hdev->tx_comm.rxcap);
hdmitx_vdev.dv_info = &hdev->tx_comm.rxcap.dv_info;
hdmi_physical_size_to_vinfo(&hdmitx21_device);
mutex_unlock(&getedid_mutex);
}
static void edidinfo_detach_to_vinfo(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = NULL;
struct vinfo_s *info = &hdmitx21_device.tx_comm.hdmitx_vinfo;
/* get current vinfo */
info = hdmitx_get_current_vinfo(NULL);
if (!info || !info->name)
return;
edidinfo_attach_to_vinfo(hdev);
memset(&info->hdr_info, 0, sizeof(struct hdr_info));
memset(&info->hdr_info, 0, sizeof(info->hdr_info));
memset(&info->rx_latency, 0, sizeof(info->rx_latency));
hdmitx_vdev.dv_info = &dv_dummy;
info->screen_real_width = 0;
info->screen_real_height = 0;
}
static void hdmitx_up_hdcp_timeout_handler(struct work_struct *work)
@@ -758,94 +705,6 @@ static void hdmitx_start_hdcp_handler(struct work_struct *work)
is_passthrough_switch = 0;
}
static int check_vic_4x3_and_16x9(struct hdmitx_dev *hdev, enum hdmi_vic vic)
{
if (vic == HDMI_3_720x480p60_16x9 ||
vic == HDMI_7_720x480i60_16x9 ||
vic == HDMI_18_720x576p50_16x9 ||
vic == HDMI_22_720x576i50_16x9) {
if (hdmitx_check_vic(vic))
return vic;
return vic - 1;
} else if (vic == HDMI_2_720x480p60_4x3 ||
vic == HDMI_6_720x480i60_4x3 ||
vic == HDMI_17_720x576p50_4x3 ||
vic == HDMI_21_720x576i50_4x3) {
if (hdmitx_check_vic(vic))
return vic;
return vic + 1;
}
return vic;
}
/* check the resolution is over 1920x1080 or not */
static bool is_over_1080p(const struct hdmi_timing *timing)
{
if (!timing)
return 1;
if (timing->h_active > 1920 || timing->v_active > 1080)
return 1;
return 0;
}
/* check the fresh rate is over 60hz or not */
static bool is_over_60hz(const struct hdmi_timing *timing)
{
if (!timing)
return 1;
if (timing->v_freq > 60000)
return 1;
return 0;
}
/* test current vic is over 150MHz or not */
static bool is_over_pixel_150mhz(const struct hdmi_timing *timing)
{
if (!timing)
return 1;
if (timing->pixel_freq > 150000)
return 1;
return 0;
}
bool hdmitx21_is_vic_over_limited_1080p(enum hdmi_vic vic)
{
const struct hdmi_timing *timing = NULL;
timing = hdmitx_mode_vic_to_hdmi_timing(vic);
if (!timing || !timing->name)
return 1;
if (strncmp(timing->name, "invalid", strlen("invalid")) == 0)
return 1;
/* if the vic equals to HDMI_0_UNKNOWN or VESA,
* then treated it as over limited
*/
if (vic == HDMI_0_UNKNOWN || vic >= HDMITX_VESA_OFFSET)
return 1;
if (is_over_1080p(timing) || is_over_60hz(timing) ||
is_over_pixel_150mhz(timing)) {
pr_err("over limited vic: %d\n", vic);
return 1;
} else {
return 0;
}
}
/* the hdmitx output limits to 1080p */
bool hdmitx21_limited_1080p(void)
{
return res_1080p;
}
/*disp_mode attr*/
static ssize_t disp_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -926,25 +785,6 @@ static ssize_t disp_mode_store(struct device *dev,
return count;
}
/*aud_mode attr*/
void setup21_attr(const char *buf)
{
char attr[16] = {0};
struct hdmitx_dev *hdev = get_hdmitx21_device();
struct hdmitx_common *tx_comm = &hdev->tx_comm;
memcpy(attr, buf, sizeof(attr));
memcpy(tx_comm->fmt_attr, attr, sizeof(tx_comm->fmt_attr));
}
void get21_attr(char attr[16])
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
struct hdmitx_common *tx_comm = &hdev->tx_comm;
memcpy(attr, tx_comm->fmt_attr, sizeof(tx_comm->fmt_attr));
}
/* todo
*static int dump_edid_data(u32 type, char *path)
*{
@@ -1152,24 +992,13 @@ static unsigned int hdmitx_get_frame_duration(void)
return frame_duration;
}
static int hdmitx_check_vic(int vic)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
int i;
for (i = 0; i < hdev->tx_comm.rxcap.VIC_count && i < VIC_MAX_NUM; i++) {
if (vic == hdev->tx_comm.rxcap.VIC[i])
return 1;
}
return 0;
}
static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
{
struct rx_cap *prxcap = &hdmitx21_device.tx_comm.rxcap;
switch (vic) {
case HDMI_2_720x480p60_4x3:
if (hdmitx_check_vic(HDMI_3_720x480p60_16x9)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_3_720x480p60_16x9)) {
if (aspect_ratio == AR_16X9)
return 1;
pr_info("same aspect_ratio = %d\n", aspect_ratio);
@@ -1178,7 +1007,7 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
}
break;
case HDMI_3_720x480p60_16x9:
if (hdmitx_check_vic(HDMI_2_720x480p60_4x3)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_2_720x480p60_4x3)) {
if (aspect_ratio == AR_4X3)
return 1;
pr_info("same aspect_ratio = %d\n", aspect_ratio);
@@ -1187,7 +1016,7 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
}
break;
case HDMI_17_720x576p50_4x3:
if (hdmitx_check_vic(HDMI_18_720x576p50_16x9)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_18_720x576p50_16x9)) {
if (aspect_ratio == AR_16X9)
return 1;
pr_info("same aspect_ratio = %d\n", aspect_ratio);
@@ -1196,7 +1025,7 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
}
break;
case HDMI_18_720x576p50_16x9:
if (hdmitx_check_vic(HDMI_17_720x576p50_4x3)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_17_720x576p50_4x3)) {
if (aspect_ratio == AR_4X3)
return 1;
pr_info("same aspect_ratio = %d\n", aspect_ratio);
@@ -1228,32 +1057,33 @@ int hdmitx21_get_aspect_ratio(void)
struct aspect_ratio_list *hdmitx21_get_support_ar_list(void)
{
struct rx_cap *prxcap = &hdmitx21_device.tx_comm.rxcap;
static struct aspect_ratio_list ar_list[4];
int i = 0;
memset(ar_list, 0, sizeof(ar_list));
if (hdmitx_check_vic(HDMI_2_720x480p60_4x3)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_2_720x480p60_4x3)) {
ar_list[i].vic = HDMI_2_720x480p60_4x3;
ar_list[i].flag = TRUE;
ar_list[i].aspect_ratio_num = 4;
ar_list[i].aspect_ratio_den = 3;
i++;
}
if (hdmitx_check_vic(HDMI_3_720x480p60_16x9)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_3_720x480p60_16x9)) {
ar_list[i].vic = HDMI_3_720x480p60_16x9;
ar_list[i].flag = TRUE;
ar_list[i].aspect_ratio_num = 16;
ar_list[i].aspect_ratio_den = 9;
i++;
}
if (hdmitx_check_vic(HDMI_17_720x576p50_4x3)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_17_720x576p50_4x3)) {
ar_list[i].vic = HDMI_17_720x576p50_4x3;
ar_list[i].flag = TRUE;
ar_list[i].aspect_ratio_num = 4;
ar_list[i].aspect_ratio_den = 3;
i++;
}
if (hdmitx_check_vic(HDMI_18_720x576p50_16x9)) {
if (hdmitx_edid_validate_mode(prxcap, HDMI_18_720x576p50_16x9)) {
ar_list[i].vic = HDMI_18_720x576p50_16x9;
ar_list[i].flag = TRUE;
ar_list[i].aspect_ratio_num = 16;
@@ -1396,9 +1226,19 @@ static bool _check_hdmi_mode(void)
return 0;
}
bool is_cur_mode_hdmi(void)
static bool hdmitx21_hdr_en(void)
{
return _check_hdmi_mode();
return (hdmitx21_get_cur_hdr_st() & HDMI_HDR_TYPE) == HDMI_HDR_TYPE;
}
static bool hdmitx21_dv_en(void)
{
return (hdmitx21_get_cur_dv_st() & HDMI_DV_TYPE) == HDMI_DV_TYPE;
}
static bool hdmitx21_hdr10p_en(void)
{
return (hdmitx21_get_cur_hdr10p_st() & HDMI_HDR10P_TYPE) == HDMI_HDR10P_TYPE;
}
#define GET_LOW8BIT(a) ((a) & 0xff)
@@ -1445,7 +1285,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
hdr_status_pos = 1;
/* if VSIF/DV or VSIF/HDR10P packet is enabled, disable it */
if (hdmitx21_dv_en()) {
update_current_para(hdev);
hdmi_avi_infoframe_config(CONF_AVI_CS, hdev->tx_comm.fmt_para.cs);
/* if using VSIF/DOVI, then only clear DV_VS10_SIG, else disable VSIF */
if (hdev->tx_hw.cntlconfig(&hdev->tx_hw, CONF_CLR_DV_VS10_SIG, 0) == 0)
@@ -1591,63 +1430,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
}
/* fr_tab[]
* 1080p24hz, 24:1
* 1080p23.976hz, 2997:125
* 25/50/100/200hz, no change
*/
static struct frac_rate_table fr_tab[] = {
{"24hz", 24, 1, 2997, 125},
{"30hz", 30, 1, 2997, 100},
{"60hz", 60, 1, 2997, 50},
{"120hz", 120, 1, 2997, 25},
{"240hz", 120, 1, 5994, 25},
{NULL},
};
static void recalc_vinfo_sync_duration(struct vinfo_s *info, u32 frac)
{
struct frac_rate_table *fr = &fr_tab[0];
if (!info)
return;
pr_info("hdmitx: recalc before %s %d %d, frac %d\n", info->name,
info->sync_duration_num, info->sync_duration_den, info->frac);
while (fr->hz) {
if (strstr(info->name, fr->hz)) {
if (frac) {
info->sync_duration_num = fr->sync_num_dec;
info->sync_duration_den = fr->sync_den_dec;
info->frac = 1;
} else {
info->sync_duration_num = fr->sync_num_int;
info->sync_duration_den = fr->sync_den_int;
info->frac = 0;
}
break;
}
fr++;
}
pr_info("recalc after %s %d %d, frac %d\n", info->name,
info->sync_duration_num, info->sync_duration_den, info->frac);
}
static int hdmi21_get_valid_fmt_para(struct hdmitx_dev *hdev,
char const *name, char const *attr, struct hdmi_format_para *para)
{
enum hdmi_vic vic = HDMI_0_UNKNOWN;
vic = hdmitx21_edid_get_VIC(hdev, name, 0);
if (vic == HDMI_0_UNKNOWN) {
pr_err("%s: get vic from (%s) fail\n", __func__, name);
//return -EINVAL;
}
return hdmi21_get_fmt_para(vic, attr, para);
}
static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct vinfo_s *tx_vinfo)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
@@ -1671,8 +1453,6 @@ static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct
tx_vinfo->sync_duration_num = timing->v_freq;
tx_vinfo->sync_duration_den = 1000;
}
/* for 24/30/60/120/240hz, recalc sync duration */
recalc_vinfo_sync_duration(tx_vinfo, hdev->tx_comm.frac_rate_policy);
tx_vinfo->video_clk = timing->pixel_freq;
tx_vinfo->htotal = timing->h_total;
tx_vinfo->vtotal = timing->v_total;
@@ -1687,6 +1467,26 @@ static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct
return 0;
}
static void update_vinfo_from_formatpara(void)
{
struct vinfo_s *vinfo = &hdmitx21_device.tx_comm.hdmitx_vinfo;
struct hdmi_format_para *fmtpara = &hdmitx21_device.tx_comm.fmt_para;
/*update vinfo for out device.*/
calc_vinfo_from_hdmi_timing(&fmtpara->timing, vinfo);
vinfo->info_3d = NON_3D;
if (hdmitx21_device.flag_3dfp)
vinfo->info_3d = FP_3D;
if (hdmitx21_device.flag_3dtb)
vinfo->info_3d = TB_3D;
if (hdmitx21_device.flag_3dss)
vinfo->info_3d = SS_3D;
vinfo->vout_device = &hdmitx_vdev;
/*dynamic info, always need set.*/
vinfo->cs = fmtpara->cs;
vinfo->cd = fmtpara->cd;
}
static void hdmitx21_reset_format_para(struct hdmi_format_para *para)
{
if (!para)
@@ -1702,45 +1502,29 @@ void update_para_from_mode(struct hdmitx_dev *hdev,
const char *name, const char *fmt_attr,
struct hdmi_format_para *update_para)
{
struct vinfo_s *vinfo = &hdev->tx_comm.hdmitx_vinfo;
enum hdmi_vic vic = HDMI_0_UNKNOWN;
if (hdmi21_get_valid_fmt_para(hdev, name, fmt_attr, update_para) < 0) {
hdmitx21_reset_format_para(update_para);
pr_err("get format para failed (%s,%s)\n", name, fmt_attr);
vic = hdmitx_common_parse_vic_in_edid(&hdev->tx_comm, name);
if (vic == HDMI_0_UNKNOWN) {
pr_err("%s: get vic from (%s) fail\n", __func__, name);
return;
}
if (hdmitx_common_validate_vic(&hdev->tx_comm, vic) != 0)
return;
hdmitx_parse_color_attr(fmt_attr, &update_para->cs,
&update_para->cd, &update_para->cr);
if (hdmitx_common_build_format_para(&hdev->tx_comm,
update_para, vic, hdev->tx_comm.frac_rate_policy,
update_para->cs, update_para->cd, update_para->cr) != 0) {
pr_err("init format para failed (%s,%s)\n", name, fmt_attr);
hdmitx_format_para_reset(update_para);
}
pr_info("get_fmt_para from %s,%s -> %d,%s\n", name, fmt_attr, update_para->vic,
update_para->sname ? update_para->sname : update_para->name);
/*update vinfo for out device.*/
calc_vinfo_from_hdmi_timing(&update_para->timing, vinfo);
vinfo->info_3d = NON_3D;
if (hdev->flag_3dfp)
vinfo->info_3d = FP_3D;
if (hdev->flag_3dtb)
vinfo->info_3d = TB_3D;
if (hdev->flag_3dss)
vinfo->info_3d = SS_3D;
vinfo->vout_device = &hdmitx_vdev;
/*dynamic info, always need set.*/
vinfo->cs = update_para->cs;
vinfo->cd = update_para->cd;
}
static void update_current_para(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = NULL;
u8 mode[32];
info = hdmitx_get_current_vinfo(NULL);
if (!info || !info->name)
return;
memset(mode, 0, sizeof(mode));
strncpy(mode, info->name, sizeof(mode) - 1);
update_para_from_mode(hdev, mode,
hdev->tx_comm.fmt_attr, &hdev->tx_comm.fmt_para);
}
static struct vsif_debug_save vsif_debug_info;
@@ -1892,7 +1676,6 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
hdmi_vend_infoframe_rawset(NULL, NULL);
if (signal_sdr) {
pr_info("hdmitx: Dolby H14b VSIF, switching signal to SDR\n");
update_current_para(hdev);
hdmi_avi_infoframe_config(CONF_AVI_CS, fmt_para->cs);
hdmi_avi_infoframe_config(CONF_AVI_Q01, RGB_RANGE_LIM);
hdmi_avi_infoframe_config(CONF_AVI_YQ01, YCC_RANGE_LIM);
@@ -2027,7 +1810,6 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
hdmi_vend_infoframe_rawset(ven_hb, db2);
if (signal_sdr) {
pr_info("hdmitx: Dolby VSIF, switching signal to SDR\n");
update_current_para(hdev);
pr_info("vic:%d, cd:%d, cs:%d, cr:%d\n",
fmt_para->timing.vic, fmt_para->cd,
fmt_para->cs, fmt_para->cr);
@@ -3023,7 +2805,7 @@ static ssize_t allm_mode_store(struct device *dev,
// disable ALLM
tx_comm->allm_mode = 0;
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC) &&
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0 &&
!hdmitx21_dv_en() &&
!hdmitx21_hdr10p_en())
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
@@ -3076,7 +2858,7 @@ static void hdmi_tx_enable_ll_mode(bool enable)
pr_info("%s: disabling ALLM before enabling game mode, enable:%d, allm:%d, cnc3:%d\n",
__func__, enable, tx_comm->rxcap.allm, tx_comm->rxcap.cnc3);
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC))
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0)
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
/* if not hdmi1.4 4k, need to sent > 4 frames and shorter than 1S
* HF-VSIF with allm_mode = 0, and then disable HF-VSIF according
@@ -3097,7 +2879,7 @@ static void hdmi_tx_enable_ll_mode(bool enable)
pr_info("%s: disabling ALLM, enable:%d, allm:%d, cnc3:%d\n",
__func__, enable, tx_comm->rxcap.allm, tx_comm->rxcap.cnc3);
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC) &&
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0 &&
!hdmitx21_dv_en() &&
!hdmitx21_hdr10p_en())
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
@@ -3118,7 +2900,7 @@ static void hdmi_tx_enable_ll_mode(bool enable)
pr_info("%s: disabling ALLM, enable:%d, allm:%d, cnc3:%d\n",
__func__, enable, tx_comm->rxcap.allm, tx_comm->rxcap.cnc3);
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC) &&
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0 &&
!hdmitx21_dv_en() &&
!hdmitx21_hdr10p_en())
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
@@ -3143,7 +2925,7 @@ static void drm_set_allm_mode(int mode)
// disable ALLM
tx_comm->allm_mode = 0;
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC) &&
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0 &&
!hdmitx21_dv_en() &&
!hdmitx21_hdr10p_en())
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
@@ -3344,7 +3126,7 @@ bool hdmitx_update_latency_info(struct tvin_latency_s *latency_info)
tx_comm->allm_mode = 0;
pr_info("%s: disabling ALLM before enable/disable game mode\n", __func__);
hdmitx21_construct_vsif(hdev, VT_ALLM, 0, NULL);
if (_is_hdmi14_4k(tx_comm->cur_VIC) &&
if (hdmitx_edid_get_hdmi14_4k_vic(tx_comm->cur_VIC) > 0 &&
!hdmitx21_dv_en() &&
!hdmitx21_hdr10p_en())
hdmitx21_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL);
@@ -4557,18 +4339,14 @@ static int hdmitx21_pre_enable_mode(struct hdmitx_common *tx_comm, struct hdmi_f
static int hdmitx21_enable_mode(struct hdmitx_common *tx_comm, struct hdmi_format_para *para)
{
int ret;
enum hdmi_vic vic;
struct hdmitx_dev *hdev = to_hdmitx21_dev(tx_comm);
edidinfo_detach_to_vinfo(hdev);
vic = check_vic_4x3_and_16x9(hdev, para->vic);
tx_comm->cur_VIC = HDMI_0_UNKNOWN;
ret = hdmitx21_set_display(hdev, vic);
ret = hdmitx21_set_display(hdev, para->vic);
if (ret >= 0) {
hdev->hwop.cntl(hdev, HDMITX_AVMUTE_CNTL, AVMUTE_CLEAR);
tx_comm->cur_VIC = vic;
tx_comm->cur_VIC = para->vic;
hdev->audio_param_update_flag = 1;
restore_mute();
}
@@ -4601,6 +4379,7 @@ static int hdmitx21_post_enable_mode(struct hdmitx_common *tx_comm, struct hdmi_
}
hdev->output_blank_flag = 1;
edidinfo_attach_to_vinfo(hdev);
update_vinfo_from_formatpara();
/* wait for TV detect signal stable,
* otherwise hdcp may easily auth fail
*/
@@ -4652,7 +4431,6 @@ static int hdmitx_set_current_vmode(enum vmode_e mode, void *data)
* here get the current parameters of
* output mode, which may be used later
*/
update_current_para(hdev);
if (tx_comm->rxcap.max_frl_rate) {
hdev->frl_rate = hdmitx21_select_frl_rate(hdev->dsc_en,
tx_comm->cur_VIC, hdev->tx_comm.fmt_para.cs,
@@ -4662,6 +4440,7 @@ static int hdmitx_set_current_vmode(enum vmode_e mode, void *data)
hdev->frl_rate, hdev->tx_max_frl_rate);
}
edidinfo_attach_to_vinfo(hdev);
update_vinfo_from_formatpara();
vinfo = get_current_vinfo();
if (vinfo) {
vinfo->cur_enc_ppc = 1;
@@ -4673,33 +4452,23 @@ static int hdmitx_set_current_vmode(enum vmode_e mode, void *data)
return 0;
}
static enum vmode_e hdmitx_validate_vmode(char *_mode, u32 frac, void *data)
static enum vmode_e hdmitx_validate_vmode(char *mode, u32 frac, void *data)
{
struct hdmitx_dev *hdev = get_hdmitx21_device();
struct hdmi_format_para fmt_para;
char mode[32] = {0};
char *y420;
struct vinfo_s *vinfo = &hdmitx21_device.tx_comm.hdmitx_vinfo;
const struct hdmi_timing *timing = 0;
strncpy(mode, _mode, sizeof(mode));
mode[31] = 0;
/* if current mode contains string 420, subtract 420 */
y420 = strstr(mode, "420");
if (y420)
*y420 = '\0';
update_para_from_mode(hdev, mode, hdev->tx_comm.fmt_attr, &fmt_para);
if (1) {
/* //remove frac support for vout api
*if (frac)
* hdev->frac_rate_policy = 1;
*else
* hdev->frac_rate_policy = 0;
*/
hdev->tx_comm.hdmitx_vinfo.info_3d = NON_3D;
hdev->tx_comm.hdmitx_vinfo.vout_device = &hdmitx_vdev;
/* vout validate vmode only used to confirm the mode is
* supported by this server. And dont check with edid,
* maybe we dont have edid when this function called.
*/
timing = hdmitx_mode_match_timing_name(mode);
if (hdmitx_common_validate_vic(&hdmitx21_device.tx_comm, timing->vic) == 0) {
/*should save mode name to vinfo, will be used in set_vmode*/
vinfo->name = timing->sname ? timing->sname : timing->name;
return VMODE_HDMI;
}
pr_err("%s validate %s fail\n", __func__, mode);
return VMODE_MAX;
}
@@ -5278,7 +5047,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
if (hdev->repeater_tx)
rx_repeat_hpd_state(1);
hdev->cedst_policy = hdev->cedst_en & hdev->tx_comm.rxcap.scdc_present;
hdmi_physical_size_update(hdev);
if (hdev->tx_comm.rxcap.ieeeoui != HDMI_IEEE_OUI)
hdev->tx_hw.cntlconfig(&hdev->tx_hw,
CONF_HDMI_DVI_MODE, DVI_MODE);
@@ -5348,16 +5116,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
hdmitx_hpd_notify_unlocked(&hdev->tx_comm);
}
static void clear_rx_vinfo(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = hdmitx_get_current_vinfo(NULL);
if (info) {
memset(&info->hdr_info, 0, sizeof(info->hdr_info));
memset(&info->rx_latency, 0, sizeof(info->rx_latency));
}
}
static void hdmitx_aud_hpd_plug_handler(struct work_struct *work)
{
int st;
@@ -5396,13 +5154,11 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
* NOTE: TV maybe changed(such as DV <-> non-DV)
*/
if (!hdev->systemcontrol_on &&
hdmitx21_uboot_already_display(hdev)) {
hdev->tx_hw.getstate(&hdev->tx_hw, STAT_TX_OUTPUT, 0)) {
plugout_mute_flg = true;
/* edidinfo_detach_to_vinfo(hdev); */
clear_rx_vinfo(hdev);
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT;
hdmitx21_edid_clear(hdev);
hdmi_physical_size_update(hdev);
hdmitx21_edid_ram_buffer_clear(hdev);
hdmitx_edid_done = false;
hdev->tx_comm.hpd_state = 0;
@@ -5441,9 +5197,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
hdmitx21_rst_stream_type(hdev->am_hdcp);
p_hdcp->saved_upstream_type = 0;
p_hdcp->rx_update_flag = 0;
clear_rx_vinfo(hdev);
hdmitx21_edid_clear(hdev);
hdmi_physical_size_update(hdev);
hdmitx21_edid_ram_buffer_clear(hdev);
hdmitx_edid_done = false;
hdev->tx_comm.hpd_state = 0;
@@ -5491,57 +5245,17 @@ int get21_hpd_state(void)
/******************************
* hdmitx kernel task
*******************************/
/*TODO: called when there is no modesetting?*/
static bool is_cur_tmds_div40(struct hdmitx_dev *hdev)
{
struct hdmitx_common *tx_comm = &hdev->tx_comm;
const struct hdmi_timing *timing = NULL;
struct hdmi_format_para tst_para;
unsigned int act_clk = 0;
if (!hdev)
return 0;
pr_info("hdmitx: get vic %d cs,cd %s\n", hdev->tx_comm.cur_VIC, tx_comm->fmt_attr);
timing = hdmitx_mode_vic_to_hdmi_timing(hdev->tx_comm.cur_VIC);
if (!timing) {
pr_err("%s[%d] can't get timing from [%d]\n",
__func__, __LINE__, hdev->tx_comm.cur_VIC);
if (!hdev || hdev->tx_comm.fmt_para.vic == HDMI_0_UNKNOWN) {
pr_err("display is not ready\n");
return 0;
}
if (hdmi21_get_valid_fmt_para(hdev, timing->name, tx_comm->fmt_attr, &tst_para) < 0) {
pr_info("%s[%d] fail exit.\n", __func__, __LINE__);
return 0;
}
act_clk = tst_para.tmds_clk / 1000;
act_clk = hdev->tx_comm.fmt_para.tmds_clk / 1000;
pr_info("hdmitx: %s original clock %d\n", __func__, act_clk);
if (tst_para.cs == HDMI_COLORSPACE_YUV420)
act_clk = act_clk / 2;
if (tst_para.cs != HDMI_COLORSPACE_YUV422) {
switch (tst_para.cd) {
case COLORDEPTH_30B:
act_clk = act_clk * 5 / 4;
break;
case COLORDEPTH_36B:
act_clk = act_clk * 3 / 2;
break;
case COLORDEPTH_48B:
act_clk = act_clk * 2;
break;
case COLORDEPTH_24B:
default:
act_clk = act_clk * 1;
break;
}
}
pr_info("hdmitx: act clock: %d\n", act_clk);
if (act_clk > 340)
return 1;
@@ -6274,6 +5988,15 @@ static int amhdmitx_probe(struct platform_device *pdev)
hdev->nb.notifier_call = hdmitx_reboot_notifier;
register_reboot_notifier(&hdev->nb);
hdmitx21_meson_init(hdev);
/*load fmt para from hw info.*/
hdmitx_common_init_bootup_format_para(tx_comm, &tx_comm->fmt_para);
if (tx_comm->fmt_para.vic != HDMI_0_UNKNOWN) {
tx_comm->cur_VIC = tx_comm->fmt_para.vic;
hdev->ready = 1;
}
/* update fmt_attr string from fmt_para*/
hdmitx_init_fmt_attr(hdev);
mutex_init(&hdev->hdmimode_mutex);
tx_comm->hpd_state = !!(hdev->tx_hw.cntlmisc(&hdev->tx_hw,
MISC_HPD_GPI_ST, 0));
@@ -6299,11 +6022,6 @@ static int amhdmitx_probe(struct platform_device *pdev)
aout_register_client(&hdmitx_notifier_nb_a);
#endif
hdmitx_extcon_register(pdev, dev);
/**
* update fmt_attr string from fmt_para,
* because fmt_para may update in hdmitx_meson_init().
*/
hdmitx_init_fmt_attr(hdev);
tx_comm->hpd_state = !!hdev->tx_hw.cntlmisc(&hdev->tx_hw,
MISC_HPD_GPI_ST, 0);
+2 -2
View File
@@ -323,7 +323,7 @@ int hdmitx21_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type,
db[0] = GET_OUI_BYTE0(ieeeoui);
db[1] = GET_OUI_BYTE1(ieeeoui);
db[2] = GET_OUI_BYTE2(ieeeoui);
if (_is_hdmi14_4k(hdev->tx_comm.cur_VIC)) {
if (hdmitx_edid_get_hdmi14_4k_vic(hdev->tx_comm.cur_VIC) > 0) {
fill_hdmi4k_vsif_data(hdev->tx_comm.cur_VIC, db, hb);
hdmitx21_set_avi_vic(0);
hdmi_vend_infoframe_rawset(hb, vsif_db);
@@ -339,7 +339,7 @@ int hdmitx21_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type,
db[3] = 0x1; /* Fixed value */
if (on) {
db[4] |= 1 << 1; /* set bit1, ALLM_MODE */
if (_is_hdmi14_4k(hdev->tx_comm.cur_VIC))
if (hdmitx_edid_get_hdmi14_4k_vic(hdev->tx_comm.cur_VIC) > 0)
hdmitx21_set_avi_vic(hdev->tx_comm.cur_VIC);
hdmi_vend_infoframe2_rawset(hb, vsif_db);
} else {
+140 -96
View File
@@ -39,6 +39,12 @@
#define to_hdmitx21_dev(x) container_of(x, struct hdmitx_dev, tx_hw)
#define MESON_CPU_ID_T7 0
/*TODO: move to struct hdmitx_hw*/
static u32 tx_max_frl_rate;
static u32 chip_type;
static struct hdmitx_infoframe *infoframes;
static void hdmi_phy_suspend(void);
static void hdmi_phy_wakeup(struct hdmitx_dev *hdev);
static void hdmitx_set_phy(struct hdmitx_dev *hdev);
@@ -268,10 +274,10 @@ void hdmitx21_sys_reset(void)
}
}
bool hdmitx21_uboot_already_display(struct hdmitx_dev *hdev)
static bool hdmitx21_uboot_already_display(void)
{
if (hdev->pxp_mode)
return 0;
// if (hdev->pxp_mode)
// return 0;
if (hd21_read_reg(ANACTRL_HDMIPHY_CTRL0))
return 1;
@@ -307,45 +313,46 @@ static enum hdmi_color_depth _get_colordepth(void)
return depth;
}
static enum hdmi_vic _get_vic_from_vsif(struct hdmitx_dev *hdev)
{
int ret;
u8 body[32] = {0};
enum hdmi_vic hdmi4k_vic = HDMI_0_UNKNOWN;
union hdmi_infoframe *infoframe = &hdev->infoframes.vend;
struct hdmi_vendor_infoframe *vendor = &infoframe->vendor.hdmi;
ret = hdmitx_infoframe_rawget(HDMI_INFOFRAME_TYPE_VENDOR, body);
if (ret == -1 || ret == 0)
return hdmi4k_vic;
ret = hdmi_infoframe_unpack(infoframe, body, sizeof(body));
if (ret < 0) {
pr_info("hdmitx21: parsing VEND failed %d\n", ret);
} else {
switch (vendor->vic) {
case 1:
hdmi4k_vic = HDMI_95_3840x2160p30_16x9;
break;
case 2:
hdmi4k_vic = HDMI_94_3840x2160p25_16x9;
break;
case 3:
hdmi4k_vic = HDMI_93_3840x2160p24_16x9;
break;
case 4:
hdmi4k_vic = HDMI_98_4096x2160p24_256x135;
break;
default:
break;
}
}
return hdmi4k_vic;
}
/*
*static enum hdmi_vic _get_vic_from_vsif(void)
*{
* int ret;
* u8 body[32] = {0};
* enum hdmi_vic hdmi 4k_vic = HDMI_0_UNKNOWN;
* union hdmi_infoframe *infoframe = &infoframes->vend;
* struct hdmi_vendor_infoframe *vendor = &infoframe->vendor.hdmi;
*
* ret = hdmitx_infoframe_rawget(HDMI_INFOFRAME_TYPE_VENDOR, body);
* if (ret == -1 || ret == 0)
* return hdmi4k_vic;
* ret = hdmi_infoframe_unpack(infoframe, body, sizeof(body));
* if (ret < 0) {
* pr_info("hdmitx21: parsing VEND failed %d\n", ret);
* } else {
* switch (vendor->vic) {
* case 1:
* hdmi4k_vic = HDMI_95_3840x2160p30_16x9;
* break;
* case 2:
* hdmi4k_vic = HDMI_94_3840x2160p25_16x9;
* break;
* case 3:
* hdmi4k_vic = HDMI_93_3840x2160p24_16x9;
* break;
* case 4:
* hdmi4k_vic = HDMI_98_4096x2160p24_256x135;
* break;
* default:
* break;
* }
* }
* return hdmi4k_vic;
*}
*/
static void hdmi_hwp_init(struct hdmitx_dev *hdev, u8 reset)
{
u32 data32;
struct hdmi_format_para tmp_para;
if (hdev->data->chip_type >= MESON_CPU_ID_S5) {
hd21_set_reg_bits(CLKCTRL_VID_CLK0_CTRL, 7, 0, 3);
@@ -357,43 +364,8 @@ static void hdmi_hwp_init(struct hdmitx_dev *hdev, u8 reset)
}
pr_info("%s%d\n", __func__, __LINE__);
if (!reset && hdmitx21_uboot_already_display(hdev)) {
int ret;
u8 body[32] = {0};
union hdmi_infoframe *infoframe = &hdev->infoframes.avi;
struct hdmi_avi_infoframe *avi = &infoframe->avi;
const struct hdmi_timing *tp;
const char *name;
enum hdmi_vic vic = HDMI_0_UNKNOWN;
hdev->ready = 1;
ret = hdmitx_infoframe_rawget(HDMI_INFOFRAME_TYPE_AVI, body);
if (ret == -1 || ret == 0) {
pr_info("hdmitx21: AVI not enabled %d\n", ret);
return;
}
ret = hdmi_infoframe_unpack(infoframe, body, sizeof(body));
if (ret < 0) {
pr_info("hdmitx21: parsing AVI failed %d\n", ret);
} else {
tmp_para.cs = avi->colorspace;
tmp_para.cd = _get_colordepth();
if (tmp_para.cs == HDMI_COLORSPACE_YUV422)
tmp_para.cd = COLORDEPTH_36B;
hdmitx21_rebuild_fmt_attr_str(hdev, &tmp_para);
vic = avi->video_code;
if (vic == HDMI_0_UNKNOWN)
vic = _get_vic_from_vsif(hdev);
hdev->tx_comm.cur_VIC = vic;
tp = hdmitx_mode_vic_to_hdmi_timing(vic);
if (tp) {
name = tp->sname ? tp->sname : tp->name;
update_para_from_mode(hdev, name, hdev->tx_comm.fmt_attr,
&hdev->tx_comm.fmt_para);
}
pr_info("hdmitx21: parsing AVI CS%d CD%d VIC%d\n",
avi->colorspace, hdev->tx_comm.fmt_para.cd, hdev->tx_comm.cur_VIC);
}
if (!reset && hdmitx21_uboot_already_display()) {
pr_info("uboot already displayed\n");
return;
}
@@ -497,8 +469,38 @@ int hdmitx21_validate_mode(u32 vic)
return 0;
}
static int hdmitx21_calc_formatpara(struct hdmi_format_para *para)
{
bool frl_enable = true;
if (chip_type < MESON_CPU_ID_S5) //todo, not in parse
frl_enable = false; //t7 not support frl
para->tmds_clk = hdmitx_calc_tmds_clk(para->timing.pixel_freq,
para->cs, para->cd);
if (frl_enable) {
u32 tx_frl_bandwidth = 0;
para->frl_clk = hdmitx_calc_frl_clk(para->timing.pixel_freq,
para->cs, para->cd);
tx_frl_bandwidth = para->frl_clk / 1000;
if (tx_frl_bandwidth > hdmitx_get_frl_bandwidth(tx_max_frl_rate))
para->frl_clk = 0;
} else {
para->frl_clk = 0;
}
return 0;
}
void hdmitx21_meson_init(struct hdmitx_dev *hdev)
{
/*TODO: move to hdmitx_hw struct*/
tx_max_frl_rate = hdev->tx_max_frl_rate;
chip_type = hdev->data->chip_type;
infoframes = &hdev->infoframes;
pr_info("%s%d\n", __func__, __LINE__);
hdev->hwop.setdispmode = hdmitx_set_dispmode;
hdev->hwop.setaudmode = hdmitx_set_audmode;
@@ -512,6 +514,7 @@ void hdmitx21_meson_init(struct hdmitx_dev *hdev)
hdev->tx_hw.cntlconfig = hdmitx_cntl_config;
hdev->tx_hw.cntlmisc = hdmitx_cntl_misc;
hdev->tx_hw.validatemode = hdmitx21_validate_mode;
hdev->tx_hw.calcformatpara = hdmitx21_calc_formatpara;
hdmi_hwp_init(hdev, 0);
hdmitx21_debugfs_init();
hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_AVMUTE_OP, CLR_AVMUTE);
@@ -933,7 +936,8 @@ static int hdmitx_set_dispmode(struct hdmitx_dev *hdev)
(0 << 6) |
(((para->cd == COLORDEPTH_24B) ? 1 : 0) << 10) |
(0 << 12);
if (para->cd == COLORDEPTH_24B && hdmitx21_dv_en() == 0)
if (para->cd == COLORDEPTH_24B &&
((hdmitx21_get_cur_dv_st() & HDMI_DV_TYPE) == HDMI_DV_TYPE))
data32 |= (1 << 4);
hd21_write_reg(VPU_HDMI_DITH_CNTL, data32);
hdmitx21_dither_config(hdev);
@@ -1216,21 +1220,6 @@ enum hdmi_tf_type hdmitx21_get_cur_hdr10p_st(void)
return type;
}
bool hdmitx21_hdr_en(void)
{
return (hdmitx21_get_cur_hdr_st() & HDMI_HDR_TYPE) == HDMI_HDR_TYPE;
}
bool hdmitx21_dv_en(void)
{
return (hdmitx21_get_cur_dv_st() & HDMI_DV_TYPE) == HDMI_DV_TYPE;
}
bool hdmitx21_hdr10p_en(void)
{
return (hdmitx21_get_cur_hdr10p_st() & HDMI_HDR10P_TYPE) == HDMI_HDR10P_TYPE;
}
#define GET_OUTCHN_NO(a) (((a) >> 4) & 0xf)
#define GET_OUTCHN_MSK(a) ((a) & 0xf)
@@ -2600,6 +2589,57 @@ static enum hdmi_vic get_vic_from_pkt(void)
return vic;
}
static enum hdmi_colorspace get_cs_from_pkt(void)
{
int ret;
u8 body[32] = {0};
union hdmi_infoframe *infoframe = &infoframes->avi;
struct hdmi_avi_infoframe *avi = &infoframe->avi;
enum hdmi_colorspace cs = HDMI_COLORSPACE_RESERVED6;
ret = hdmitx_infoframe_rawget(HDMI_INFOFRAME_TYPE_AVI, body);
if (ret == -1 || ret == 0) {
pr_info("hdmitx21: AVI not enabled %d\n", ret);
return cs;
}
ret = hdmi_infoframe_unpack(infoframe, body, sizeof(body));
if (ret < 0)
pr_info("hdmitx21: parsing AVI failed %d\n", ret);
else
cs = avi->colorspace;
return cs;
}
static enum hdmi_color_depth get_cd_from_pkt(void)
{
int ret;
u8 body[32] = {0};
union hdmi_infoframe *infoframe = &infoframes->avi;
struct hdmi_avi_infoframe *avi = &infoframe->avi;
enum hdmi_color_depth cd = COLORDEPTH_RESERVED;
enum hdmi_colorspace cs = HDMI_COLORSPACE_RESERVED6;
ret = hdmitx_infoframe_rawget(HDMI_INFOFRAME_TYPE_AVI, body);
if (ret == -1 || ret == 0) {
pr_info("hdmitx21: AVI not enabled %d\n", ret);
return cd;
}
ret = hdmi_infoframe_unpack(infoframe, body, sizeof(body));
if (ret < 0) {
pr_info("hdmitx21: parsing AVI failed %d\n", ret);
} else {
cs = avi->colorspace;
cd = _get_colordepth();
if (cs == HDMI_COLORSPACE_YUV422)
cd = COLORDEPTH_36B;
}
return cd;
}
static int hdmitx_get_state(struct hdmitx_hw_common *tx_hw, u32 cmd,
u32 argv)
{
@@ -2611,11 +2651,14 @@ static int hdmitx_get_state(struct hdmitx_hw_common *tx_hw, u32 cmd,
switch (cmd) {
case STAT_VIDEO_VIC:
return (int)get_vic_from_pkt();
case STAT_VIDEO_CLK:
break;
case STAT_HDR_TYPE:
return 0;
case STAT_VIDEO_CS:
return (int)get_cs_from_pkt();
case STAT_VIDEO_CD:
return (int)get_cd_from_pkt();
case STAT_TX_OUTPUT:
return hdmitx21_uboot_already_display();
default:
pr_err("Unsupported cmd %x\n", cmd);
break;
}
return 0;
@@ -3016,7 +3059,8 @@ void hdmitx21_dither_config(struct hdmitx_dev *hdev)
{
struct hdmi_format_para *para = &hdev->tx_comm.fmt_para;
if (para->cd == COLORDEPTH_24B && hdmitx21_dv_en() == 0)
if (para->cd == COLORDEPTH_24B &&
((hdmitx21_get_cur_dv_st() & HDMI_DV_TYPE) == HDMI_DV_TYPE))
hd21_set_reg_bits(VPU_HDMI_DITH_CNTL, 1, 4, 1);
else
hd21_set_reg_bits(VPU_HDMI_DITH_CNTL, 0, 4, 1);
@@ -263,7 +263,9 @@ int hdmitx_edid_validate_format_para(struct rx_cap *prxcap,
if (para->cd != COLORDEPTH_24B && !para->frl_clk)
return -EPERM;
break;
case HDMI_6_720x480i60_4x3:
case HDMI_7_720x480i60_16x9:
case HDMI_21_720x576i50_4x3:
case HDMI_22_720x576i50_16x9:
if (para->cs == HDMI_COLORSPACE_YUV422)
return -EPERM;
@@ -25,7 +25,7 @@ int hdmitx_hw_set_phy(struct hdmitx_hw_common *tx_hw, int flag)
return 0;
}
u32 hdmitx_hw_calc_frl_bandwidth(u32 pixel_freq,
u32 hdmitx_calc_frl_clk(u32 pixel_freq,
enum hdmi_colorspace cs, enum hdmi_color_depth cd)
{
u32 bandwidth;
@@ -631,7 +631,6 @@ unsigned int hdmitx_rd_reg(unsigned int addr);
unsigned int hdmitx_rd_check_reg(unsigned int addr, unsigned int exp_data,
unsigned int mask);
bool hdmitx_get_bit(unsigned int addr, unsigned int bit_nr);
void vsem_init_cfg(struct hdmitx_dev *hdev);
enum hdmi_tf_type hdmitx_get_cur_hdr_st(void);
enum hdmi_tf_type hdmitx_get_cur_dv_st(void);
@@ -13,13 +13,6 @@
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_edid.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_mode.h>
#define HDMI_PACKET_TYPE_GCP 0x3
u32 calc_frl_bandwidth(u32 pixel_freq, enum hdmi_colorspace cs,
enum hdmi_color_depth cd);
u32 calc_tmds_bandwidth(u32 pixel_freq, enum hdmi_colorspace cs,
enum hdmi_color_depth cd);
enum hdmi_audio_fs;
struct hdmi_csc_coef_table {
@@ -226,15 +226,7 @@ struct hdmitx_dev {
int (*cntlmisc)(struct hdmitx_dev *hdev, u32 cmd, u32 arg);
int (*cntl)(struct hdmitx_dev *hdev, u32 cmd, u32 arg); /* Other control */
} hwop;
struct {
u32 enable;
union hdmi_infoframe vend;
union hdmi_infoframe avi;
union hdmi_infoframe spd;
union hdmi_infoframe aud;
union hdmi_infoframe drm;
union hdmi_infoframe emp;
} infoframes;
struct hdmitx_infoframe infoframes;
struct hdmi_config_platform_data config_data;
enum hdmi_event_t hdmitx_event;
u32 irq_hpd;
@@ -341,31 +333,21 @@ struct hdmitx_dev {
};
struct hdmitx_dev *get_hdmitx21_device(void);
int hdmitx21_construct_vsif(struct hdmitx_dev *hdev,
enum vsif_type type, int on, void *param);
/***********************************************************************
* hdmitx protocol level interface
**********************************************************************/
enum hdmi_vic hdmitx21_edid_vic_tab_map_vic(const char *disp_mode);
int hdmitx21_edid_parse(struct hdmitx_dev *hdev);
int check21_dvi_hdmi_edid_valid(u8 *buf);
enum hdmi_vic hdmitx21_edid_get_VIC(struct hdmitx_dev *hdev,
const char *disp_mode,
char force_flag);
bool hdmitx21_edid_check_valid_mode(struct hdmitx_dev *hdev,
struct hdmi_format_para *para);
const char *hdmitx21_edid_vic_to_string(enum hdmi_vic vic);
void hdmitx21_edid_clear(struct hdmitx_dev *hdev);
void hdmitx21_edid_ram_buffer_clear(struct hdmitx_dev *hdev);
void hdmitx21_edid_buf_compare_print(struct hdmitx_dev *hdev);
void hdmitx21_dither_config(struct hdmitx_dev *hdev);
int hdmitx21_construct_vsif(struct hdmitx_dev *hdev,
enum vsif_type type, int on, void *param);
/* if vic is 93 ~ 95, or 98 (HDMI14 4K), return 1 */
bool _is_hdmi14_4k(enum hdmi_vic vic);
/* if vic is 96, 97, 101, 102, 106, 107, 4k 50/60hz, return 1 */
bool _is_y420_vic(enum hdmi_vic vic);
enum hdmi_tf_type hdmitx21_get_cur_hdr_st(void);
enum hdmi_tf_type hdmitx21_get_cur_dv_st(void);
enum hdmi_tf_type hdmitx21_get_cur_hdr10p_st(void);
/* set vic to AVI.VIC */
void hdmitx21_set_avi_vic(enum hdmi_vic vic);
@@ -456,7 +438,6 @@ int hdmitx21_set_uevent(enum hdmitx_event type, int val);
int hdmitx21_set_uevent_state(enum hdmitx_event type, int state);
void hdmi_set_audio_para(int para);
int get21_cur_vout_index(void);
void phy_hpll_off(void);
int get21_hpd_state(void);
void hdmitx21_event_notify(unsigned long state, void *arg);
@@ -492,8 +473,6 @@ enum ddc_op {
DDC_UNMUX_DDC,
};
int hdmitx21_ddc_hw_op(enum ddc_op cmd);
#define HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH 0x3
#define HDMITX_HWCMD_TURNOFF_HDMIHW 0x4
#define HDMITX_HWCMD_MUX_HPD 0x5
@@ -524,19 +503,5 @@ int hdmitx21_ddc_hw_op(enum ddc_op cmd);
#define INTR_MASKN_DISABLE 1
#define INTR_CLEAR 2
/* the hdmitx output limits to 1080p */
bool hdmitx21_limited_1080p(void);
/* test current vic is over limited or not */
bool hdmitx21_is_vic_over_limited_1080p(enum hdmi_vic vic);
void vsem_init_cfg(struct hdmitx_dev *hdev);
enum hdmi_tf_type hdmitx21_get_cur_hdr_st(void);
enum hdmi_tf_type hdmitx21_get_cur_dv_st(void);
enum hdmi_tf_type hdmitx21_get_cur_hdr10p_st(void);
bool hdmitx21_hdr_en(void);
bool hdmitx21_dv_en(void);
bool hdmitx21_hdr10p_en(void);
u32 aud_sr_idx_to_val(enum hdmi_audio_fs e_sr_idx);
bool hdmitx21_uboot_already_display(struct hdmitx_dev *hdev);
#endif
@@ -17,14 +17,6 @@
#define HDMI_INFOFRAME_TYPE_VENDOR2 (0x81 | 0x100)
struct frac_rate_table {
char *hz;
u32 sync_num_int;
u32 sync_den_int;
u32 sync_num_dec;
u32 sync_den_dec;
};
struct hdmitx_ctrl_ops {
int (*pre_enable_mode)(struct hdmitx_common *tx_comm, struct hdmi_format_para *para);
int (*enable_mode)(struct hdmitx_common *tx_comm, struct hdmi_format_para *para);
@@ -58,6 +58,8 @@ enum hdmi_aspect_ratio {
TV_ASPECT_RATIO_MAX
};
#define HDMI_INFOFRAME_TYPE_VENDOR2 (0x81 | 0x100)
enum frl_rate_enum {
FRL_NONE = 0,
FRL_3G3L = 1,
@@ -84,4 +86,16 @@ struct size_map {
enum hdmi_audio_sampsize ss;
};
#define HDMI_PACKET_TYPE_GCP 0x3
struct hdmitx_infoframe {
u32 enable;
union hdmi_infoframe vend;
union hdmi_infoframe avi;
union hdmi_infoframe spd;
union hdmi_infoframe aud;
union hdmi_infoframe drm;
union hdmi_infoframe emp;
};
#endif