From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 08:20:59 +0000 Subject: [PATCH] kernel_5.10 no rt --- kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c | 64 +++++++++++++++++++++++++------ 1 files changed, 51 insertions(+), 13 deletions(-) diff --git a/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 067314d..dcd49b6 100644 --- a/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/kernel/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -45,11 +45,11 @@ #include <media/videobuf2-v4l2.h> #include <soc/rockchip/rockchip-system-status.h> #include <sound/hdmi-codec.h> +#include <linux/rk_hdmirx_class.h> #include "rk_hdmirx.h" #include "rk_hdmirx_cec.h" #include "rk_hdmirx_hdcp.h" -static struct class *hdmirx_class; static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-3)"); @@ -269,6 +269,7 @@ static void hdmirx_cancel_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev); static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev); static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev); +static void hdmirx_interrupts_setup(struct rk_hdmirx_dev *hdmirx_dev, bool en); static u8 edid_init_data_340M[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, @@ -529,6 +530,16 @@ struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; u32 dma_cfg1; + if (port_no_link(hdmirx_dev)) { + v4l2_err(v4l2_dev, "%s port has no link!\n", __func__); + return -ENOLINK; + } + + if (signal_not_lock(hdmirx_dev)) { + v4l2_err(v4l2_dev, "%s signal is not locked!\n", __func__); + return -ENOLCK; + } + *timings = hdmirx_dev->timings; dma_cfg1 = hdmirx_readl(hdmirx_dev, DMA_CONFIG1); v4l2_dbg(1, debug, v4l2_dev, "%s: pix_fmt: %s, DMA_CONFIG1:%#x\n", @@ -615,8 +626,10 @@ static void hdmirx_get_pix_fmt(struct rk_hdmirx_dev *hdmirx_dev) { u32 val; + int timeout = 10; struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; +try_loop: val = hdmirx_readl(hdmirx_dev, DMA_STATUS11); hdmirx_dev->pix_fmt = val & HDMIRX_FORMAT_MASK; @@ -635,11 +648,16 @@ break; default: + if (timeout-- > 0) { + usleep_range(200 * 1000, 200 * 1010); + v4l2_err(v4l2_dev, "%s: get format failed, read again!\n", __func__); + goto try_loop; + } + hdmirx_dev->pix_fmt = HDMIRX_RGB888; + hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24; v4l2_err(v4l2_dev, "%s: err pix_fmt: %d, set RGB888 as default\n", __func__, hdmirx_dev->pix_fmt); - hdmirx_dev->pix_fmt = HDMIRX_RGB888; - hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24; break; } @@ -880,9 +898,12 @@ struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; u32 last_w, last_h; struct v4l2_bt_timings *bt = &timings->bt; + enum hdmirx_pix_fmt last_fmt; last_w = 0; last_h = 0; + last_fmt = HDMIRX_RGB888; + for (i = 0; i < try_cnt; i++) { ret = hdmirx_get_detected_timings(hdmirx_dev, timings, from_dma); @@ -891,7 +912,8 @@ last_h = bt->height; } - if (ret || (last_w != bt->width) || (last_h != bt->height)) + if (ret || (last_w != bt->width) || (last_h != bt->height) + || (last_fmt != hdmirx_dev->pix_fmt)) cnt = 0; else cnt++; @@ -901,6 +923,7 @@ last_w = bt->width; last_h = bt->height; + last_fmt = hdmirx_dev->pix_fmt; usleep_range(10*1000, 10*1100); } @@ -1545,7 +1568,7 @@ } hdmirx_reset_dma(hdmirx_dev); - usleep_range(200*1000, 200*1010); + usleep_range(500*1000, 500*1010); hdmirx_format_change(hdmirx_dev); return 0; @@ -2349,6 +2372,7 @@ FIFO_UNDERFLOW_INT_EN | HDMIRX_AXI_ERROR_INT_EN, 0); hdmirx_reset_dma(hdmirx_dev); + hdmirx_interrupts_setup(hdmirx_dev, false); v4l2_event_queue(&stream->vdev, &evt_signal_lost); if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_stop) hdmirx_dev->hdcp->hdcp_stop(hdmirx_dev->hdcp); @@ -2459,13 +2483,28 @@ hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_FORCE, 0x0); } +/* + * In the normal preview, some scenarios will trigger the change interrupt + * by mistake, and the trigger source of the interrupt needs to be detected + * to avoid the problem. + */ static void pkt_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev, int status, bool *handled) { struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; + u32 pre_fmt_fourcc = hdmirx_dev->cur_fmt_fourcc; + u32 pre_color_range = hdmirx_dev->cur_color_range; + u32 pre_color_space = hdmirx_dev->cur_color_space; if ((status & PKTDEC_AVIIF_CHG_IRQ)) { - process_signal_change(hdmirx_dev); + hdmirx_get_color_range(hdmirx_dev); + hdmirx_get_color_space(hdmirx_dev); + hdmirx_get_pix_fmt(hdmirx_dev); + if (hdmirx_dev->cur_fmt_fourcc != pre_fmt_fourcc || + hdmirx_dev->cur_color_range != pre_color_range || + hdmirx_dev->cur_color_space != pre_color_space) { + process_signal_change(hdmirx_dev); + } v4l2_dbg(2, debug, v4l2_dev, "%s: ptk0_st:%#x\n", __func__, status); *handled = true; @@ -3158,7 +3197,7 @@ struct rk_hdmirx_dev, delayed_work_audio); struct hdmirx_audiostate *as = &hdmirx_dev->audio_state; - u32 fs_audio, ch_audio; + u32 fs_audio, ch_audio, sample_flat; int cur_state, init_state, pre_state, fifo_status2; unsigned long delay = 200; @@ -3223,6 +3262,10 @@ } } as->pre_state = cur_state; + + sample_flat = hdmirx_readl(hdmirx_dev, AUDIO_PROC_STATUS1) & AUD_SAMPLE_FLAT; + hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, sample_flat ? 0 : I2S_EN); + exit: schedule_delayed_work_on(hdmirx_dev->bound_cpu, &hdmirx_dev->delayed_work_audio, @@ -3243,7 +3286,6 @@ plugin = tx_5v_power_present(hdmirx_dev); v4l2_dbg(1, debug, v4l2_dev, "%s: plugin:%d\n", __func__, plugin); if (plugin) { - hdmirx_interrupts_setup(hdmirx_dev, false); hdmirx_submodule_init(hdmirx_dev); hdmirx_update_bits(hdmirx_dev, SCDC_CONFIG, POWERPROVIDED, POWERPROVIDED); @@ -4280,7 +4322,7 @@ if (ret) goto err_unreg_video_dev; - hdmirx_dev->classdev = device_create_with_groups(hdmirx_class, + hdmirx_dev->classdev = device_create_with_groups(rk_hdmirx_class(), dev, MKDEV(0, 0), hdmirx_dev, hdmirx_groups, @@ -4438,9 +4480,6 @@ static int __init hdmirx_init(void) { - hdmirx_class = class_create(THIS_MODULE, "hdmirx"); - if (IS_ERR(hdmirx_class)) - return PTR_ERR(hdmirx_class); return platform_driver_register(&hdmirx_driver); } module_init(hdmirx_init); @@ -4448,7 +4487,6 @@ static void __exit hdmirx_exit(void) { platform_driver_unregister(&hdmirx_driver); - class_destroy(hdmirx_class); } module_exit(hdmirx_exit); -- Gitblit v1.6.2