diff --git a/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 851096e31..e7bebd6b2 100644 --- a/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -46,6 +46,9 @@ #include #include #include +#include +#include + #include "hw/tvenc_conf.h" #include "hw/common.h" #include "hw/hw_clk.h" @@ -194,6 +197,13 @@ struct vout_device_s hdmitx_vdev = { struct hdmi_config_platform_data *hdmi_pdata; +static struct extcon_dev *hdmitx_extcon_hdmi; + +static const unsigned int hdmi_extcon_cable[] = { + EXTCON_DISP_HDMI, + EXTCON_NONE, +}; + static struct hdmitx_uevent hdmi_events[] = { { .type = HDMITX_HPD_EVENT, @@ -323,6 +333,7 @@ static void hdmitx_early_suspend(struct early_suspend *h) hdmitx_edid_clear(hdev); hdmitx_edid_ram_buffer_clear(hdev); edidinfo_detach_to_vinfo(hdev); + hdmitx_set_uevent(HDMITX_HDCPPWR_EVENT, HDMI_SUSPEND); hdmitx_set_uevent(HDMITX_AUDIO_EVENT, 0); hdev->tx_hw.cntlconfig(&hdev->tx_hw, CONF_CLR_AVI_PACKET, 0); @@ -396,6 +407,8 @@ static void hdmitx_late_resume(struct early_suspend *h) if (info && drm_hdmitx_chk_mode_attr_sup(info->name, suspend_fmt_attr)) setup_attr(suspend_fmt_attr); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, + hdev->tx_comm.hpd_state); hdmitx_set_uevent(HDMITX_HPD_EVENT, hdev->tx_comm.hpd_state); hdmitx_set_uevent(HDMITX_HDCPPWR_EVENT, HDMI_WAKEUP); hdmitx_set_uevent(HDMITX_AUDIO_EVENT, hdev->tx_comm.hpd_state); @@ -4172,7 +4185,8 @@ static ssize_t fake_plug_store(struct device *dev, /*notify to drm hdmi*/ hdmitx_hpd_notify_unlocked(&hdev->tx_comm); - + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, + hdev->tx_comm.hpd_state); hdmitx_set_uevent(HDMITX_HPD_EVENT, hdev->tx_comm.hpd_state); return count; @@ -5551,6 +5565,7 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) hdev->tx_comm.edid_parsing ? hdev->tx_comm.edid_ptr : NULL); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 1); hdmitx_set_uevent(HDMITX_HPD_EVENT, 1); /* audio uevent is used for android to * register hdmi audio device, it should @@ -5629,6 +5644,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->tx_comm.hpd_state = 0; hdmitx_notify_hpd(hdev->tx_comm.hpd_state, NULL); hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_AVMUTE_OP, SET_AVMUTE); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); hdmitx_set_uevent(HDMITX_HPD_EVENT, 0); hdmitx_set_uevent(HDMITX_AUDIO_EVENT, 0); mutex_unlock(&hdmimode_mutex); @@ -5660,6 +5676,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->tx_comm.hpd_state = 0; hdmitx_notify_hpd(hdev->tx_comm.hpd_state, NULL); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); hdmitx_set_uevent(HDMITX_HPD_EVENT, 0); hdmitx_set_uevent(HDMITX_AUDIO_EVENT, 0); mutex_unlock(&hdmimode_mutex); @@ -5926,6 +5943,30 @@ void hdmitx_hdcp_status(int hdmi_authenticated) hdmi_authenticated); } +/* for compliance with p/q/r/s/t, need both extcon and hdmi_event + * there're mixed android/kernel combination, P/Q + * only listen to extcon; while R/S only listen to uevent + * t need listen to extcon(only hdmi hpd) and uevent + */ +static int hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) +{ + int ret; + + /*hdmitx extcon hdmi*/ + hdmitx_extcon_hdmi = devm_extcon_dev_allocate(&pdev->dev, hdmi_extcon_cable); + if (IS_ERR(hdmitx_extcon_hdmi)) { + pr_info("%s[%d] hdmitx_extcon_hdmi allocated failed\n", __func__, __LINE__); + if (PTR_ERR(hdmitx_extcon_hdmi) != -ENODEV) + return PTR_ERR(hdmitx_extcon_hdmi); + hdmitx_extcon_hdmi = NULL; + } + ret = devm_extcon_dev_register(&pdev->dev, hdmitx_extcon_hdmi); + if (ret < 0) + pr_info("%s[%d] hdmitx_extcon_hdmi register failed\n", __func__, __LINE__); + + return 0; +} + static void hdmitx_init_parameters(struct hdmitx_info *info) { memset(info, 0, sizeof(struct hdmitx_info)); @@ -6421,11 +6462,14 @@ static int amhdmitx_probe(struct platform_device *pdev) aout_register_client(&hdmitx_notifier_nb_a); #endif spin_lock_init(&hdev->edid_spinlock); + hdmitx_extcon_register(pdev, dev); + /* update fmt_attr */ hdmitx_fmt_attr(hdev); hdev->tx_comm.hpd_state = !!hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_HPD_GPI_ST, 0); hdmitx_notify_hpd(hdev->tx_comm.hpd_state, NULL); + hdmitx_set_uevent(HDMITX_HDCPPWR_EVENT, HDMI_WAKEUP); INIT_WORK(&hdev->work_hdr, hdr_work_func); diff --git a/drivers/media/vout/hdmitx21/hdmi_tx_main.c b/drivers/media/vout/hdmitx21/hdmi_tx_main.c index 4835dcc9d..0550ad995 100644 --- a/drivers/media/vout/hdmitx21/hdmi_tx_main.c +++ b/drivers/media/vout/hdmitx21/hdmi_tx_main.c @@ -46,6 +46,9 @@ #include #include #include +#include +#include + #include "hdmi_tx_ext.h" #include "hdmi_tx.h" @@ -161,6 +164,13 @@ static struct vout_device_s hdmitx_vdev = { .video_mute = hdmitx21_video_mute_op, }; +static struct extcon_dev *hdmitx_extcon_hdmi; + +static const unsigned int hdmi_extcon_cable[] = { + EXTCON_DISP_HDMI, + EXTCON_NONE, +}; + static struct hdmitx_uevent hdmi_events[] = { { .type = HDMITX_HPD_EVENT, @@ -329,6 +339,8 @@ static void hdmitx_late_resume(struct early_suspend *h) hdev->tx_hw.cntlconfig(&hdev->tx_hw, CONF_AUDIO_MUTE_OP, AUDIO_MUTE); /* set_disp_mode_auto(); */ + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, + hdev->tx_comm.hpd_state); hdmitx21_set_uevent(HDMITX_HPD_EVENT, hdev->tx_comm.hpd_state); hdmitx21_set_uevent(HDMITX_HDCPPWR_EVENT, HDMI_WAKEUP); hdmitx21_set_uevent(HDMITX_AUDIO_EVENT, hdev->tx_comm.hpd_state); @@ -3264,6 +3276,8 @@ static ssize_t fake_plug_store(struct device *dev, /*notify to drm hdmi*/ hdmitx_hpd_notify_unlocked(&hdev->tx_comm); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, + hdev->tx_comm.hpd_state); hdmitx21_set_uevent(HDMITX_HPD_EVENT, hdev->tx_comm.hpd_state); return count; @@ -4025,6 +4039,7 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) /*notify to drm hdmi*/ hdmitx_hpd_notify_unlocked(&hdev->tx_comm); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 1); hdmitx21_set_uevent(HDMITX_HPD_EVENT, 1); hdmitx21_set_uevent(HDMITX_AUDIO_EVENT, 1); /* Should be started at end of output */ @@ -4098,6 +4113,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdmitx_notify_hpd(hdev->tx_comm.hpd_state, NULL); } hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_AVMUTE_OP, SET_AVMUTE); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); hdmitx21_set_uevent(HDMITX_HPD_EVENT, 0); hdmitx21_set_uevent(HDMITX_AUDIO_EVENT, 0); mutex_unlock(&hdev->tx_comm.setclk_mutex); @@ -4128,6 +4144,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) /*notify to drm hdmi*/ hdmitx_hpd_notify_unlocked(&hdev->tx_comm); + extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); hdmitx21_set_uevent(HDMITX_HPD_EVENT, 0); hdmitx21_set_uevent(HDMITX_AUDIO_EVENT, 0); @@ -4326,6 +4343,30 @@ void hdmitx21_hdcp_status(int hdmi_authenticated) hdmitx21_set_uevent(HDMITX_HDCP_EVENT, hdmi_authenticated); } +/* for compliance with p/q/r/s/t, need both extcon and hdmi_event + * there're mixed combination, P/Q only listen to extcon; + * while R/S only listen to uevent + * t need listen to extcon(only hdmi hpd) and uevent + */ +static int hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) +{ + int ret; + + /*hdmitx extcon hdmi*/ + hdmitx_extcon_hdmi = devm_extcon_dev_allocate(&pdev->dev, hdmi_extcon_cable); + if (IS_ERR(hdmitx_extcon_hdmi)) { + pr_info("%s[%d] hdmitx_extcon_hdmi allocated failed\n", __func__, __LINE__); + if (PTR_ERR(hdmitx_extcon_hdmi) != -ENODEV) + return PTR_ERR(hdmitx_extcon_hdmi); + hdmitx_extcon_hdmi = NULL; + } + ret = devm_extcon_dev_register(&pdev->dev, hdmitx_extcon_hdmi); + if (ret < 0) + pr_info("%s[%d] hdmitx_extcon_hdmi register failed\n", __func__, __LINE__); + + return 0; +} + static void hdmitx_init_parameters(struct hdmitx_info *info) { memset(info, 0, sizeof(struct hdmitx_info)); @@ -4744,7 +4785,7 @@ static int amhdmitx_probe(struct platform_device *pdev) } aout_register_client(&hdmitx_notifier_nb_a); #endif - + hdmitx_extcon_register(pdev, dev); /* update fmt_attr */ hdmitx21_fmt_attr(hdev); diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_version.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_version.h index 8b38ea4c6..4846b065c 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_version.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_version.h @@ -33,6 +33,7 @@ "V03.00.01.00.01.03.04 [20220803] [BUG] echo 1 > /sys/class/display/bist lead to panic\n" \ "V03.00.01.00.01.03.05 [20220913] [BUG] add DDC reset before do EDID transaction\n" \ "V03.00.01.00.01.03.06 [20220915] [BUG] Don't reset variables when parse a new block\n" \ - "V03.00.01.00.01.03.07 [20220926] [BUG] enable null packt for special TV\n" + "V03.00.01.00.01.03.07 [20220926] [BUG] enable null packt for special TV\n" \ + "V03.00.01.00.01.03.08 [20221012] [NEW] add hdmi hpd extcon\n" #endif // __HDMI20_VERSION_H__ diff --git a/include/linux/amlogic/media/vout/hdmi_tx21/hdmi_version.h b/include/linux/amlogic/media/vout/hdmi_tx21/hdmi_version.h index 91d5d1438..83f01ab74 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx21/hdmi_version.h +++ b/include/linux/amlogic/media/vout/hdmi_tx21/hdmi_version.h @@ -36,6 +36,7 @@ "V03.00.00.00.03.03.06 [20220829] [NEWF] support avi content type\n" \ "V03.00.00.00.03.03.07 [20220913] [BUGFIX] add DDC reset before do EDID transaction\n" \ "V03.00.00.00.03.03.08 [20220919] [BUG] y422 mapping and Enable the dither\n" \ - "V03.00.00.00.03.03.09 [20220915] [BUG] Don't reset variables when parse a new block\n" + "V03.00.00.00.03.03.09 [20220915] [BUG] Don't reset variables when parse a new block\n" \ + "V03.00.00.00.03.03.10 [20221012] [NEW] add hdmi hpd extcon\n" #endif // __HDMI21_VERSION_H__