hdmitx: optimise hdmi struct member [1/1]

PD#SWPL-141539

Problem:
Need to clean hdmitx_common/edid member data

Solution:
Clean the hdmitx_common
Clean edid_ptr, EDID_hash, edid_done
Unify hdmi reading edid

Verify:
ohm/t7c

Test:
DRM-TX-37

Change-Id: Ibba7fc61cb3103c1d9a539ee395cb06dd29e4507
Signed-off-by: zongdong.jiao <zongdong.jiao@amlogic.com>
This commit is contained in:
zongdong.jiao
2023-09-30 13:43:36 +08:00
committed by Ao Xu
parent 701d14f09a
commit 7ae328db6f
14 changed files with 322 additions and 424 deletions
@@ -32,10 +32,10 @@ bool hdmitx_find_vendor_6g(struct hdmitx_dev *hdev)
{
int i;
if (!hdev || !hdev->tx_comm.edid_ptr)
if (!hdev)
return false;
for (i = 0; i < ARRAY_SIZE(vendor_6g); i++) {
if (memcmp(&hdev->tx_comm.edid_ptr[8], vendor_6g[i].data,
if (memcmp(&hdev->tx_comm.EDID_buf[8], vendor_6g[i].data,
sizeof(vendor_6g[i].data)) == 0)
return true;
}
@@ -47,10 +47,10 @@ bool hdmitx_find_vendor_ratio(struct hdmitx_dev *hdev)
{
int i;
if (!hdev || !hdev->tx_comm.edid_ptr)
if (!hdev)
return false;
for (i = 0; i < ARRAY_SIZE(vendor_ratio); i++) {
if (memcmp(&hdev->tx_comm.edid_ptr[8], vendor_ratio[i].data,
if (memcmp(&hdev->tx_comm.EDID_buf[8], vendor_ratio[i].data,
sizeof(vendor_ratio[i].data)) == 0)
return true;
}
@@ -62,10 +62,10 @@ bool hdmitx_find_vendor_null_pkt(struct hdmitx_dev *hdev)
{
int i;
if (!hdev || !hdev->tx_comm.edid_ptr)
if (!hdev)
return false;
for (i = 0; i < ARRAY_SIZE(vendor_null_pkt); i++) {
if (memcmp(&hdev->tx_comm.edid_ptr[8], vendor_null_pkt[i].data,
if (memcmp(&hdev->tx_comm.EDID_buf[8], vendor_null_pkt[i].data,
sizeof(vendor_null_pkt[i].data)) == 0)
return true;
}
@@ -52,8 +52,6 @@
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_audio.h>
#include <linux/of_gpio.h>
#include <linux/rtc.h>
#include <linux/timekeeping.h>
#include "hw/tvenc_conf.h"
#include "hw/common.h"
@@ -82,7 +80,6 @@
#define to_hdmitx20_dev(x) container_of(x, struct hdmitx_dev, tx_comm)
static struct class *hdmitx_class;
static void hdmitx_get_edid(struct hdmitx_dev *hdev);
static void hdmitx_set_drm_pkt(struct master_display_info_s *data);
static void hdmitx_set_vsif_pkt(enum eotf_type type, enum mode_type
tunnel_mode, struct dv_vsif_para *data, bool signal_sdr);
@@ -169,13 +166,9 @@ static const struct of_device_id meson_amhdmitx_of_match[] = {
#define meson_amhdmitx_dt_match NULL
#endif
/*global getedid mutex*/
DEFINE_MUTEX(getedid_mutex);
static struct hdmitx_dev *tx20_dev;
static const struct dv_info dv_dummy;
int hdmitx_log_level;
static bool hdmitx_edid_done;
/* for SONY-KD-55A8F TV, need to mute more frames
* when switch DV(LL)->HLG
@@ -264,9 +257,9 @@ static void hdmitx_early_suspend(struct early_suspend *h)
hdmitx_set_drm_pkt(NULL);
hdmitx_set_vsif_pkt(0, 0, NULL, true);
hdmitx_set_hdr10plus_pkt(0, NULL);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
edidinfo_detach_to_vinfo(hdev);
hdmitx_set_uevent(HDMITX_HDCPPWR_EVENT, HDMI_SUSPEND);
@@ -318,12 +311,12 @@ static void hdmitx_late_resume(struct early_suspend *h)
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_GLITCH_FILTER_RESET, 0);
if (hdev->tx_hw.chip_data->chip_type >= MESON_CPU_ID_G12A)
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_I2C_RESET, 0);
hdmitx_get_edid(hdev);
hdmitx_edid_done = true;
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
hdev->tx_comm.hdmitx_edid_done = true;
}
hdmitx_notify_hpd(hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
/* recover attr (especially for HDR case) */
if (info && drm_hdmitx_chk_mode_attr_sup(info->name,
@@ -477,29 +470,29 @@ static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = &hdev->tx_comm.hdmitx_vinfo;
mutex_lock(&getedid_mutex);
mutex_lock(&hdev->tx_comm.getedid_mutex);
hdrinfo_to_vinfo(&info->hdr_info, hdev);
if (hdev->tx_comm.fmt_para.cd == COLORDEPTH_24B)
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(hdev);
memcpy(info->hdmichecksum, hdev->tx_comm.rxcap.chksum, 10);
mutex_unlock(&getedid_mutex);
memcpy(info->hdmichecksum, hdev->tx_comm.rxcap.hdmichecksum, 10);
mutex_unlock(&hdev->tx_comm.getedid_mutex);
}
static void edidinfo_detach_to_vinfo(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = &hdev->tx_comm.hdmitx_vinfo;
mutex_lock(&getedid_mutex);
mutex_lock(&hdev->tx_comm.getedid_mutex);
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;
mutex_unlock(&getedid_mutex);
mutex_unlock(&hdev->tx_comm.getedid_mutex);
}
/*disp_mode attr*/
@@ -881,7 +874,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
struct hdmitx_hw_common *tx_hw_base = &hdev->tx_hw.base;
hdmi_debug();
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (data)
memcpy(&drm_config_data, data,
sizeof(struct master_display_info_s));
@@ -962,7 +955,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
hdmitx_hw_set_packet(tx_hw_base, HDMI_PACKET_DRM, NULL, NULL);
hdmitx_hw_cntl_config(tx_hw_base,
CONF_AVI_BT2020, hdev->colormetry);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1003,7 +996,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
__func__, hdev->tx_comm.fmt_para.cs,
hdev->tx_comm.fmt_para.cd);
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1054,7 +1047,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
hdmitx_hw_cntl_config(tx_hw_base,
CONF_AVI_BT2020, SET_AVI_BT2020);
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1146,7 +1139,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
pr_info("%s: switch to 422,12bit\n", __func__);
}
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct vinfo_s *tx_vinfo)
@@ -1233,9 +1226,9 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
unsigned long flags = 0;
hdmi_debug();
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (hdev->bist_lock) {
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (!data)
@@ -1260,7 +1253,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
if (hdev->ready == 0) {
ltype = EOTF_T_NULL;
ltmode = -1;
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (hdev->tx_comm.rxcap.dv_info.ieeeoui != DV_IEEE_OUI) {
@@ -1270,7 +1263,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
if (hdev->tx_hw.chip_data->chip_type < MESON_CPU_ID_GXL) {
pr_info("hdmitx: not support DolbyVision\n");
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1341,7 +1334,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
if (type == EOTF_T_DV_AHEAD) {
hdmitx_hw_set_packet(tx_hw_base, HDMI_PACKET_VEND, VEN_DB1, VEN_HB);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (type == EOTF_T_DOLBYVISION) {
@@ -1447,7 +1440,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
if (type == EOTF_T_DV_AHEAD) {
hdmitx_hw_set_packet(tx_hw_base, HDMI_PACKET_VEND, VEN_DB2, VEN_HB);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
/*Dolby Vision standard case*/
@@ -1529,7 +1522,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
}
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
struct hdr10plus_para hdr10p_config_data;
@@ -1632,14 +1625,14 @@ static void hdmitx_set_cuva_hdr_vsif(struct cuva_hdr_vsif_para *data)
const struct cuva_info *cuva = &hdev->tx_comm.rxcap.hdr_info.cuva_info;
struct hdmitx_hw_common *tx_hw_base = &hdev->tx_hw.base;
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (cuva->ieeeoui != CUVA_IEEEOUI) {
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (!data) {
hdmitx_hw_set_packet(tx_hw_base, HDMI_PACKET_VEND, NULL, NULL);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
ven_db[0] = GET_OUI_BYTE0(CUVA_IEEEOUI);
@@ -1648,7 +1641,7 @@ static void hdmitx_set_cuva_hdr_vsif(struct cuva_hdr_vsif_para *data)
ven_db[3] = data->system_start_code;
ven_db[4] = (data->version_code & 0xf) << 4;
hdmitx_hw_set_packet(tx_hw_base, HDMI_PACKET_VEND, ven_db, ven_hb);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
struct hdmi_packet_t {
@@ -1667,10 +1660,10 @@ static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data)
unsigned long phys_ptr;
memset(vs_emds, 0, sizeof(vs_emds));
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (!data) {
hdmitx_hw_cntl_config(&hdev->tx_hw.base, CONF_EMP_NUMBER, 0);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1771,7 +1764,7 @@ static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data)
hdmitx_hw_cntl_config(&hdev->tx_hw.base, CONF_EMP_NUMBER,
sizeof(vs_emds) / (sizeof(struct hdmi_packet_t)));
hdmitx_hw_cntl_config(&hdev->tx_hw.base, CONF_EMP_PHY_ADDR, phys_ptr);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
#define EMP_FIRST 0x80
@@ -3988,70 +3981,6 @@ static int hdmitx_notify_callback_a(struct notifier_block *block,
#endif
static void hdmitx_get_edid(struct hdmitx_dev *hdev)
{
unsigned long flags = 0;
struct hdmitx_common *tx_comm = &hdev->tx_comm;
mutex_lock(&getedid_mutex);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_RESET_EDID, 0);
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_PIN_MUX_OP, PIN_MUX);
/* start reading edid first time */
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(hdev->tx_comm.EDID_buf)) {
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_EDID_READ_DATA, 0);
}
/* If EDID is not correct at first time, then retry */
if (!check_dvi_hdmi_edid_valid(hdev->tx_comm.EDID_buf)) {
struct timespec64 kts;
struct rtc_time tm;
msleep(20);
ktime_get_real_ts64(&kts);
rtc_time64_to_tm(kts.tv_sec, &tm);
if (hdev->hdmitx_gpios_scl != -EPROBE_DEFER)
pr_info("UTC+0 %ptRd %ptRt DDC SCL %s\n", &tm, &tm,
gpio_get_value(hdev->hdmitx_gpios_scl) ? "HIGH" : "LOW");
if (hdev->hdmitx_gpios_sda != -EPROBE_DEFER)
pr_info("UTC+0 %ptRd %ptRt DDC SDA %s\n", &tm, &tm,
gpio_get_value(hdev->hdmitx_gpios_sda) ? "HIGH" : "LOW");
msleep(80);
/* start reading edid second time */
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(hdev->tx_comm.EDID_buf)) {
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_EDID_READ_DATA, 0);
}
}
spin_lock_irqsave(&hdev->edid_spinlock, flags);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_parse(&hdev->tx_comm);
if (tx_comm->hdr_priority == 1) { /* clear dv_info */
struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
memset(dv, 0, sizeof(struct dv_info));
pr_info("clear dv_info\n");
}
if (tx_comm->hdr_priority == 2) { /* clear dv_info/hdr_info */
struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
struct hdr_info *hdr = &hdev->tx_comm.rxcap.hdr_info;
memset(dv, 0, sizeof(struct dv_info));
memset(hdr, 0, sizeof(struct hdr_info));
pr_info("clear dv_info/hdr_info\n");
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
hdmitx_event_mgr_notify(hdev->tx_comm.event_mgr,
HDMITX_PHY_ADDR_VALID, &hdev->tx_comm.rxcap.physical_addr);
hdmitx_edid_print(&hdev->tx_comm);
mutex_unlock(&getedid_mutex);
}
static void hdmitx_rxsense_process(struct work_struct *work)
{
int sense;
@@ -4087,9 +4016,8 @@ bool is_tv_changed(void)
struct hdmitx_dev *hdev = get_hdmitx_device();
struct hdmitx_common *tx_comm = &hdev->tx_comm;
if (memcmp(tx_comm->hdmichecksum, hdev->tx_comm.rxcap.chksum, 10) &&
memcmp(emptychecksum, hdev->tx_comm.rxcap.chksum, 10) &&
memcmp(invalidchecksum, tx_comm->hdmichecksum, 10)) {
if (memcmp(emptychecksum, tx_comm->rxcap.hdmichecksum, 10) &&
memcmp(invalidchecksum, tx_comm->rxcap.hdmichecksum, 10)) {
ret = true;
pr_info("hdmi crc is diff between uboot and kernel\n");
}
@@ -4152,11 +4080,11 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
* EDID, now EDID already read done and hdcp already started,
* not read EDID again.
*/
if (!hdmitx_edid_done) {
if (!hdev->tx_comm.hdmitx_edid_done) {
if (hdev->tx_hw.chip_data->chip_type >= MESON_CPU_ID_G12A)
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_I2C_RESET, 0);
hdmitx_get_edid(hdev);
hdmitx_edid_done = true;
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
hdev->tx_comm.hdmitx_edid_done = true;
}
/* start reading E-EDID */
hdev->cedst_policy = hdev->cedst_en & hdev->tx_comm.rxcap.scdc_present;
@@ -4166,10 +4094,10 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
else
hdmitx_hw_cntl_config(&hdev->tx_hw.base,
CONF_HDMI_DVI_MODE, HDMI_MODE);
mutex_lock(&getedid_mutex);
mutex_lock(&hdev->tx_comm.getedid_mutex);
if (hdev->tx_hw.chip_data->chip_type < MESON_CPU_ID_G12A)
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_I2C_REACTIVE, 0);
mutex_unlock(&getedid_mutex);
mutex_unlock(&hdev->tx_comm.getedid_mutex);
if (hdev->tx_comm.repeater_mode) {
rx_set_repeater_support(1);
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_HDCP_GET_BKSV,
@@ -4205,8 +4133,8 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
}
hdev->tx_comm.hpd_state = 1;
hdmitx_notify_hpd(hdev->tx_comm.hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
/* audio uevent is used for android to
* register hdmi audio device, it should
* sync with hdmi hpd state.
@@ -4266,9 +4194,9 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
edidinfo_detach_to_vinfo(hdev);
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT;
rx_edid_physical_addr(0, 0, 0, 0);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
hdev->tx_comm.hpd_state = 0;
hdmitx_notify_hpd(hdev->tx_comm.hpd_state, NULL);
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_AVMUTE_OP, SET_AVMUTE);
@@ -4292,9 +4220,9 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
/*edid info clear*/
rx_edid_physical_addr(0, 0, 0, 0);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
edidinfo_detach_to_vinfo(hdev);
/*update hpd state*/
@@ -4432,8 +4360,8 @@ int hdmitx20_event_notifier_regist(struct notifier_block *nb)
/* update status when register */
if (!ret && nb->notifier_call) {
hdmitx_notify_hpd(hdev->tx_comm.hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
if (hdev->tx_comm.rxcap.physical_addr != 0xffff)
hdmitx_event_mgr_notify(hdev->tx_comm.event_mgr,
HDMITX_PHY_ADDR_VALID, &hdev->tx_comm.rxcap.physical_addr);
@@ -4587,17 +4515,17 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev, struct hdmitx_dev
hdev->pinctrl_default);
}
hdev->hdmitx_gpios_hpd = of_get_named_gpio_flags(pdev->dev.of_node,
hdev->tx_comm.hdmitx_gpios_hpd = of_get_named_gpio_flags(pdev->dev.of_node,
"hdmitx-gpios-hpd", 0, NULL);
if (hdev->hdmitx_gpios_hpd == -EPROBE_DEFER)
if (hdev->tx_comm.hdmitx_gpios_hpd == -EPROBE_DEFER)
pr_err("get hdmitx-gpios-hpd error\n");
hdev->hdmitx_gpios_scl = of_get_named_gpio_flags(pdev->dev.of_node,
hdev->tx_comm.hdmitx_gpios_scl = of_get_named_gpio_flags(pdev->dev.of_node,
"hdmitx-gpios-scl", 0, NULL);
if (hdev->hdmitx_gpios_scl == -EPROBE_DEFER)
if (hdev->tx_comm.hdmitx_gpios_scl == -EPROBE_DEFER)
pr_err("get hdmitx-gpios-scl error\n");
hdev->hdmitx_gpios_sda = of_get_named_gpio_flags(pdev->dev.of_node,
hdev->tx_comm.hdmitx_gpios_sda = of_get_named_gpio_flags(pdev->dev.of_node,
"hdmitx-gpios-sda", 0, NULL);
if (hdev->hdmitx_gpios_sda == -EPROBE_DEFER)
if (hdev->tx_comm.hdmitx_gpios_sda == -EPROBE_DEFER)
pr_err("get hdmitx-gpios-sda error\n");
#ifdef CONFIG_OF
@@ -4947,8 +4875,8 @@ static int amhdmitx_probe(struct platform_device *pdev)
hdev->tx_comm.fmt_attr, sizeof(hdev->tx_comm.fmt_attr));
/* When init hdmi, clear the hdmitx module edid ram and edid buffer. */
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdmitx_hdr_state_init(hdev);
#ifdef CONFIG_AMLOGIC_VOUT_SERVE
@@ -4969,7 +4897,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
hdmitx20_audio_mute_op(1); /* default audio clock is ON */
aout_register_client(&hdmitx_notifier_nb_a);
#endif
spin_lock_init(&hdev->edid_spinlock);
spin_lock_init(&hdev->tx_comm.edid_spinlock);
hdev->tx_comm.hpd_state = !!hdmitx_hw_cntl_misc(&hdev->tx_hw.base,
MISC_HPD_GPI_ST, 0);
@@ -5002,7 +4930,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
if (hdev->tx_comm.hpd_state) {
/* need to get edid before vout probe */
hdev->tx_comm.already_used = 1;
hdmitx_get_edid(hdev);
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
edidinfo_attach_to_vinfo(hdev);
/* When bootup mbox and TV simultaneously,
@@ -719,14 +719,14 @@ static irqreturn_t intr_handler(int irq, void *dev)
pr_info(SYS "irq %x %x\n", dat_top, dat_dwc);
/* bit[2:1] of dat_top means HPD falling and rising */
if ((dat_top & 0x6) && hdev->hdmitx_gpios_hpd != -EPROBE_DEFER) {
if ((dat_top & 0x6) && hdev->tx_comm.hdmitx_gpios_hpd != -EPROBE_DEFER) {
struct timespec64 kts;
struct rtc_time tm;
ktime_get_real_ts64(&kts);
rtc_time64_to_tm(kts.tv_sec, &tm);
pr_info("UTC+0 %ptRd %ptRt HPD %s\n", &tm, &tm,
gpio_get_value(hdev->hdmitx_gpios_hpd) ? "HIGH" : "LOW");
gpio_get_value(hdev->tx_comm.hdmitx_gpios_hpd) ? "HIGH" : "LOW");
}
if (hdev->tx_hw.debug_hpd_lock == 1) {
@@ -617,9 +617,9 @@ unsigned int meson_hdcp_get_rx_cap(void)
return 0x1;
/* Detect RX support HDCP22 */
mutex_lock(&getedid_mutex);
mutex_lock(&hdev->tx_comm.getedid_mutex);
ver = hdcp_rd_hdcp22_ver();
mutex_unlock(&getedid_mutex);
mutex_unlock(&hdev->tx_comm.getedid_mutex);
/* Here, must assume RX support HDCP14, otherwise affect 1A-03 */
if (ver)
return 0x3;
+44 -101
View File
@@ -77,7 +77,6 @@ unsigned int rx_hdcp2_ver;
#define to_hdmitx21_dev(x) container_of(x, struct hdmitx_dev, tx_comm)
static struct class *hdmitx_class;
static void hdmitx_get_edid(struct hdmitx_dev *hdev);
static void hdmitx_set_drm_pkt(struct master_display_info_s *data);
static void hdmitx_set_vsif_pkt(enum eotf_type type, enum mode_type
tunnel_mode, struct dv_vsif_para *data, bool signal_sdr);
@@ -151,8 +150,6 @@ static const struct of_device_id meson_amhdmitx_of_match[] = {
#define meson_amhdmitx_dt_match NULL
#endif
static DEFINE_MUTEX(getedid_mutex);
static struct hdmitx_dev *tx21_dev;
struct hdmitx_dev *get_hdmitx21_device(void)
@@ -180,7 +177,6 @@ struct vsdb_phyaddr *get_hdmitx21_phy_addr(void)
static const struct dv_info dv_dummy;
static struct dv_info ext_dvinfo;
static int log21_level;
static bool hdmitx_edid_done;
static struct vout_device_s hdmitx_vdev = {
.dv_info = &dv_dummy,
@@ -197,10 +193,6 @@ static struct vout_device_s hdmitx_vdev = {
/* indicate plugout before systemcontrol boot */
static bool plugout_mute_flg;
static char hdmichecksum[11] = {
'i', 'n', 'v', 'a', 'l', 'i', 'd', 'c', 'r', 'c', '\0'
};
static char invalidchecksum[11] = {
'i', 'n', 'v', 'a', 'l', 'i', 'd', 'c', 'r', 'c', '\0'
};
@@ -297,9 +289,9 @@ static void hdmitx_early_suspend(struct early_suspend *h)
hdev->tx_comm.cur_VIC = HDMI_0_UNKNOWN;
hdmitx_set_vsif_pkt(0, 0, NULL, true);
hdmitx_set_hdr10plus_pkt(0, NULL);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
edidinfo_detach_to_vinfo(hdev);
/* clear audio/video mute flag of stream type */
hdmitx21_video_mute_op(1, VIDEO_MUTE_PATH_2);
@@ -336,13 +328,13 @@ static void hdmitx_late_resume(struct early_suspend *h)
/* add i2c soft reset before read EDID */
hdmitx_hw_cntl_ddc(&hdev->tx_hw.base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_I2C_RESET, 0);
hdmitx_get_edid(hdev);
hdmitx_edid_done = true;
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
hdev->tx_comm.hdmitx_edid_done = true;
}
if (hdev->tv_usage == 0)
hdmitx_notify_hpd(hdev->tx_comm.hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
hdmitx_hw_cntl_config(&hdev->tx_hw.base, CONF_AUDIO_MUTE_OP, AUDIO_MUTE);
/* set_disp_mode_auto(); */
@@ -498,7 +490,7 @@ static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev)
struct vinfo_s *info = &hdev->tx_comm.hdmitx_vinfo;
struct hdmi_format_para *para = &hdev->tx_comm.fmt_para;
mutex_lock(&getedid_mutex);
mutex_lock(&hdev->tx_comm.getedid_mutex);
hdrinfo_to_vinfo(&info->hdr_info, hdev);
memcpy(&ext_dvinfo, &hdev->tx_comm.rxcap.dv_info, sizeof(ext_dvinfo));
if (para->cd == COLORDEPTH_24B)
@@ -506,7 +498,7 @@ static void edidinfo_attach_to_vinfo(struct hdmitx_dev *hdev)
rxlatency_to_vinfo(info, &hdev->tx_comm.rxcap);
hdmitx_vdev.dv_info = &hdev->tx_comm.rxcap.dv_info;
hdmi_physical_size_to_vinfo(hdev);
mutex_unlock(&getedid_mutex);
mutex_unlock(&hdev->tx_comm.getedid_mutex);
}
static void edidinfo_detach_to_vinfo(struct hdmitx_dev *hdev)
@@ -845,7 +837,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
if (!_check_hdmi_mode())
return;
hdmi_debug();
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (hdr_status_pos == 4) {
/* zero hdr10+ VSIF being sent - disable it */
pr_info("%s: disable hdr10+ zero vsif\n", __func__);
@@ -898,7 +890,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
drm_db[0] = 0;
hdmi_drm_infoframe_set(NULL);
hdmi_avi_infoframe_config(CONF_AVI_BT2020, hdev->colormetry);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -914,7 +906,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
schedule_work(&hdev->work_hdr);
drm_db[0] = 0;
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -959,7 +951,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
hdmi_drm_infoframe_rawset(drm_hb, db);
hdmi_avi_infoframe_config(CONF_AVI_BT2020, SET_AVI_BT2020);
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1017,7 +1009,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
hdev->hdmi_last_hdr_mode = hdev->hdmi_current_hdr_mode;
schedule_work(&hdev->work_hdr);
}
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
static int calc_vinfo_from_hdmi_timing(const struct hdmi_timing *timing, struct vinfo_s *tx_vinfo)
@@ -1103,9 +1095,9 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
if (!_check_hdmi_mode())
return;
hdmi_debug();
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (hdev->bist_lock) {
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1122,7 +1114,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
if (hdev->ready == 0) {
ltype = EOTF_T_NULL;
ltmode = -1;
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (hdev->tx_comm.rxcap.dv_info.ieeeoui != DV_IEEE_OUI) {
@@ -1192,7 +1184,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
if (type == EOTF_T_DV_AHEAD) {
hdmi_vend_infoframe_rawset(ven_hb, db1);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
if (type == EOTF_T_DOLBYVISION) {
@@ -1297,7 +1289,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
if (type == EOTF_T_DV_AHEAD) {
hdmi_vend_infoframe_rawset(ven_hb, db2);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
/*Dolby Vision standard case*/
@@ -1377,7 +1369,7 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
}
}
hdmitx21_dither_config(hdev);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
static void hdmitx_set_hdr10plus_pkt(u32 flag,
@@ -1463,10 +1455,10 @@ static void hdmitx_set_cuva_hdr_vsif(struct cuva_hdr_vsif_para *data)
if (!_check_hdmi_mode())
return;
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (!data) {
hdmi_vend_infoframe_rawset(NULL, NULL);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
ven_db[0] = GET_OUI_BYTE0(CUVA_IEEEOUI);
@@ -1475,7 +1467,7 @@ static void hdmitx_set_cuva_hdr_vsif(struct cuva_hdr_vsif_para *data)
ven_db[3] = data->system_start_code;
ven_db[4] = (data->version_code & 0xf) << 4;
hdmi_vend_infoframe_rawset(ven_hb, db);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data)
@@ -1488,10 +1480,10 @@ static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data)
if (!_check_hdmi_mode())
return;
memset(vs_emds, 0, sizeof(vs_emds));
spin_lock_irqsave(&hdev->edid_spinlock, flags);
spin_lock_irqsave(&hdev->tx_comm.edid_spinlock, flags);
if (!data) {
hdmitx_dhdr_send(NULL, 0);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
return;
}
@@ -1582,7 +1574,7 @@ static void hdmitx_set_cuva_hdr_vs_emds(struct cuva_hdr_vs_emds_para *data)
vs_emds[2].pb[6] = data->max_display_mastering_lum & 0xff;
hdmitx_dhdr_send((u8 *)&vs_emds, max_size);
spin_unlock_irqrestore(&hdev->edid_spinlock, flags);
spin_unlock_irqrestore(&hdev->tx_comm.edid_spinlock, flags);
}
/* reserved, left blank here, move to hdmi_tx_vrr.c file */
@@ -3797,53 +3789,6 @@ static int hdmitx_notify_callback_a(struct notifier_block *block,
}
#endif
static void hdmitx_get_edid(struct hdmitx_dev *hdev)
{
struct hdmitx_common *tx_comm = &hdev->tx_comm;
struct hdmitx_hw_common *tx_hw_base = &hdev->tx_hw.base;
mutex_lock(&getedid_mutex);
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_RESET_EDID, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_PIN_MUX_OP, PIN_MUX);
/* start reading edid first time */
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(tx_comm->EDID_buf)) {
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
}
/* If EDID is not correct at first time, then retry */
if (!check_dvi_hdmi_edid_valid(hdev->tx_comm.EDID_buf)) {
msleep(100);
/* start reading edid second time */
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(hdev->tx_comm.EDID_buf)) {
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
}
}
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_parse(&hdev->tx_comm);
if (tx_comm->hdr_priority == 1) { /* clear dv_info */
struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
memset(dv, 0, sizeof(struct dv_info));
pr_info("clear dv_info\n");
}
if (tx_comm->hdr_priority == 2) { /* clear dv_info/hdr_info */
struct dv_info *dv = &hdev->tx_comm.rxcap.dv_info;
struct hdr_info *hdr = &hdev->tx_comm.rxcap.hdr_info;
memset(dv, 0, sizeof(struct dv_info));
memset(hdr, 0, sizeof(struct hdr_info));
pr_info("clear dv_info/hdr_info\n");
}
hdmitx_edid_print(&hdev->tx_comm);
mutex_unlock(&getedid_mutex);
}
static void hdmitx_rxsense_process(struct work_struct *work)
{
int sense;
@@ -3874,9 +3819,8 @@ static bool is_tv_changed(void)
bool ret = false;
struct hdmitx_dev *hdev = get_hdmitx21_device();
if (memcmp(hdmichecksum, hdev->tx_comm.rxcap.chksum, 10) &&
memcmp(emptychecksum, hdev->tx_comm.rxcap.chksum, 10) &&
memcmp(invalidchecksum, hdmichecksum, 10)) {
if (memcmp(emptychecksum, hdev->tx_comm.rxcap.hdmichecksum, 10) &&
memcmp(invalidchecksum, hdev->tx_comm.rxcap.hdmichecksum, 10)) {
ret = true;
pr_info("hdmi crc is diff between uboot and kernel\n");
}
@@ -3908,10 +3852,10 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
* EDID, now EDID already read done and hdcp already started,
* not read EDID again.
*/
if (!hdmitx_edid_done) {
if (!hdev->tx_comm.rxcap.edid_parsing) {
hdmitx_hw_cntl_misc(&hdev->tx_hw.base, MISC_I2C_RESET, 0);
hdmitx_get_edid(hdev);
hdmitx_edid_done = true;
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
hdev->tx_comm.hdmitx_edid_done = true;
}
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN;
/* start reading E-EDID */
@@ -3955,8 +3899,8 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
hdev->tx_comm.hpd_state = 1;
if (hdev->tv_usage == 0)
hdmitx_notify_hpd(hdev->tx_comm.hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
/* Should be started at end of output */
cancel_delayed_work(&hdev->work_cedst);
if (hdev->cedst_policy)
@@ -3999,9 +3943,9 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
plugout_mute_flg = true;
/* edidinfo_detach_to_vinfo(hdev); */
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT;
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
hdev->tx_comm.hpd_state = 0;
if (hdev->tv_usage == 0) {
rx_edid_physical_addr(0, 0, 0, 0);
@@ -4035,9 +3979,9 @@ 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;
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_done = false;
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->tx_comm.hdmitx_edid_done = false;
hdev->tx_comm.hpd_state = 0;
hdev->ll_enabled_in_auto_mode = false;
if (hdev->tv_usage == 0) {
@@ -4135,8 +4079,8 @@ int hdmitx21_event_notifier_regist(struct notifier_block *nb)
if (!ret && nb->notifier_call) {
if (hdev->tv_usage == 0)
hdmitx_notify_hpd(hdev->tx_comm.hpd_state,
hdev->tx_comm.edid_parsing ?
hdev->tx_comm.edid_ptr : NULL);
hdev->tx_comm.rxcap.edid_parsing ?
hdev->tx_comm.EDID_buf : NULL);
if (hdev->tx_comm.rxcap.physical_addr != 0xffff) {
if (hdev->tv_usage == 0)
hdmitx_event_mgr_notify(hdev->tx_comm.event_mgr,
@@ -4681,7 +4625,6 @@ static int amhdmitx_probe(struct platform_device *pdev)
hdmitx_format_para_rebuild_fmtattr_str(&hdev->tx_comm.fmt_para,
hdev->tx_comm.fmt_attr, sizeof(hdev->tx_comm.fmt_attr));
mutex_init(&hdev->tx_comm.hdmimode_mutex);
tx_comm->hpd_state = !!(hdmitx_hw_cntl_misc(&hdev->tx_hw.base,
MISC_HPD_GPI_ST, 0));
#ifdef CONFIG_AMLOGIC_VOUT_SERVE
@@ -4712,8 +4655,8 @@ static int amhdmitx_probe(struct platform_device *pdev)
INIT_WORK(&hdev->work_hdr, hdr_work_func);
/* When init hdmi, clear the hdmitx module edid ram and edid buffer. */
hdmitx_edid_buffer_clear(&hdev->tx_comm);
hdmitx_edid_rxcap_clear(&hdev->tx_comm);
hdmitx_edid_buffer_clear(hdev->tx_comm.EDID_buf, sizeof(hdev->tx_comm.EDID_buf));
hdmitx_edid_rxcap_clear(&hdev->tx_comm.rxcap);
hdev->hdmi_wq = alloc_workqueue(DEVICE_NAME,
WQ_HIGHPRI | WQ_CPU_INTENSIVE, 0);
INIT_DELAYED_WORK(&hdev->work_hpd_plugin, hdmitx_hpd_plugin_handler);
@@ -4738,7 +4681,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
if (tx_comm->hpd_state) {
/* need to get edid before vout probe */
hdev->tx_comm.already_used = 1;
hdmitx_get_edid(hdev);
hdmitx_get_edid(&hdev->tx_comm, &hdev->tx_hw.base);
/* When bootup mbox and TV simultaneously,
* TV may not handle SCDC/DIV40
@@ -6,6 +6,10 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <linux/rtc.h>
#include <linux/timekeeping.h>
#include <linux/amlogic/media/vout/hdmi_tx_ext.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h>
#include <hdmitx_boot_parameters.h>
@@ -42,14 +46,14 @@ int hdmitx_common_init(struct hdmitx_common *tx_comm, struct hdmitx_hw_common *h
/*load tx boot params*/
tx_comm->hdr_priority = boot_param->hdr_mask;
memcpy(tx_comm->hdmichecksum, boot_param->edid_chksum, sizeof(tx_comm->hdmichecksum));
memcpy(tx_comm->rxcap.hdmichecksum, boot_param->edid_chksum,
sizeof(tx_comm->rxcap.hdmichecksum));
memcpy(tx_comm->fmt_attr, boot_param->color_attr, sizeof(tx_comm->fmt_attr));
tx_comm->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->edid_ptr = tx_comm->EDID_buf;
tx_comm->tx_hw = hw_comm;
tx_comm->repeater_mode = 0;
@@ -62,6 +66,7 @@ int hdmitx_common_init(struct hdmitx_common *tx_comm, struct hdmitx_hw_common *h
/*mutex init*/
mutex_init(&tx_comm->setclk_mutex);
mutex_init(&tx_comm->hdmimode_mutex);
mutex_init(&tx_comm->getedid_mutex);
return 0;
}
@@ -102,21 +107,6 @@ int hdmitx_common_destroy(struct hdmitx_common *tx_comm)
return 0;
}
bool hdmitx_validate_y420_vic(enum hdmi_vic vic)
{
const struct hdmi_timing *timing;
/* 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;
}
int hdmitx_common_validate_vic(struct hdmitx_common *tx_comm, u32 vic)
{
const struct hdmi_timing *timing = hdmitx_mode_vic_to_hdmi_timing(vic);
@@ -246,10 +236,7 @@ int hdmitx_register_hpd_cb(struct hdmitx_common *tx_comm, struct connector_hpd_c
unsigned char *hdmitx_get_raw_edid(struct hdmitx_common *tx_comm)
{
if (tx_comm->edid_ptr)
return tx_comm->edid_ptr;
else
return tx_comm->EDID_buf;
return tx_comm->EDID_buf;
}
int hdmitx_setup_attr(struct hdmitx_common *tx_comm, const char *buf)
@@ -280,47 +267,6 @@ int hdmitx_get_hdrinfo(struct hdmitx_common *tx_comm, struct hdr_info *hdrinfo)
return 0;
}
static unsigned char __nosavedata edid_checkvalue[4] = {0};
static int xtochar(u8 value, u8 *checksum)
{
if (((value >> 4) & 0xf) <= 9)
checksum[0] = ((value >> 4) & 0xf) + '0';
else
checksum[0] = ((value >> 4) & 0xf) - 10 + 'a';
if ((value & 0xf) <= 9)
checksum[1] = (value & 0xf) + '0';
else
checksum[1] = (value & 0xf) - 10 + 'a';
return 0;
}
int hdmitx_update_edid_chksum(u8 *buf, u32 block_cnt, struct rx_cap *rxcap)
{
u32 i, length, max;
if (!buf)
return -EINVAL;
length = sizeof(edid_checkvalue);
memset(edid_checkvalue, 0x00, length);
max = (block_cnt > length) ? length : block_cnt;
for (i = 0; i < max; i++)
edid_checkvalue[i] = *(buf + (i + 1) * 128 - 1);
rxcap->chksum[0] = '0';
rxcap->chksum[1] = 'x';
for (i = 0; i < 4; i++)
xtochar(edid_checkvalue[i], &rxcap->chksum[2 * i + 2]);
return 0;
}
static enum hdmi_vic get_alternate_ar_vic(enum hdmi_vic vic)
{
int i = 0;
@@ -464,10 +410,10 @@ int hdmitx_common_notify_hpd_status(struct hdmitx_common *tx_comm)
HDMITX_AUDIO_EVENT, tx_comm->hpd_state);
}
/*notify to other driver module:cec/rx TODO: need lock for edid_ptr */
/*notify to other driver module:cec/rx TODO: need lock for EDID_buf */
/*if (tx_comm->hpd_state)
* hdmitx_event_mgr_notify(tx_comm->event_mgr, HDMITX_PLUG,
* tx_comm->edid_parsing ? tx_comm->edid_ptr : NULL);
* tx_comm->edid_parsing ? tx_comm->EDID_buf : NULL);
*else
* hdmitx_event_mgr_notify(tx_comm->event_mgr, HDMITX_UNPLUG, NULL);
*/
@@ -765,12 +711,70 @@ int hdmitx_print_sink_cap(struct hdmitx_common *tx_comm,
* whether edid is changed
*/
pos += snprintf(buffer + pos, buffer_len - pos,
"checkvalue: 0x%02x%02x%02x%02x\n",
edid_checkvalue[0],
edid_checkvalue[1],
edid_checkvalue[2],
edid_checkvalue[3]);
"checkvalue: %s\n", prxcap->hdmichecksum);
return pos;
}
void hdmitx_get_edid(struct hdmitx_common *tx_comm, struct hdmitx_hw_common *tx_hw_base)
{
unsigned long flags = 0;
mutex_lock(&tx_comm->getedid_mutex);
hdmitx_edid_buffer_clear(tx_comm->EDID_buf, sizeof(tx_comm->EDID_buf));
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_RESET_EDID, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_PIN_MUX_OP, PIN_MUX);
/* start reading edid first time */
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(tx_comm->EDID_buf)) {
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
}
/* If EDID is not correct at first time, then retry */
if (!check_dvi_hdmi_edid_valid(tx_comm->EDID_buf)) {
struct timespec64 kts;
struct rtc_time tm;
msleep(20);
ktime_get_real_ts64(&kts);
rtc_time64_to_tm(kts.tv_sec, &tm);
if (tx_comm->hdmitx_gpios_scl != -EPROBE_DEFER)
pr_info("UTC+0 %ptRd %ptRt DDC SCL %s\n", &tm, &tm,
gpio_get_value(tx_comm->hdmitx_gpios_scl) ? "HIGH" : "LOW");
if (tx_comm->hdmitx_gpios_sda != -EPROBE_DEFER)
pr_info("UTC+0 %ptRd %ptRt DDC SDA %s\n", &tm, &tm,
gpio_get_value(tx_comm->hdmitx_gpios_sda) ? "HIGH" : "LOW");
msleep(80);
/* start reading edid second time */
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
if (hdmitx_edid_is_all_zeros(tx_comm->EDID_buf)) {
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_GLITCH_FILTER_RESET, 0);
hdmitx_hw_cntl_ddc(tx_hw_base, DDC_EDID_READ_DATA, 0);
}
}
spin_lock_irqsave(&tx_comm->edid_spinlock, flags);
hdmitx_edid_rxcap_clear(&tx_comm->rxcap);
hdmitx_edid_parse(&tx_comm->rxcap, tx_comm->EDID_buf);
if (tx_comm->hdr_priority == 1) { /* clear dv_info */
struct dv_info *dv = &tx_comm->rxcap.dv_info;
memset(dv, 0, sizeof(struct dv_info));
pr_info("clear dv_info\n");
}
if (tx_comm->hdr_priority == 2) { /* clear dv_info/hdr_info */
struct dv_info *dv = &tx_comm->rxcap.dv_info;
struct hdr_info *hdr = &tx_comm->rxcap.hdr_info;
memset(dv, 0, sizeof(struct dv_info));
memset(hdr, 0, sizeof(struct hdr_info));
pr_info("clear dv_info/hdr_info\n");
}
spin_unlock_irqrestore(&tx_comm->edid_spinlock, flags);
hdmitx_event_mgr_notify(tx_comm->event_mgr,
HDMITX_PHY_ADDR_VALID, &tx_comm->rxcap.physical_addr);
hdmitx_edid_print(tx_comm->EDID_buf);
mutex_unlock(&tx_comm->getedid_mutex);
}
+95 -79
View File
@@ -20,14 +20,12 @@
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <crypto/hash.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/amlogic/media/vout/vinfo.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h>
#include <linux/amlogic/media/vout/hdmitx_common/hdmitx_edid.h>
#define CEA_DATA_BLOCK_COLLECTION_ADDR_1STP 0x04
@@ -84,7 +82,6 @@
(((val) >> (start)) & ((1 << (len)) - 1))
const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name);
static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf);
static void edid_dtd_parsing(struct rx_cap *prxcap, unsigned char *data);
static void hdmitx_edid_set_default_aud(struct rx_cap *prxcap);
/* Base Block, Vendor/Product Information, byte[8]~[18] */
@@ -2136,14 +2133,6 @@ static void hdmitx_edid_set_default_vic(struct rx_cap *prxcap)
pr_info(EDID "set default vic\n");
}
#define PRINT_HASH(hash)
static int edid_hash_calc(u8 *hash, const char *data,
u32 len)
{
return 1;
}
static int hdmitx_edid_search_IEEEOUI(char *buf)
{
int i;
@@ -2556,17 +2545,16 @@ static void check_dv_truly_support(struct rx_cap *prxcap, struct dv_info *dv)
}
}
int hdmitx_find_philips(struct hdmitx_common *tx_comm)
int hdmitx_find_philips(u8 *edid_buf)
{
int j;
int length = sizeof(vendor_id) / sizeof(struct edid_venddat_t);
if (!tx_comm)
if (!edid_buf)
return 0;
for (j = 0; j < length; j++) {
if (memcmp(&tx_comm->EDID_buf[8], &vendor_id[j],
sizeof(struct edid_venddat_t)) == 0)
if (memcmp(edid_buf, &vendor_id[j], sizeof(struct edid_venddat_t)) == 0)
return 1;
}
return 0;
@@ -2662,27 +2650,63 @@ static void _edid_parse_base_structure(struct rx_cap *prxcap, unsigned char *EDI
}
}
int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
static int xtochar(u8 value, u8 *checksum)
{
if (!checksum)
return 0;
if (((value >> 4) & 0xf) <= 9)
checksum[0] = ((value >> 4) & 0xf) + '0';
else
checksum[0] = ((value >> 4) & 0xf) - 10 + 'a';
if ((value & 0xf) <= 9)
checksum[1] = (value & 0xf) + '0';
else
checksum[1] = (value & 0xf) - 10 + 'a';
return 0;
}
static int update_edid_chksum(struct rx_cap *prxcap, u8 *edid_buf)
{
u32 i;
unsigned char tmp_chksum[4] = {0};
if (!prxcap || !edid_buf)
return -EINVAL;
memset(prxcap->hdmichecksum, 0, sizeof(prxcap->hdmichecksum));
/* get the first 4 sub-blocks chksum */
for (i = 0; i < 4; i++)
tmp_chksum[i] = edid_buf[i * 128 + 127];
prxcap->hdmichecksum[0] = '0';
prxcap->hdmichecksum[1] = 'x';
for (i = 0; i < 4; i++)
xtochar(tmp_chksum[i], &prxcap->hdmichecksum[2 * i + 2]);
return 0;
}
int hdmitx_edid_parse(struct rx_cap *prxcap, u8 *edid_buf)
{
unsigned char cta_block_count;
unsigned char *EDID_buf;
int i;
int idx[4];
struct rx_cap *prxcap;
struct dv_info *dv;
if (!tx_comm)
return 0;
if (!edid_buf || !prxcap)
return -1;
EDID_buf = tx_comm->EDID_buf;
prxcap = &tx_comm->rxcap;
dv = &tx_comm->rxcap.dv_info;
if (check_dvi_hdmi_edid_valid(tx_comm->EDID_buf))
tx_comm->edid_parsing = 1;
dv = &prxcap->dv_info;
if (check_dvi_hdmi_edid_valid(edid_buf))
prxcap->edid_parsing = 1;
else
tx_comm->edid_parsing = 0;
prxcap->edid_parsing = 0;
prxcap->head_err = hdmitx_edid_header_invalid(&EDID_buf[0]);
prxcap->head_err = hdmitx_edid_header_invalid(&edid_buf[0]);
// TODO
/*if (prxcap->head_err)
* hdmitx_current_status(HDMITX_EDID_HEAD_ERROR);
@@ -2691,31 +2715,27 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
* hdmitx_current_status(HDMITX_EDID_CHECKSUM_ERROR);
*/
tx_comm->edid_ptr = EDID_buf;
pr_debug(EDID "EDID Parser:\n");
/* Calculate the EDID hash for special use */
memset(tx_comm->EDID_hash, 0, ARRAY_SIZE(tx_comm->EDID_hash));
edid_hash_calc(tx_comm->EDID_hash, tx_comm->EDID_buf, 256);
if (!check_dvi_hdmi_edid_valid(EDID_buf)) {
if (!check_dvi_hdmi_edid_valid(edid_buf)) {
edid_set_fallback_mode(prxcap);
pr_info("set fallback mode\n");
return 0;
}
if (_check_base_structure(EDID_buf))
_edid_parse_base_structure(prxcap, EDID_buf);
if (_check_base_structure(edid_buf))
_edid_parse_base_structure(prxcap, edid_buf);
cta_block_count = EDID_buf[0x7E];
cta_block_count = edid_buf[0x7E];
/* HFR-EEODB */
if (cta_block_count && EDID_buf[128 + 4] == EXTENSION_EEODB_EXT_TAG &&
EDID_buf[128 + 5] == EXTENSION_EEODB_EXT_CODE)
cta_block_count = EDID_buf[128 + 6];
if (cta_block_count && edid_buf[128 + 4] == EXTENSION_EEODB_EXT_TAG &&
edid_buf[128 + 5] == EXTENSION_EEODB_EXT_CODE)
cta_block_count = edid_buf[128 + 6];
/* limit cta_block_count to EDID_MAX_BLOCK - 1 */
if (cta_block_count > EDID_MAX_BLOCK - 1)
cta_block_count = EDID_MAX_BLOCK - 1;
for (i = 1; i <= cta_block_count; i++) {
if (EDID_buf[i * 0x80] == 0x02)
hdmitx_edid_cta_block_parse(prxcap, &EDID_buf[i * 0x80]);
if (edid_buf[i * 0x80] == 0x02)
hdmitx_edid_cta_block_parse(prxcap, &edid_buf[i * 0x80]);
}
/* EDID parsing complete - check if 4k60/50 DV can be truly supported */
@@ -2723,13 +2743,13 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
check_dv_truly_support(prxcap, dv);
dv = &prxcap->dv_info2;
check_dv_truly_support(prxcap, dv);
edid_check_pcm_declare(&tx_comm->rxcap);
edid_check_pcm_declare(prxcap);
/* move parts that may contain cea timing parse behind
* VDB parse, so that to not affect VDB index which
* will be used in Y420CMDB map
*/
edid_standardtiming(&tx_comm->rxcap, &EDID_buf[0x26], 8);
edid_parseceatiming(&tx_comm->rxcap, &EDID_buf[0x36]);
edid_standardtiming(prxcap, &edid_buf[0x26], 8);
edid_parseceatiming(prxcap, &edid_buf[0x36]);
/*
* Because DTDs are not able to represent some Video Formats, which can be
* represented as SVDs and might be preferred by Sinks, the first DTD in the
@@ -2751,40 +2771,37 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
idx[2] = EDID_DETAILED_TIMING_DES_BLOCK2_POS;
idx[3] = EDID_DETAILED_TIMING_DES_BLOCK3_POS;
for (i = 0; i < 4; i++) {
if ((EDID_buf[idx[i]]) && (EDID_buf[idx[i] + 1])) {
if ((edid_buf[idx[i]]) && (edid_buf[idx[i] + 1])) {
struct vesa_standard_timing t;
memset(&t, 0, sizeof(struct vesa_standard_timing));
if (i == 0)
edid_descriptor_pmt(prxcap, &t,
&EDID_buf[idx[i]]);
edid_descriptor_pmt(prxcap, &t, &edid_buf[idx[i]]);
if (i == 1)
edid_descriptor_pmt2(prxcap, &t,
&EDID_buf[idx[i]]);
edid_descriptor_pmt2(prxcap, &t, &edid_buf[idx[i]]);
continue;
}
switch (EDID_buf[idx[i] + 3]) {
switch (edid_buf[idx[i] + 3]) {
case TAG_STANDARD_TIMINGS:
edid_standardtiming(prxcap, &EDID_buf[idx[i] + 5], 6);
edid_standardtiming(prxcap, &edid_buf[idx[i] + 5], 6);
break;
case TAG_CVT_TIMING_CODES:
edid_cvt_timing(prxcap, &EDID_buf[idx[i] + 6]);
edid_cvt_timing(prxcap, &edid_buf[idx[i] + 6]);
break;
case TAG_ESTABLISHED_TIMING_III:
edid_standard_timing_iii(prxcap, &EDID_buf[idx[i] + 6]);
edid_standard_timing_iii(prxcap, &edid_buf[idx[i] + 6]);
break;
case TAG_RANGE_LIMITS:
break;
case TAG_DISPLAY_PRODUCT_NAME_STRING:
edid_receiverproductnameparse(prxcap,
&EDID_buf[idx[i] + 5]);
edid_receiverproductnameparse(prxcap, &edid_buf[idx[i] + 5]);
break;
default:
break;
}
}
if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) {
if (hdmitx_edid_search_IEEEOUI(&edid_buf[128])) {
prxcap->ieeeoui = HDMI_IEEE_OUI;
pr_debug(EDID "find IEEEOUT\n");
} else {
@@ -2794,14 +2811,14 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
/* strictly DVI device judgement */
/* valid EDID & no audio tag & no IEEEOUI */
if (check_dvi_hdmi_edid_valid(&EDID_buf[0]) &&
!hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) {
if (check_dvi_hdmi_edid_valid(&edid_buf[0]) &&
!hdmitx_edid_search_IEEEOUI(&edid_buf[128])) {
prxcap->ieeeoui = 0x0;
pr_debug(EDID "sink is DVI device\n");
} else {
prxcap->ieeeoui = HDMI_IEEE_OUI;
}
if (edid_zero_data(EDID_buf))
if (edid_zero_data(edid_buf))
prxcap->ieeeoui = HDMI_IEEE_OUI;
if (!prxcap->AUD_count && !prxcap->ieeeoui)
@@ -2812,9 +2829,9 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
if (!prxcap->AUD_count)
hdmitx_edid_set_default_aud(prxcap);
hdmitx_update_edid_chksum(EDID_buf, cta_block_count + 1, prxcap);
update_edid_chksum(prxcap, edid_buf);
if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) {
if (!hdmitx_edid_valid_block_num(&edid_buf[0])) {
prxcap->ieeeoui = HDMI_IEEE_OUI;
pr_info(EDID "Invalid edid, consider RX as HDMI device\n");
}
@@ -2846,7 +2863,7 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
}
/* if edid are all zeroes, or no VIC, set default vic */
if (edid_zero_data(EDID_buf) || prxcap->VIC_count == 0)
if (edid_zero_data(edid_buf) || prxcap->VIC_count == 0)
hdmitx_edid_set_default_vic(prxcap);
if (prxcap->ieeeoui == HDMI_IEEE_OUI) {
// hdmitx_current_status(HDMITX_EDID_HDMI_DEVICE);
@@ -2857,24 +2874,22 @@ int hdmitx_edid_parse(struct hdmitx_common *tx_comm)
return 0;
}
void hdmitx_edid_buffer_clear(struct hdmitx_common *tx_comm)
void hdmitx_edid_buffer_clear(u8 *edid_buf, int size)
{
if (!tx_comm)
if (!edid_buf)
return;
memset(tx_comm->EDID_buf, 0, sizeof(tx_comm->EDID_buf));
memset(edid_buf, 0, size);
}
/* Clear the Parse result of HDMI Sink's EDID. */
void hdmitx_edid_rxcap_clear(struct hdmitx_common *tx_comm)
void hdmitx_edid_rxcap_clear(struct rx_cap *prxcap)
{
char tmp[2] = {0};
struct rx_cap *prxcap;
if (!tx_comm)
if (!prxcap)
return;
prxcap = &tx_comm->rxcap;
memset(prxcap, 0, sizeof(struct rx_cap));
/* Note: in most cases, we think that rx is tv and the default
@@ -2882,8 +2897,7 @@ void hdmitx_edid_rxcap_clear(struct hdmitx_common *tx_comm)
*/
prxcap->ieeeoui = HDMI_IEEE_OUI;
memset(&tx_comm->EDID_hash[0], 0, sizeof(tx_comm->EDID_hash));
tx_comm->edid_parsing = 0;
prxcap->edid_parsing = 0;
hdmitx_edid_set_default_aud(prxcap);
rx_set_hdr_lumi(&tmp[0], 2);
rx_set_receiver_edid(&tmp[0], 2);
@@ -2925,18 +2939,18 @@ static void hdmitx_edid_blk_print(unsigned char *blk, unsigned int blk_idx)
/*
* check EDID buf contains valid block numbers
*/
static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf)
unsigned int hdmitx_edid_valid_block_num(unsigned char *edid_buf)
{
unsigned int valid_blk_no = 0;
unsigned int i = 0, j = 0;
unsigned int tmp_chksum = 0;
if (!buf)
if (!edid_buf)
return 0;
for (j = 0; j < EDID_MAX_BLOCK; j++) {
for (i = 0; i < 128; i++)
tmp_chksum += buf[i + j * 128];
tmp_chksum += edid_buf[i + j * 128];
if (tmp_chksum != 0) {
valid_blk_no++;
if ((tmp_chksum & 0xff) == 0)
@@ -2946,30 +2960,32 @@ static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf)
}
tmp_chksum = 0;
}
/* EEODB case */
if (edid_buf[128 + 4] == EXTENSION_EEODB_EXT_TAG &&
edid_buf[128 + 5] == EXTENSION_EEODB_EXT_CODE)
valid_blk_no = edid_buf[128 + 6] + 1;
return valid_blk_no;
}
/*
* print out EDID_buf
*/
void hdmitx_edid_print(struct hdmitx_common *tx_comm)
void hdmitx_edid_print(u8 *edid_buf)
{
u8 *buf0 = tx_comm->EDID_buf;
u32 valid_blk_no = 0;
u32 blk_idx = 0;
if (!tx_comm)
if (!edid_buf)
return;
/* calculate valid edid block numbers */
valid_blk_no = hdmitx_edid_check_valid_blocks(buf0);
valid_blk_no = hdmitx_edid_valid_block_num(edid_buf);
if (valid_blk_no == 0) {
pr_debug(EDID "raw data are all zeroes\n");
} else {
for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++)
hdmitx_edid_blk_print(&buf0[blk_idx * 128],
blk_idx);
hdmitx_edid_blk_print(&edid_buf[blk_idx * 128], blk_idx);
}
}
@@ -560,6 +560,22 @@ const struct hdmi_timing *hdmitx_mode_match_timing_name(const char *name)
}
EXPORT_SYMBOL(hdmitx_mode_match_timing_name);
bool hdmitx_validate_y420_vic(enum hdmi_vic vic)
{
const struct hdmi_timing *timing;
/* 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;
}
EXPORT_SYMBOL(hdmitx_validate_y420_vic);
const char *hdmitx_mode_get_timing_name(enum hdmi_vic vic)
{
const struct hdmi_timing *timing =
@@ -23,7 +23,7 @@ static int hdmitx_common_pre_enable_mode(struct hdmitx_common *tx_comm,
return -1;
}
memcpy(vinfo->hdmichecksum, tx_comm->rxcap.chksum, 10);
memcpy(vinfo->hdmichecksum, tx_comm->rxcap.hdmichecksum, 10);
if (vinfo->mode == VMODE_HDMI) {
width = tx_comm->rxcap.physical_width;
height = tx_comm->rxcap.physical_height;
@@ -58,24 +58,17 @@ static ssize_t rawedid_show(struct device *dev,
int pos = 0;
int i;
int num;
int ext_block_num = 0;
int block_num = 0;
/* prevent null prt */
if (!global_tx_common->edid_ptr)
global_tx_common->edid_ptr = global_tx_common->EDID_buf;
ext_block_num = global_tx_common->edid_ptr[126];
if (ext_block_num && global_tx_common->edid_ptr[128 + 4] == EXTENSION_EEODB_EXT_TAG &&
global_tx_common->edid_ptr[128 + 5] == EXTENSION_EEODB_EXT_CODE)
ext_block_num = global_tx_common->edid_ptr[128 + 6]; //EEODB
if (ext_block_num < 8)
num = (ext_block_num + 1) * 128;
block_num = hdmitx_edid_valid_block_num(global_tx_common->EDID_buf);
if (block_num <= 8)
num = block_num * 128;
else
num = 8 * 128;
for (i = 0; i < num; i++)
pos += snprintf(buf + pos, PAGE_SIZE, "%02x",
global_tx_common->edid_ptr[i]);
global_tx_common->EDID_buf[i]);
pos += snprintf(buf + pos, PAGE_SIZE, "\n");
@@ -98,7 +91,7 @@ static ssize_t edid_parsing_show(struct device *dev,
{
int pos = 0;
if (check_dvi_hdmi_edid_valid(global_tx_common->edid_ptr))
if (check_dvi_hdmi_edid_valid(global_tx_common->EDID_buf))
pos += snprintf(buf + pos, PAGE_SIZE, "ok\n");
else
pos += snprintf(buf + pos, PAGE_SIZE, "ng\n");
@@ -207,12 +207,7 @@ struct hdmitx_dev {
bool systemcontrol_on;
unsigned char vid_mute_op;
atomic_t kref_video_mute;
spinlock_t edid_spinlock; /* edid hdr/dv cap lock */
/*hw members*/
int hdmitx_gpios_hpd;
int hdmitx_gpios_scl;
int hdmitx_gpios_sda;
unsigned int hdmi_rext; /* Rext resistor */
struct hdmitx_clk_tree_s hdmitx_clk_tree;
bool pre_tmds_clk_div40;
@@ -243,7 +238,6 @@ void hdmitx_current_status(enum hdmitx_event_log_bits event);
extern struct aud_para hdmiaud_config_data;
extern struct aud_para hsty_hdmiaud_config_data[8];
extern unsigned int hsty_hdmiaud_config_loc, hsty_hdmiaud_config_num;
extern struct mutex getedid_mutex;
int hdmitx_set_display(struct hdmitx_dev *hdmitx_device,
enum hdmi_vic videocode);
@@ -192,7 +192,6 @@ struct hdmitx_dev {
u32 aon_output:1; /* always output in bl30 */
u32 bist_lock:1;
u32 fr_duration;
spinlock_t edid_spinlock; /* edid hdr/dv cap lock */
struct vpu_dev_s *hdmitx_vpu_clk_gate_dev;
/*DRM related*/
@@ -36,8 +36,6 @@ struct hdmitx_common {
*/
u32 hdr_priority;
char hdmichecksum[11];
char fmt_attr[16];
/* 0.1% clock shift, 1080p60hz->59.94hz */
@@ -63,13 +61,18 @@ struct hdmitx_common {
u32 already_used;
/*edid related*/
unsigned char *edid_ptr;
unsigned char EDID_buf[EDID_MAX_BLOCK * 128]; // TODO
unsigned char EDID_hash[20];
/* the checksum of current edid */
/* indicate RX edid data integrated, HEAD valid and checksum pass */
unsigned int edid_parsing;
struct rx_cap rxcap;
/*edid related end*/
bool hdmitx_edid_done;
/* edid related end */
struct mutex getedid_mutex;
spinlock_t edid_spinlock; /* edid hdr/dv cap lock */
/* GPIO hpd/scl/sda members*/
int hdmitx_gpios_hpd;
int hdmitx_gpios_scl;
int hdmitx_gpios_sda;
/*DRM related*/
struct connector_hpd_cb drm_hpd_cb;
@@ -197,13 +200,7 @@ int hdmitx_get_attr(struct hdmitx_common *tx_comm, char attr[16]);
int hdmitx_get_hdrinfo(struct hdmitx_common *tx_comm, struct hdr_info *hdrinfo);
/*edid related function.*/
int hdmitx_update_edid_chksum(u8 *buf, u32 block_cnt, struct rx_cap *rxcap);
int hdmitx_edid_parse(struct hdmitx_common *tx_comm); // TODO
void hdmitx_edid_print(struct hdmitx_common *tx_comm); // TODO, remove compare
void hdmitx_edid_buffer_clear(struct hdmitx_common *tx_comm);
void hdmitx_edid_rxcap_clear(struct hdmitx_common *tx_comm);
bool hdmitx_edid_only_support_sd(struct rx_cap *prxcap);
bool hdmitx_validate_y420_vic(enum hdmi_vic vic);
void hdmitx_get_edid(struct hdmitx_common *tx_comm, struct hdmitx_hw_common *tx_hw_base);
/*debug functions*/
int hdmitx_load_edid_file(char *path);
@@ -199,9 +199,10 @@ struct rx_cap {
bool ifdb_present;
/* IFDB, currently only use below node */
u8 additional_vsif_num;
u8 edid_parsing;
/*blk0 check sum*/
u8 blk0_chksum;
u8 chksum[10];
u8 hdmichecksum[11]; /* string with 0xAABBCCDD */
u8 head_err;
u8 chksum_err;
};
@@ -261,5 +262,12 @@ bool hdmitx_edid_is_all_zeros(unsigned char *rawedid);
int _check_base_structure(unsigned char *buf);
int _check_edid_blk_chksum(unsigned char *block);
int check_dvi_hdmi_edid_valid(unsigned char *buf);
int hdmitx_edid_parse(struct rx_cap *prxcap, u8 *edid_buf);
unsigned int hdmitx_edid_valid_block_num(unsigned char *edid_buf);
bool hdmitx_validate_y420_vic(enum hdmi_vic vic);
void hdmitx_edid_print(u8 *edid_buf);
void hdmitx_edid_buffer_clear(u8 *edid_buf, int size);
void hdmitx_edid_rxcap_clear(struct rx_cap *prxcap);
bool hdmitx_edid_only_support_sd(struct rx_cap *prxcap);
#endif