mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
hdmitx: add validate mode api [1/1]
PD#SWPL-132959 Problem: mode validation is in many functions and checked many times. Solution: abstract the mode validate api and cleanup the flow in tx20. Verify: verify on ohm. Test: DRM-TX-27, DRM-TX-26,DRM-TX-28,DRM-TX-25,DRM-TX-20 Change-Id: I9ddd17718fa43ac7a670192ba72a48d9bc0a6dc5 Signed-off-by: sky zhou <sky.zhou@amlogic.com>
This commit is contained in:
committed by
gerrit autosubmit
parent
dfd329f86c
commit
3f4940271b
@@ -31,8 +31,6 @@
|
||||
#include "hw/common.h"
|
||||
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_edid.h>
|
||||
|
||||
const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name);
|
||||
|
||||
#define CEA_DATA_BLOCK_COLLECTION_ADDR_1STP 0x04
|
||||
#define VIDEO_TAG 0x40
|
||||
#define AUDIO_TAG 0x20
|
||||
@@ -2287,38 +2285,6 @@ static bool is_rx_support_y420(struct hdmitx_dev *hdev, enum hdmi_vic vic)
|
||||
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_720x480p60_4x3 ||
|
||||
vic == HDMI_720x480i60_4x3 ||
|
||||
vic == HDMI_720x576p50_4x3 ||
|
||||
vic == HDMI_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_720x480p60_16x9 ||
|
||||
vic == HDMI_720x480i60_16x9 ||
|
||||
vic == HDMI_720x576p50_16x9 ||
|
||||
vic == HDMI_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.
|
||||
@@ -2329,11 +2295,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
bool valid = 0;
|
||||
struct rx_cap *prxcap = NULL;
|
||||
const struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
|
||||
enum hdmi_vic *vesa_t = &hdev->tx_comm.rxcap.vesa_timing[0];
|
||||
unsigned int rx_max_tmds_clk = 0;
|
||||
unsigned int 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;
|
||||
@@ -2341,19 +2304,9 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
if (!hdev || !para)
|
||||
return 0;
|
||||
|
||||
/* if current limits to 1080p, here will check the freshrate and
|
||||
* 4k resolution
|
||||
*/
|
||||
if (hdmitx_limited_1080p()) {
|
||||
if (is_vic_over_limited_1080p(para->vic)) {
|
||||
pr_err("over limited vic%d in %s\n", para->vic, __func__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (para->vic == HDMI_0_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
if (para->sname)
|
||||
if (strcmp(para->sname, "invalid") == 0)
|
||||
return 0;
|
||||
/* exclude such as: 2160p60hz YCbCr444 10bit */
|
||||
switch (para->vic) {
|
||||
case HDMI_3840x2160p50_16x9:
|
||||
@@ -2383,38 +2336,6 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* target mode is not contained at RX SVD */
|
||||
for (i = 0; (i < prxcap->VIC_count) && (i < VIC_MAX_NUM); i++) {
|
||||
if (para->vic == prxcap->VIC[i]) {
|
||||
svd_flag = 1;
|
||||
break;
|
||||
} else if (hdmitx_check_4x3_16x9_mode(hdev, para->vic & 0xff)) {
|
||||
svd_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (para->vic >= HDMITX_VESA_OFFSET) {
|
||||
if (para->cd != COLORDEPTH_24B)
|
||||
return 0;
|
||||
if (para->cs != HDMI_COLORSPACE_RGB)
|
||||
return 0;
|
||||
for (i = 0; vesa_t[i] && i < VESA_MAX_TIMING; i++) {
|
||||
const struct hdmi_timing *timing =
|
||||
hdmitx_mode_vic_to_hdmi_timing(vesa_t[i]);
|
||||
|
||||
if (timing) {
|
||||
if (timing->vic >= HDMITX_VESA_OFFSET &&
|
||||
para->vic == timing->vic) {
|
||||
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;
|
||||
@@ -2424,11 +2345,12 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
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 (hdmitx_limited_1080p()) {
|
||||
if (false /*hdmitx_limited_1080p()*/) {
|
||||
if (rx_max_tmds_clk > 225)
|
||||
rx_max_tmds_clk = 225;
|
||||
}
|
||||
@@ -2511,110 +2433,6 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
return valid;
|
||||
}
|
||||
|
||||
static bool check_sd(struct rx_cap *prxcap, const char *_mode,
|
||||
const char *mode, const unsigned int _vic,
|
||||
unsigned int *vic)
|
||||
{
|
||||
int i;
|
||||
bool check1 = 0;
|
||||
bool check2 = 0;
|
||||
|
||||
if (strcmp(_mode, mode) == 0) {
|
||||
for (i = 0 ; i < prxcap->VIC_count ; i++) {
|
||||
if (prxcap->VIC[i] == _vic)
|
||||
check1 = 1;
|
||||
}
|
||||
for (i = 0 ; i < prxcap->VIC_count ; i++) {
|
||||
if (prxcap->VIC[i] == (_vic + 1))
|
||||
check2 = 1;
|
||||
}
|
||||
if (check1 == 1 && check2 == 0) {
|
||||
*vic = _vic;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For some TV only support 480p 4:3,
|
||||
*then consider it also supports in disp_cap
|
||||
*/
|
||||
static bool is_sink_only_sd_4x3(struct hdmitx_dev *hdev,
|
||||
const char *mode, unsigned int *vic)
|
||||
{
|
||||
struct rx_cap *prxcap = &hdev->tx_comm.rxcap;
|
||||
|
||||
if (check_sd(prxcap, "480i60hz", mode, HDMI_720x480i60_4x3, vic))
|
||||
return 1;
|
||||
if (check_sd(prxcap, "480p60hz", mode, HDMI_720x480p60_4x3, vic))
|
||||
return 1;
|
||||
if (check_sd(prxcap, "576i50hz", mode, HDMI_720x576i50_4x3, vic))
|
||||
return 1;
|
||||
if (check_sd(prxcap, "576p50hz", mode, HDMI_720x576p50_4x3, vic))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* force_flag: 0 means check with RX's edid */
|
||||
/* 1 means no check with RX's edid */
|
||||
enum hdmi_vic hdmitx_edid_get_VIC(struct hdmitx_dev *hdev,
|
||||
const char *disp_mode,
|
||||
char force_flag)
|
||||
{
|
||||
const struct hdmi_timing *timing;
|
||||
enum hdmi_vic vic = HDMI_0_UNKNOWN;
|
||||
struct rx_cap *prxcap = &hdev->tx_comm.rxcap;
|
||||
enum hdmi_vic *vesa_t = &prxcap->vesa_timing[0];
|
||||
enum hdmi_vic vesa_vic;
|
||||
int j;
|
||||
|
||||
timing = hdmitx_mode_match_timing_name(disp_mode);
|
||||
if (!timing || timing->vic == HDMI_0_UNKNOWN)
|
||||
return HDMI_0_UNKNOWN;
|
||||
|
||||
if (hdmitx_hw_validate_mode(&hdev->tx_hw, timing->vic) != 0)
|
||||
return HDMI_0_UNKNOWN;
|
||||
|
||||
vic = timing->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;
|
||||
}
|
||||
/* if TV only supports 480p/2, add 480p60hz as well */
|
||||
if (is_sink_only_sd_4x3(hdev, disp_mode, &vic)) {
|
||||
; /* pr_debug("hdmitx: find SD only 4x3\n"); */
|
||||
}
|
||||
}
|
||||
|
||||
if (vic == HDMI_UNKNOWN && vesa_vic != HDMI_UNKNOWN) {
|
||||
for (j = 0; vesa_t[j] && j < VESA_MAX_TIMING; j++) {
|
||||
timing = hdmitx_mode_vic_to_hdmi_timing(vesa_t[j]);
|
||||
|
||||
if (timing) {
|
||||
if (timing->vic >= HDMITX_VESA_OFFSET &&
|
||||
vesa_vic == timing->vic) {
|
||||
vic = timing->vic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vic;
|
||||
}
|
||||
|
||||
/* Clear HDMI Hardware Module EDID RAM and EDID Buffer */
|
||||
void hdmitx_edid_ram_buffer_clear(struct hdmitx_dev *hdmitx_device)
|
||||
{
|
||||
|
||||
@@ -200,8 +200,6 @@ static bool hdmitx_edid_done;
|
||||
* when switch DV(LL)->HLG
|
||||
*/
|
||||
static int hdr_mute_frame = 20;
|
||||
static unsigned int res_1080p;
|
||||
static u32 max_refreshrate = 60;
|
||||
static char suspend_fmt_attr[16];
|
||||
|
||||
struct vout_device_s hdmitx_vdev = {
|
||||
@@ -520,25 +518,22 @@ static int set_disp_mode(const char *mode)
|
||||
{
|
||||
int ret = -1;
|
||||
enum hdmi_vic vic;
|
||||
const struct hdmi_timing *timing = 0;
|
||||
|
||||
vic = hdmitx_edid_get_VIC(&hdmitx_device, mode, 1);
|
||||
if (strncmp(mode, "2160p30hz", strlen("2160p30hz")) == 0)
|
||||
vic = HDMI_3840x2160p30_16x9;
|
||||
else if (strncmp(mode, "2160p25hz", strlen("2160p25hz")) == 0)
|
||||
vic = HDMI_3840x2160p25_16x9;
|
||||
else if (strncmp(mode, "2160p24hz", strlen("2160p24hz")) == 0)
|
||||
vic = HDMI_3840x2160p24_16x9;
|
||||
else if (strncmp(mode, "smpte24hz", strlen("smpte24hz")) == 0)
|
||||
vic = HDMI_4096x2160p24_256x135;
|
||||
else
|
||||
;/* nothing */
|
||||
/*function for debug, only get vic and check if ip can support, skip rx cap check.*/
|
||||
timing = hdmitx_mode_match_timing_name(mode);
|
||||
if (!timing || timing->vic == HDMI_0_UNKNOWN) {
|
||||
pr_err("unknown mode %s\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strncmp(mode, "1080p60hz", strlen("1080p60hz")) == 0)
|
||||
vic = HDMI_1080p60;
|
||||
if (strncmp(mode, "1080p50hz", strlen("1080p50hz")) == 0)
|
||||
vic = HDMI_1080p50;
|
||||
vic = timing->vic;
|
||||
if (hdmitx_common_validate_mode(&hdmitx_device.tx_comm, timing->vic) != 0) {
|
||||
pr_err("ip cannot support mode %s. %d\n", mode, timing->vic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vic != HDMI_UNKNOWN) {
|
||||
if (vic != HDMI_0_UNKNOWN) {
|
||||
hdmitx_device.mux_hpd_if_pin_high_flag = 1;
|
||||
if (hdmitx_device.vic_count == 0) {
|
||||
if (hdmitx_device.unplug_powerdown)
|
||||
@@ -1177,24 +1172,12 @@ static unsigned int hdmitx_get_frame_duration(void)
|
||||
return frame_duration;
|
||||
}
|
||||
|
||||
static int hdmitx_check_vic(int vic)
|
||||
{
|
||||
struct hdmitx_dev *hdev = &hdmitx_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)
|
||||
{
|
||||
switch (vic) {
|
||||
case HDMI_720x480p60_4x3:
|
||||
if (hdmitx_check_vic(HDMI_720x480p60_16x9)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap,
|
||||
HDMI_720x480p60_16x9) == 0) {
|
||||
if (aspect_ratio == AR_16X9)
|
||||
return 1;
|
||||
pr_info("same aspect_ratio = %d\n", aspect_ratio);
|
||||
@@ -1203,7 +1186,8 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
|
||||
}
|
||||
break;
|
||||
case HDMI_720x480p60_16x9:
|
||||
if (hdmitx_check_vic(HDMI_720x480p60_4x3)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap,
|
||||
HDMI_720x480p60_4x3) == 0) {
|
||||
if (aspect_ratio == AR_4X3)
|
||||
return 1;
|
||||
pr_info("same aspect_ratio = %d\n", aspect_ratio);
|
||||
@@ -1212,7 +1196,8 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
|
||||
}
|
||||
break;
|
||||
case HDMI_720x576p50_4x3:
|
||||
if (hdmitx_check_vic(HDMI_720x576p50_16x9)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap,
|
||||
HDMI_720x576p50_16x9) == 0) {
|
||||
if (aspect_ratio == AR_16X9)
|
||||
return 1;
|
||||
pr_info("same aspect_ratio = %d\n", aspect_ratio);
|
||||
@@ -1221,7 +1206,8 @@ static int hdmitx_check_valid_aspect_ratio(enum hdmi_vic vic, int aspect_ratio)
|
||||
}
|
||||
break;
|
||||
case HDMI_720x576p50_16x9:
|
||||
if (hdmitx_check_vic(HDMI_720x576p50_4x3)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap,
|
||||
HDMI_720x576p50_4x3) == 0) {
|
||||
if (aspect_ratio == AR_4X3)
|
||||
return 1;
|
||||
pr_info("same aspect_ratio = %d\n", aspect_ratio);
|
||||
@@ -1266,10 +1252,11 @@ struct aspect_ratio_list *hdmitx_get_support_ar_list(void)
|
||||
{
|
||||
static struct aspect_ratio_list ar_list[4];
|
||||
int i = 0;
|
||||
struct rx_cap *prxcap = &hdmitx_device.tx_comm.rxcap;
|
||||
|
||||
memset(ar_list, 0, sizeof(ar_list));
|
||||
if (hdmitx_check_vic(HDMI_720x480p60_4x3) &&
|
||||
hdmitx_check_vic(HDMI_720x480p60_16x9)) {
|
||||
if (hdmitx_edid_validate_mode(prxcap, HDMI_720x480p60_4x3) == 0 &&
|
||||
hdmitx_edid_validate_mode(prxcap, HDMI_720x480p60_16x9) == 0) {
|
||||
ar_list[i].vic = HDMI_720x480p60_4x3;
|
||||
ar_list[i].flag = TRUE;
|
||||
ar_list[i].aspect_ratio_num = 4;
|
||||
@@ -1282,8 +1269,8 @@ struct aspect_ratio_list *hdmitx_get_support_ar_list(void)
|
||||
ar_list[i].aspect_ratio_den = 9;
|
||||
i++;
|
||||
}
|
||||
if (hdmitx_check_vic(HDMI_720x576p50_4x3) &&
|
||||
hdmitx_check_vic(HDMI_720x576p50_16x9)) {
|
||||
if (hdmitx_edid_validate_mode(prxcap, HDMI_720x576p50_4x3) == 0 &&
|
||||
hdmitx_edid_validate_mode(prxcap, HDMI_720x576p50_16x9) == 0) {
|
||||
ar_list[i].vic = HDMI_720x576p50_4x3;
|
||||
ar_list[i].flag = TRUE;
|
||||
ar_list[i].aspect_ratio_num = 4;
|
||||
@@ -1693,20 +1680,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
|
||||
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
|
||||
}
|
||||
|
||||
static int hdmi_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 = hdmitx_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 hdmi_get_fmt_para(vic, attr, para);
|
||||
}
|
||||
|
||||
static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct vinfo_s *tx_vinfo)
|
||||
{
|
||||
/* manually assign hdmitx_vinfo from timing */
|
||||
@@ -1756,8 +1729,18 @@ static void update_para_from_mode(struct hdmitx_dev *hdev,
|
||||
struct hdmi_format_para *update_para)
|
||||
{
|
||||
struct vinfo_s *vinfo = &hdev->tx_comm.hdmitx_vinfo;
|
||||
enum hdmi_vic vic = HDMI_0_UNKNOWN;
|
||||
|
||||
if (hdmi_get_valid_fmt_para(hdev, name, fmt_attr, update_para) < 0) {
|
||||
vic = hdmitx_parse_mode_vic(&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_mode(&hdev->tx_comm, vic) != 0)
|
||||
return;
|
||||
|
||||
if (hdmi_get_fmt_para(vic, fmt_attr, update_para) < 0) {
|
||||
pr_err("get format para failed (%s,%s)\n", name, fmt_attr);
|
||||
hdmitx_reset_format_para(update_para);
|
||||
return;
|
||||
@@ -1789,14 +1772,7 @@ static void update_current_para(struct hdmitx_dev *hdev)
|
||||
if (!info || !info->name)
|
||||
return;
|
||||
memset(mode, 0, sizeof(mode));
|
||||
if (!info || !info->name)
|
||||
strncpy(mode, " ", sizeof(mode) - 1);
|
||||
else
|
||||
strncpy(mode, info->name, sizeof(mode) - 1);
|
||||
if (strstr(hdev->tx_comm.fmt_attr, "420")) {
|
||||
if (!strstr(mode, "420"))
|
||||
strncat(mode, "420", sizeof(mode) - strlen("420") - 1);
|
||||
}
|
||||
strncpy(mode, info->name, sizeof(mode) - 1);
|
||||
|
||||
update_para_from_mode(hdev, mode,
|
||||
hdev->tx_comm.fmt_attr, &hdev->tx_comm.fmt_para);
|
||||
@@ -2890,104 +2866,6 @@ static ssize_t debug_store(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
/* 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 validate_mode_refreshrate(enum hdmi_vic vic, u32 maxfreq)
|
||||
{
|
||||
const struct hdmi_timing *timing = hdmitx_mode_vic_to_hdmi_timing(vic);
|
||||
|
||||
if (!timing || vic == HDMI_0_UNKNOWN)
|
||||
return false;
|
||||
|
||||
/* if the vic equals to HDMI_UNKNOWN or VESA,
|
||||
* then create it as over limited
|
||||
*/
|
||||
if (vic >= HDMITX_VESA_OFFSET)
|
||||
return true;
|
||||
|
||||
if (timing->v_freq > (maxfreq * 1000)) {
|
||||
pr_info("validate refreshrate (%s)-(%d) fail\n",
|
||||
timing->name, timing->v_freq);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_vic_over_limited_1080p(enum hdmi_vic vic)
|
||||
{
|
||||
const struct hdmi_timing *timing = hdmitx_mode_vic_to_hdmi_timing(vic);
|
||||
|
||||
if (!timing) {
|
||||
pr_err("unsupported vic: %d\n", vic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if the vic equals to HDMI_UNKNOWN or VESA,
|
||||
* then create it as over limited
|
||||
*/
|
||||
if (vic == HDMI_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 hdmitx_limited_1080p(void)
|
||||
{
|
||||
return res_1080p;
|
||||
}
|
||||
|
||||
bool hdmitx_validate_vic_para(enum hdmi_vic vic, const char *attr)
|
||||
{
|
||||
struct hdmi_format_para tst_para;
|
||||
|
||||
if (hdmi_get_fmt_para(vic, attr, &tst_para) < 0)
|
||||
return false;
|
||||
|
||||
return hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para);
|
||||
}
|
||||
|
||||
/* for some non-std TV, it declare 4k while MAX_TMDS_CLK
|
||||
* not match 4K format, so filter out mode list by
|
||||
* check if basic color space/depth is supported
|
||||
@@ -2995,6 +2873,8 @@ bool hdmitx_validate_vic_para(enum hdmi_vic vic, const char *attr)
|
||||
*/
|
||||
static bool hdmitx_validate_vic(enum hdmi_vic vic)
|
||||
{
|
||||
struct hdmi_format_para tst_para;
|
||||
|
||||
if (vic == HDMI_0_UNKNOWN)
|
||||
return false;
|
||||
|
||||
@@ -3002,22 +2882,23 @@ static bool hdmitx_validate_vic(enum hdmi_vic vic)
|
||||
vic == HDMI_97_3840x2160p60_16x9 ||
|
||||
vic == HDMI_101_4096x2160p50_256x135 ||
|
||||
vic == HDMI_102_4096x2160p60_256x135) {
|
||||
if (hdmitx_validate_vic_para(vic, "420,8bit"))
|
||||
return true;
|
||||
if (hdmitx_validate_vic_para(vic, "rgb,8bit"))
|
||||
return true;
|
||||
if (hdmitx_validate_vic_para(vic, "444,8bit"))
|
||||
return true;
|
||||
if (hdmitx_validate_vic_para(vic, "422,12bit"))
|
||||
return true;
|
||||
} else {
|
||||
if (hdmitx_validate_vic_para(vic, "rgb,8bit"))
|
||||
return true;
|
||||
if (hdmitx_validate_vic_para(vic, "444,8bit"))
|
||||
return true;
|
||||
if (hdmitx_validate_vic_para(vic, "422,12bit"))
|
||||
if (hdmi_get_fmt_para(vic, "420,8bit", &tst_para) == 0 &&
|
||||
hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hdmi_get_fmt_para(vic, "rgb,8bit", &tst_para) == 0 &&
|
||||
hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para))
|
||||
return true;
|
||||
|
||||
if (hdmi_get_fmt_para(vic, "444,8bit", &tst_para) == 0 &&
|
||||
hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para))
|
||||
return true;
|
||||
|
||||
if (hdmi_get_fmt_para(vic, "422,12bit", &tst_para) == 0 &&
|
||||
hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3053,7 +2934,8 @@ static ssize_t disp_cap_show(struct device *dev,
|
||||
vic == HDMI_6_720x480i60_4x3 ||
|
||||
vic == HDMI_17_720x576p50_4x3 ||
|
||||
vic == HDMI_21_720x576i50_4x3) {
|
||||
if (hdmitx_check_vic(vic + 1)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap,
|
||||
vic + 1) == 0) {
|
||||
pr_info("%s: check vic exist, handle [%d] later.\n",
|
||||
__func__, vic + 1);
|
||||
continue;
|
||||
@@ -3066,13 +2948,11 @@ static ssize_t disp_cap_show(struct device *dev,
|
||||
continue;
|
||||
}
|
||||
|
||||
/*filter 1080p max size.*/
|
||||
if (hdmitx_limited_1080p() && is_vic_over_limited_1080p(vic))
|
||||
continue;
|
||||
|
||||
/*filter max refreshrate.*/
|
||||
if (validate_mode_refreshrate(vic, max_refreshrate) == false)
|
||||
if (hdmitx_common_validate_mode(&hdmitx_device.tx_comm, vic) != 0) {
|
||||
if (hdmitx_device.log_level & EDID_LOG)
|
||||
pr_err("%s: vic[%d] over range.\n", __func__, vic);
|
||||
continue;
|
||||
}
|
||||
|
||||
mode_name = timing->sname ? timing->sname : timing->name;
|
||||
|
||||
@@ -3400,20 +3280,39 @@ static ssize_t dc_cap_show(struct device *dev,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static bool pre_process_str(char *name)
|
||||
static bool pre_process_str(const char *name, char *mode, char *attr)
|
||||
{
|
||||
int i;
|
||||
unsigned int flag = 0;
|
||||
char *color_format[4] = {"444", "422", "420", "rgb"};
|
||||
char *search_pos = 0;
|
||||
|
||||
if (!mode || !attr)
|
||||
return false;
|
||||
|
||||
for (i = 0 ; i < 4 ; i++) {
|
||||
if (strstr(name, color_format[i]))
|
||||
flag++;
|
||||
search_pos = strstr(name, color_format[i]);
|
||||
if (search_pos)
|
||||
break;
|
||||
}
|
||||
if (flag >= 2)
|
||||
/*no cs parsed, return error.*/
|
||||
if (!search_pos)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
||||
/*search remaining color_formats, if have more than one cs string, return error.*/
|
||||
i++;
|
||||
for (; i < 4 ; i++) {
|
||||
if (strstr(search_pos, color_format[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*copy mode name;*/
|
||||
memcpy(mode, name, search_pos - name);
|
||||
/*copy attr str;*/
|
||||
memcpy(attr, search_pos, strlen(search_pos));
|
||||
|
||||
// pr_info("%s parse (%s,%s) from (%s)\n", __func__, mode, attr, name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static ssize_t valid_mode_store(struct device *dev,
|
||||
@@ -3423,30 +3322,37 @@ static ssize_t valid_mode_store(struct device *dev,
|
||||
int ret;
|
||||
bool valid_mode = false;
|
||||
char cvalid_mode[32];
|
||||
char modename[32], attrstr[32];
|
||||
struct hdmi_format_para tst_para;
|
||||
enum hdmi_vic vic = HDMI_0_UNKNOWN;
|
||||
|
||||
mutex_lock(&valid_mode_mutex);
|
||||
|
||||
memset(modename, 0, sizeof(modename));
|
||||
memset(attrstr, 0, sizeof(attrstr));
|
||||
memset(cvalid_mode, 0, sizeof(cvalid_mode));
|
||||
|
||||
strncpy(cvalid_mode, buf, sizeof(cvalid_mode));
|
||||
cvalid_mode[31] = '\0';
|
||||
if (cvalid_mode[0]) {
|
||||
valid_mode = pre_process_str(cvalid_mode);
|
||||
if (valid_mode) {
|
||||
if (hdmi_get_valid_fmt_para(&hdmitx_device,
|
||||
cvalid_mode, cvalid_mode, &tst_para) == 0)
|
||||
valid_mode = true;
|
||||
else
|
||||
valid_mode = false;
|
||||
}
|
||||
if (cvalid_mode[0])
|
||||
valid_mode = pre_process_str(cvalid_mode, modename, attrstr);
|
||||
|
||||
if (valid_mode) {
|
||||
vic = hdmitx_parse_mode_vic(&hdmitx_device.tx_comm, modename);
|
||||
if (vic == HDMI_0_UNKNOWN ||
|
||||
hdmitx_common_validate_mode(&hdmitx_device.tx_comm, vic) != 0)
|
||||
valid_mode = false;
|
||||
}
|
||||
|
||||
if (valid_mode && hdmi_get_fmt_para(vic, attrstr, &tst_para) != 0)
|
||||
valid_mode = false;
|
||||
|
||||
if (valid_mode)
|
||||
valid_mode = hdmitx_edid_check_valid_mode(&hdmitx_device, &tst_para);
|
||||
ret = valid_mode ? count : -1;
|
||||
|
||||
ret = valid_mode ? count : -1;
|
||||
if (ret == -1)
|
||||
pr_info("hdmitx: valid_mode %s fail\n", cvalid_mode);
|
||||
pr_err("hdmitx: valid_mode %s fail\n", cvalid_mode);
|
||||
|
||||
mutex_unlock(&valid_mode_mutex);
|
||||
|
||||
@@ -6439,8 +6345,6 @@ int tv_audio_support(int type, struct rx_cap *prxcap)
|
||||
static bool is_cur_tmds_div40(struct hdmitx_dev *hdev)
|
||||
{
|
||||
struct hdmitx_common *tx_comm = &hdev->tx_comm;
|
||||
const struct hdmi_timing *timing = NULL;
|
||||
const char *modename = NULL;
|
||||
struct hdmi_format_para tst_para;
|
||||
unsigned int act_clk = 0;
|
||||
|
||||
@@ -6449,19 +6353,12 @@ static bool is_cur_tmds_div40(struct hdmitx_dev *hdev)
|
||||
|
||||
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",
|
||||
if (hdmi_get_fmt_para(hdev->tx_comm.cur_VIC, tx_comm->fmt_attr, &tst_para) < 0) {
|
||||
pr_info("%s[%d] get mode fail [%d] exit.\n",
|
||||
__func__, __LINE__, hdev->tx_comm.cur_VIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
modename = timing->sname ? timing->sname : timing->name;
|
||||
if (hdmi_get_valid_fmt_para(hdev, modename, tx_comm->fmt_attr, &tst_para) < 0) {
|
||||
pr_info("%s[%d] get mode fail [%s] exit.\n", __func__, __LINE__, modename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
act_clk = tst_para.tmds_clk / 1000;
|
||||
|
||||
pr_info("hdmitx: %s original clock %d\n", __func__, act_clk);
|
||||
@@ -6968,13 +6865,13 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev)
|
||||
hdmitx_device.dongle_mode);
|
||||
/* Get res_1080p information */
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "res_1080p",
|
||||
&res_1080p);
|
||||
res_1080p = !!res_1080p;
|
||||
&hdmitx_device.tx_comm.res_1080p);
|
||||
hdmitx_device.tx_comm.res_1080p = !!hdmitx_device.tx_comm.res_1080p;
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "max_refreshrate",
|
||||
&refreshrate_limit);
|
||||
if (ret == 0 && refreshrate_limit > 0)
|
||||
max_refreshrate = refreshrate_limit;
|
||||
hdmitx_device.tx_comm.max_refreshrate = refreshrate_limit;
|
||||
|
||||
/* Get repeater_tx information */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
@@ -7159,7 +7056,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
|
||||
struct hdmitx_common *tx_comm = &hdev->tx_comm;
|
||||
|
||||
pr_debug(SYS "%s start\n", __func__);
|
||||
hdmitx_common_init(tx_comm);
|
||||
hdmitx_common_init(tx_comm, &hdev->tx_hw);
|
||||
amhdmitx_device_init(hdev, get_hdmitx_boot_params());
|
||||
|
||||
ret = amhdmitx_get_dt_info(pdev);
|
||||
@@ -7585,26 +7482,19 @@ static int drm_hdmitx_get_vic_list(int **vics)
|
||||
vic == HDMI_6_720x480i60_4x3 ||
|
||||
vic == HDMI_17_720x576p50_4x3 ||
|
||||
vic == HDMI_21_720x576i50_4x3) {
|
||||
if (hdmitx_check_vic(vic + 1)) {
|
||||
if (hdmitx_edid_validate_mode(&hdmitx_device.tx_comm.rxcap, vic + 1) == 0) {
|
||||
pr_info("%s: check vic exist, handle [%d] later.\n",
|
||||
__func__, vic + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdmitx_limited_1080p() && is_vic_over_limited_1080p(vic)) {
|
||||
if (hdmitx_common_validate_mode(&hdmitx_device.tx_comm, vic) != 0) {
|
||||
if (hdmitx_device.log_level & EDID_LOG)
|
||||
pr_err("%s: vic[%d] over range.\n", __func__, vic);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (validate_mode_refreshrate(vic, max_refreshrate) == false) {
|
||||
if (hdmitx_device.log_level & EDID_LOG)
|
||||
pr_err("%s: vic[%d] over refresh rate[%d].\n",
|
||||
__func__, vic, max_refreshrate);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hdmitx_validate_vic(vic)) {
|
||||
if (hdmitx_device.log_level & EDID_LOG)
|
||||
pr_err("%s: vic[%d] check fmt attr failed.\n", __func__, vic);
|
||||
@@ -7768,15 +7658,15 @@ bool drm_hdmitx_chk_mode_attr_sup(char *mode, char *attr)
|
||||
if (!mode || !attr)
|
||||
return false;
|
||||
|
||||
if (!pre_process_str(attr))
|
||||
return false;
|
||||
|
||||
vic = hdmitx_edid_get_VIC(&hdmitx_device, mode, 0);
|
||||
vic = hdmitx_parse_mode_vic(&hdmitx_device.tx_comm, mode);
|
||||
if (vic == HDMI_0_UNKNOWN) {
|
||||
pr_err("%s: get vic from (%s) fail\n", __func__, mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdmitx_common_validate_mode(&hdmitx_device.tx_comm, vic) != 0)
|
||||
return false;
|
||||
|
||||
if (hdmi_get_fmt_para(vic, attr, &tst_para) < 0)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -6391,7 +6391,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
|
||||
struct hdmitx_dev *hdev = get_hdmitx21_device();
|
||||
struct hdmitx_common *tx_comm = &hdev->tx_comm;
|
||||
|
||||
hdmitx_common_init(&hdev->tx_comm);
|
||||
hdmitx_common_init(&hdev->tx_comm, &hdev->tx_hw);
|
||||
|
||||
pr_debug("amhdmitx_probe_start\n");
|
||||
amhdmitx21_device_init(hdev);
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h>
|
||||
#include <hdmitx_boot_parameters.h>
|
||||
|
||||
const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name);
|
||||
|
||||
struct hdmitx_base_state *hdmitx_get_mod_state(struct hdmitx_common *tx_common,
|
||||
enum HDMITX_MODULE type)
|
||||
{
|
||||
@@ -27,31 +30,78 @@ void hdmitx_get_init_state(struct hdmitx_common *tx_common,
|
||||
}
|
||||
EXPORT_SYMBOL(hdmitx_get_init_state);
|
||||
|
||||
int hdmitx_common_init(struct hdmitx_common *tx_common)
|
||||
int hdmitx_common_init(struct hdmitx_common *tx_comm, struct hdmitx_hw_common *hw_comm)
|
||||
{
|
||||
struct hdmitx_boot_param *boot_param = get_hdmitx_boot_params();
|
||||
|
||||
/*load tx boot params*/
|
||||
tx_common->hdr_priority = boot_param->hdr_mask;
|
||||
memcpy(tx_common->hdmichecksum, boot_param->edid_chksum, sizeof(tx_common->hdmichecksum));
|
||||
tx_comm->hdr_priority = boot_param->hdr_mask;
|
||||
memcpy(tx_comm->hdmichecksum, boot_param->edid_chksum, sizeof(tx_comm->hdmichecksum));
|
||||
|
||||
memcpy(tx_common->fmt_attr, boot_param->color_attr, sizeof(tx_common->fmt_attr));
|
||||
memcpy(tx_common->backup_fmt_attr, boot_param->color_attr, sizeof(tx_common->fmt_attr));
|
||||
memcpy(tx_comm->fmt_attr, boot_param->color_attr, sizeof(tx_comm->fmt_attr));
|
||||
memcpy(tx_comm->backup_fmt_attr, boot_param->color_attr, sizeof(tx_comm->fmt_attr));
|
||||
|
||||
tx_common->frac_rate_policy = boot_param->fraction_refreshrate;
|
||||
tx_common->backup_frac_rate_policy = boot_param->fraction_refreshrate;
|
||||
tx_common->config_csc_en = boot_param->config_csc;
|
||||
tx_comm->frac_rate_policy = boot_param->fraction_refreshrate;
|
||||
tx_comm->backup_frac_rate_policy = boot_param->fraction_refreshrate;
|
||||
tx_comm->config_csc_en = boot_param->config_csc;
|
||||
|
||||
tx_comm->res_1080p = 0;
|
||||
tx_comm->max_refreshrate = 60;
|
||||
|
||||
tx_comm->tx_hw = hw_comm;
|
||||
|
||||
/*mutex init*/
|
||||
mutex_init(&tx_common->setclk_mutex);
|
||||
mutex_init(&tx_comm->setclk_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmitx_common_destroy(struct hdmitx_common *tx_common)
|
||||
int hdmitx_common_destroy(struct hdmitx_common *tx_comm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmitx_common_validate_mode(struct hdmitx_common *tx_comm, u32 vic)
|
||||
{
|
||||
const struct hdmi_timing *timing = hdmitx_mode_vic_to_hdmi_timing(vic);
|
||||
|
||||
if (!timing)
|
||||
return -EINVAL;
|
||||
|
||||
/*soc level filter*/
|
||||
/*filter 1080p max size.*/
|
||||
if (tx_comm->res_1080p) {
|
||||
/* if the vic equals to HDMI_UNKNOWN or VESA,
|
||||
* then create it as over limited
|
||||
*/
|
||||
if (vic == HDMI_0_UNKNOWN || vic >= HDMITX_VESA_OFFSET)
|
||||
return -ERANGE;
|
||||
|
||||
/* check the resolution is over 1920x1080 or not */
|
||||
if (timing->h_active > 1920 || timing->v_active > 1080)
|
||||
return -ERANGE;
|
||||
|
||||
/* check the fresh rate is over 60hz or not */
|
||||
if (timing->v_freq > 60000)
|
||||
return -ERANGE;
|
||||
|
||||
/* test current vic is over 150MHz or not */
|
||||
if (timing->pixel_freq > 150000)
|
||||
return -ERANGE;
|
||||
}
|
||||
/*filter max refreshrate.*/
|
||||
if (timing->v_freq > (tx_comm->max_refreshrate * 1000)) {
|
||||
pr_info("validate refreshrate (%s)-(%d) fail\n",
|
||||
timing->name, timing->v_freq);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/*ip level filter*/
|
||||
if (tx_comm->tx_hw->validatemode(vic) != 0)
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmitx_hpd_notify_unlocked(struct hdmitx_common *tx_comm)
|
||||
{
|
||||
if (tx_comm->drm_hpd_cb.callback)
|
||||
@@ -145,6 +195,71 @@ int hdmitx_update_edid_chksum(u8 *buf, u32 block_cnt, struct rx_cap *rxcap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum hdmi_vic get_alternate_ar_vic(enum hdmi_vic vic)
|
||||
{
|
||||
int i = 0;
|
||||
struct {
|
||||
u32 mode_16x9_vic;
|
||||
u32 mode_4x3_vic;
|
||||
} vic_pairs[] = {
|
||||
{HDMI_7_720x480i60_16x9, HDMI_6_720x480i60_4x3},
|
||||
{HDMI_3_720x480p60_16x9, HDMI_2_720x480p60_4x3},
|
||||
{HDMI_22_720x576i50_16x9, HDMI_21_720x576i50_4x3},
|
||||
{HDMI_18_720x576p50_16x9, HDMI_17_720x576p50_4x3},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vic_pairs); i++) {
|
||||
if (vic_pairs[i].mode_16x9_vic == vic)
|
||||
return vic_pairs[i].mode_4x3_vic;
|
||||
if (vic_pairs[i].mode_4x3_vic == vic)
|
||||
return vic_pairs[i].mode_16x9_vic;
|
||||
}
|
||||
|
||||
return HDMI_0_UNKNOWN;
|
||||
}
|
||||
|
||||
int hdmitx_parse_mode_vic(struct hdmitx_common *tx_comm, const char *mode)
|
||||
{
|
||||
const struct hdmi_timing *timing;
|
||||
enum hdmi_vic vic = HDMI_0_UNKNOWN;
|
||||
enum hdmi_vic alternate_vic = HDMI_0_UNKNOWN;
|
||||
|
||||
/*parse by name to find default mode*/
|
||||
timing = hdmitx_mode_match_timing_name(mode);
|
||||
if (!timing || timing->vic == HDMI_0_UNKNOWN)
|
||||
return HDMI_0_UNKNOWN;
|
||||
|
||||
vic = timing->vic;
|
||||
/* for compatibility: 480p/576p
|
||||
* 480p/576p use same short name in hdmitx_timing table, so when match name, will return
|
||||
* 4x3 mode fist. But user prefer 16x9 first, so try 16x9 first;
|
||||
*/
|
||||
alternate_vic = get_alternate_ar_vic(vic);
|
||||
if (alternate_vic != HDMI_0_UNKNOWN) {
|
||||
pr_info("get alternate vic %d->%d\n", vic, alternate_vic);
|
||||
vic = alternate_vic;
|
||||
}
|
||||
|
||||
/*check if vic supported by rx*/
|
||||
if (hdmitx_edid_validate_mode(&tx_comm->rxcap, vic) == 0)
|
||||
return vic;
|
||||
|
||||
/* for compatibility: 480p/576p, will get 0 if there is no alternate vic;*/
|
||||
alternate_vic = get_alternate_ar_vic(vic);
|
||||
if (alternate_vic != vic) {
|
||||
pr_info("get alternate vic %d->%d\n", vic, alternate_vic);
|
||||
vic = alternate_vic;
|
||||
}
|
||||
|
||||
if (vic != HDMI_0_UNKNOWN && hdmitx_edid_validate_mode(&tx_comm->rxcap, vic) != 0)
|
||||
vic = HDMI_0_UNKNOWN;
|
||||
|
||||
if (vic == HDMI_0_UNKNOWN)
|
||||
pr_err("%s: parse mode %s fail\n", __func__, mode);
|
||||
|
||||
return vic;
|
||||
}
|
||||
|
||||
/********************************Debug function***********************************/
|
||||
int hdmitx_load_edid_file(char *path)
|
||||
{
|
||||
|
||||
@@ -183,3 +183,31 @@ u32 hdmitx_edid_get_hdmi14_4k_vic(u32 vic)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hdmitx_edid_validate_mode(struct rx_cap *rxcap, u32 vic)
|
||||
{
|
||||
int i = 0;
|
||||
bool edid_matched = false;
|
||||
|
||||
if (vic < HDMITX_VESA_OFFSET) {
|
||||
/*check cea cap*/
|
||||
for (i = 0 ; i < rxcap->VIC_count; i++) {
|
||||
if (rxcap->VIC[i] == vic) {
|
||||
edid_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enum hdmi_vic *vesa_t = &rxcap->vesa_timing[0];
|
||||
/*check vesa mode.*/
|
||||
for (i = 0; i < VESA_MAX_TIMING && vesa_t[i]; i++) {
|
||||
if (vic == vesa_t[i]) {
|
||||
edid_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return edid_matched ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,3 @@ int hdmitx_hw_set_phy(struct hdmitx_hw_common *tx_hw, int flag)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmitx_hw_validate_mode(struct hdmitx_hw_common *tx_hw,
|
||||
u32 vic)
|
||||
{
|
||||
return tx_hw->validatemode(vic);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ static const struct hdmi_timing edid_cea_modes_0[] = {
|
||||
{HDMI_0_UNKNOWN, "invalid", NULL},
|
||||
{HDMI_1_640x480p60_4x3, "640x480p60hz", NULL, 1, 31469, 59940, 25175,
|
||||
800, 160, 16, 96, 48, 640, 525, 45, 10, 2, 33, 480, 1, 0, 0, 4, 3, 1, 1},
|
||||
{HDMI_2_720x480p60_4x3, "720x480p60hz", "480p60hz_4x3", 1, 31469, 59940, 27000,
|
||||
{HDMI_2_720x480p60_4x3, "720x480p60hz", "480p60hz", 1, 31469, 59940, 27000,
|
||||
858, 138, 16, 62, 60, 720, 525, 45, 9, 6, 30, 480, 7, 0, 0, 4, 3, 8, 9},
|
||||
{HDMI_3_720x480p60_16x9, "720x480p60hz", "480p60hz", 1, 31469, 59940, 27000,
|
||||
858, 138, 16, 62, 60, 720, 525, 45, 9, 6, 30, 480, 7, 0, 0, 16, 9, 32, 27},
|
||||
@@ -54,7 +54,7 @@ static const struct hdmi_timing edid_cea_modes_0[] = {
|
||||
1716, 276, 32, 124, 120, 1440, 525, 45, 9, 6, 30, 480, 7, 0, 0, 16, 9, 16, 27},
|
||||
{HDMI_16_1920x1080p60_16x9, "1920x1080p60hz", "1080p60hz", 1, 67500, 60000, 148500,
|
||||
2200, 280, 88, 44, 148, 1920, 1125, 45, 4, 5, 36, 1080, 1, 1, 1, 16, 9, 1, 1},
|
||||
{HDMI_17_720x576p50_4x3, "720x576p50hz", "576p50hz_4x3", 1, 31250, 50000, 27000,
|
||||
{HDMI_17_720x576p50_4x3, "720x576p50hz", "576p50hz", 1, 31250, 50000, 27000,
|
||||
864, 144, 12, 64, 68, 720, 625, 49, 5, 5, 39, 576, 1, 0, 0, 4, 3, 16, 15},
|
||||
{HDMI_18_720x576p50_16x9, "720x576p50hz", "576p50hz", 1, 31250, 50000, 27000,
|
||||
864, 144, 12, 64, 68, 720, 625, 49, 5, 5, 39, 576, 1, 0, 0, 16, 9, 64, 65},
|
||||
@@ -546,11 +546,11 @@ const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name)
|
||||
break;
|
||||
|
||||
/* check sname first */
|
||||
if (timing->sname && !strncmp(timing->sname, name, strlen(timing->sname)))
|
||||
if (timing->sname && !strcmp(timing->sname, name))
|
||||
return timing;
|
||||
|
||||
/* check full name first */
|
||||
if (!strncmp(timing->name, name, strlen(timing->name)))
|
||||
if (!strcmp(timing->name, name))
|
||||
return timing;
|
||||
|
||||
i++;
|
||||
@@ -636,27 +636,6 @@ int hdmitx_mode_update_timing(struct hdmi_timing *t,
|
||||
return alternate_clock;
|
||||
}
|
||||
|
||||
enum hdmi_vic hdmitx_mode_get_alternate_4x3_vic(enum hdmi_vic vic)
|
||||
{
|
||||
int i = 0;
|
||||
struct {
|
||||
u32 mode_16x9_vic;
|
||||
u32 mode_4x3_vic;
|
||||
} vic_pairs[] = {
|
||||
{HDMI_7_720x480i60_16x9, HDMI_6_720x480i60_4x3},
|
||||
{HDMI_3_720x480p60_16x9, HDMI_2_720x480p60_4x3},
|
||||
{HDMI_22_720x576i50_16x9, HDMI_21_720x576i50_4x3},
|
||||
{HDMI_18_720x576p50_16x9, HDMI_17_720x576p50_4x3},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vic_pairs); i++) {
|
||||
if (vic_pairs[i].mode_16x9_vic == vic)
|
||||
return vic_pairs[i].mode_4x3_vic;
|
||||
}
|
||||
|
||||
return HDMI_0_UNKNOWN;
|
||||
}
|
||||
|
||||
void hdmitx_mode_print_hdmi_timing(const struct hdmi_timing *t)
|
||||
{
|
||||
struct hdmi_timing alternate_t;
|
||||
|
||||
@@ -481,9 +481,6 @@ struct hdmitx_dev {
|
||||
**********************************************************************/
|
||||
int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device);
|
||||
int check_dvi_hdmi_edid_valid(unsigned char *buf);
|
||||
enum hdmi_vic hdmitx_edid_get_VIC(struct hdmitx_dev *hdmitx_device,
|
||||
const char *disp_mode,
|
||||
char force_flag);
|
||||
bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev,
|
||||
struct hdmi_format_para *para);
|
||||
void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device);
|
||||
@@ -507,11 +504,6 @@ bool is_hdmi14_4k(enum hdmi_vic vic);
|
||||
*/
|
||||
bool is_hdmi4k_support_420(enum hdmi_vic vic);
|
||||
|
||||
/* the hdmitx output limits to 1080p */
|
||||
bool hdmitx_limited_1080p(void);
|
||||
/* test current vic is over limited or not */
|
||||
bool is_vic_over_limited_1080p(enum hdmi_vic vic);
|
||||
|
||||
/*
|
||||
* HDMI Repeater TX I/F
|
||||
* RX downstream Information from rptx to rprx
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/hdmi.h>
|
||||
|
||||
#include <drm/amlogic/meson_connector_dev.h>
|
||||
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h>
|
||||
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_edid.h>
|
||||
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_types.h>
|
||||
|
||||
@@ -67,6 +68,12 @@ struct hdmitx_common {
|
||||
|
||||
struct hdmitx_base_state *states[HDMITX_MAX_MODULE];
|
||||
struct hdmitx_base_state *old_states[HDMITX_MAX_MODULE];
|
||||
|
||||
/*soc limitation*/
|
||||
int res_1080p;
|
||||
int max_refreshrate;
|
||||
|
||||
struct hdmitx_hw_common *tx_hw;
|
||||
};
|
||||
|
||||
struct hdmitx_base_state *hdmitx_get_mod_state(struct hdmitx_common *tx_common,
|
||||
@@ -76,7 +83,7 @@ struct hdmitx_base_state *hdmitx_get_old_mod_state(struct hdmitx_common *tx_comm
|
||||
void hdmitx_get_init_state(struct hdmitx_common *tx_common,
|
||||
struct hdmitx_binding_state *state);
|
||||
|
||||
int hdmitx_common_init(struct hdmitx_common *tx_common);
|
||||
int hdmitx_common_init(struct hdmitx_common *tx_common, struct hdmitx_hw_common *hw_comm);
|
||||
int hdmitx_common_destroy(struct hdmitx_common *tx_common);
|
||||
|
||||
int hdmitx_hpd_notify_unlocked(struct hdmitx_common *tx_comm);
|
||||
@@ -86,6 +93,13 @@ unsigned char *hdmitx_get_raw_edid(struct hdmitx_common *tx_comm);
|
||||
int hdmitx_setup_attr(struct hdmitx_common *tx_comm, const char *buf);
|
||||
int hdmitx_get_attr(struct hdmitx_common *tx_comm, char attr[16]);
|
||||
|
||||
/* modename policy: get vic from name and check if support by rx;
|
||||
* return the vic of mode, if failed return HDMI_0_UNKNOWN;
|
||||
*/
|
||||
int hdmitx_parse_mode_vic(struct hdmitx_common *tx_comm, const char *mode);
|
||||
|
||||
int hdmitx_common_validate_mode(struct hdmitx_common *tx_comm, u32 vic);
|
||||
|
||||
int hdmitx_get_hdrinfo(struct hdmitx_common *tx_comm, struct hdr_info *hdrinfo);
|
||||
|
||||
/*edid related function.*/
|
||||
|
||||
@@ -248,6 +248,8 @@ enum vsif_type {
|
||||
u32 hdmitx_edid_get_hdmi14_4k_vic(u32 vic);
|
||||
void phy_addr_clear(struct vsdb_phyaddr *vsdb_phy_addr);
|
||||
|
||||
int hdmitx_edid_validate_mode(struct rx_cap *rxcap, u32 vic);
|
||||
|
||||
/*edid is good return 0, otherwise return < 0.*/
|
||||
int hdmitx_edid_validate(unsigned char *rawedid);
|
||||
bool hdmitx_edid_is_all_zeros(unsigned char *rawedid);
|
||||
|
||||
@@ -188,7 +188,5 @@ int hdmitx_hw_avmute(struct hdmitx_hw_common *tx_hw,
|
||||
int muteflag);
|
||||
int hdmitx_hw_set_phy(struct hdmitx_hw_common *tx_hw,
|
||||
int flag);
|
||||
int hdmitx_hw_validate_mode(struct hdmitx_hw_common *tx_hw,
|
||||
u32 vic);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user