From 6784a061a285edc74fdd3783ae5bf4b4ee87feb5 Mon Sep 17 00:00:00 2001 From: Wang Chenlu Date: Wed, 13 May 2026 17:48:13 +0800 Subject: [PATCH 1/3] media:phytium-jpeg: Redesign the feature of diplaying 'No Signal' on KVM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BMC KVM Web UI must display a 'No Signal' status from the moment a host is powered on until its VGA monitor is activated. As the previous implementation did not perform reliably on certain platform, this new solution has been adopted to resolve these known issues. Mainline: Open-Source Signed-off-by: Wang Min Signed-off-by: Wang Yinfeng Signed-off-by:Wang Chenlu --- .../platform/phytium/phytium_jpeg_core.c | 58 ++++++++++++++----- .../platform/phytium/phytium_jpeg_core.h | 7 ++- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.c b/drivers/media/platform/phytium/phytium_jpeg_core.c index 540359974a419..a80f61310e91e 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.c +++ b/drivers/media/platform/phytium/phytium_jpeg_core.c @@ -210,22 +210,47 @@ static void phytium_jpeg_get_resolution(struct phytium_jpeg_dev *jpeg_dev) u32 width; u32 height; struct v4l2_bt_timings *detected_timings = &jpeg_dev->detected_timings; + u32 input_signal; /* Before get a new resolution, maybe need to wait 10 us */ detected_timings->width = MIN_WIDTH; detected_timings->height = MIN_HEIGHT; jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; - phytium_jpeg_enable_source_detecting(jpeg_dev); source_info = phytium_jpeg_read(jpeg_dev, SRC_VGA_INFO_REG); width = (source_info & SRC_HOR_PIXELS) >> SRC_WIDTH_SHIFT; height = (source_info & SRC_VER_PIXELS) >> SRC_HEIGHT_SHIFT; + input_signal = phytium_jpeg_read(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST)); + dev_dbg(jpeg_dev->dev, "get resolution: %uX%u, power 0x%x, once_power %u.\n", + width, height, input_signal, jpeg_dev->once_poweroff); + /* The resolution is 640*480 and V4L2_IN_ST_NO_SIGNAL in the case that host is poweroff. */ + if (input_signal == HOST_POWER_OFF) { + dev_dbg(jpeg_dev->dev, "Host is poweroff.\n"); + jpeg_dev->once_poweroff = true; + return; + } + + /* Host machine has never been poweroff since JPEG driver starts running */ + if (jpeg_dev->once_poweroff == false) { + input_signal = HAVE_SIGNAL; + phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL); + } else if (input_signal == HOST_POWER_ON) { + dev_dbg(jpeg_dev->dev, "No signal on KVM.\n"); + return; + } + + if ((input_signal == HAVE_SIGNAL && width * height != 0) || + test_bit(VIDEO_RES_CHANGE, &jpeg_dev->status)) { + jpeg_dev->v4l2_input_status = 0; + dev_dbg(jpeg_dev->dev, "output signal, status 0x%lx.\n", jpeg_dev->status); + } + + if (width * height != 0) { detected_timings->width = width; detected_timings->height = height; - jpeg_dev->v4l2_input_status = 0; cur_non_zero = true; } else { /* filter some repeated log-print lines */ @@ -492,11 +517,8 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { int ret; - u32 source_info; - u32 width; - u32 height; struct phytium_jpeg_dev *jpeg_dev = video_drvdata(file); - + u32 input_signal; /* * This blocks only if the driver is currently in the process of * detecting a new resolution; in the event of no signal or timeout @@ -516,13 +538,9 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv, timings->type = V4L2_DV_BT_656_1120; timings->bt = jpeg_dev->detected_timings; - /* Get resolution from SRC_VGA_INFO_REG */ - source_info = phytium_jpeg_read(jpeg_dev, SRC_VGA_INFO_REG); - width = (source_info & SRC_HOR_PIXELS) >> SRC_WIDTH_SHIFT; - height = (source_info & SRC_VER_PIXELS) >> SRC_HEIGHT_SHIFT; - - /* Check if that the current resolution is zero. */ - if (width == 0 || height == 0) + input_signal = phytium_jpeg_read(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST)); + /* Check if that the power status of the host machine resolution */ + if (input_signal != HAVE_SIGNAL) jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; return jpeg_dev->v4l2_input_status ? -ENOLINK : 0; @@ -820,8 +838,14 @@ static void phytium_jpeg_resolution_work(struct work_struct *work) goto done; phytium_jpeg_init_regs(jpeg_dev); + /* It is evident that the host remains powered on during the + * resolution switch process, so restore the JPEG configuration. + */ + phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL); + jpeg_dev->once_poweroff = false; phytium_jpeg_get_resolution(jpeg_dev); + /* if source's resolution is changed, the event should be enqueued */ if (jpeg_dev->detected_timings.width != jpeg_dev->active_timings.width || jpeg_dev->detected_timings.height != jpeg_dev->active_timings.height || @@ -833,7 +857,7 @@ static void phytium_jpeg_resolution_work(struct work_struct *work) }; v4l2_event_queue(&jpeg_dev->vdev, &event); clear_bit(VIDEO_FRAME_INPRG, &jpeg_dev->status); - dev_info(jpeg_dev->dev, "event notifies changing resolution\n"); + dev_info(jpeg_dev->dev, "event notifies changing resolution.\n"); } else if (test_bit(VIDEO_STREAMING, &jpeg_dev->status)) { /* No resolution change so just restart streaming */ dev_info(jpeg_dev->dev, "resolution doesn't change\n"); @@ -1178,7 +1202,7 @@ static int phytium_jpeg_parser_timer30_irq(struct phytium_jpeg_dev *jpeg_dev) } ret = devm_request_irq(dev, irq, phytium_jpeg_timer30_irq, - IRQF_TIMER, PHYTIUM_JPEG_NAME, jpeg_dev); + IRQF_TIMER, PHYTIUM_JPEG_NAME, jpeg_dev); if (ret < 0) dev_err(dev, "Failed to request timer30 IRQ %d\n", irq); @@ -1231,7 +1255,8 @@ static int phytium_jpeg_init(struct phytium_jpeg_dev *jpeg_dev) dev_err(dev, "Failed to set DMA mask\n"); return ret; } - + /* Initialize the value of buffer_list_address15 register to identify having signal */ + phytium_jpeg_write(jpeg_dev, BUF_LIST_INDEX_ADDR(VB_BUF_LAST), HAVE_SIGNAL); /* Initializing JPEG Y and CbCr quantization table */ phytium_jpeg_init_jpeg_quant(jpeg_dev); @@ -1287,6 +1312,7 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) jpeg_dev->pix_fmt.colorspace = V4L2_COLORSPACE_SRGB; /* maybe ARGB */ jpeg_dev->pix_fmt.quantization = V4L2_QUANTIZATION_FULL_RANGE; jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; + jpeg_dev->once_poweroff = false; ret = v4l2_device_register(jpeg_dev->dev, v4l2_dev); if (ret != 0) { diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.h b/drivers/media/platform/phytium/phytium_jpeg_core.h index a03ced5a0f6d3..927a215d3af23 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.h +++ b/drivers/media/platform/phytium/phytium_jpeg_core.h @@ -53,6 +53,10 @@ #define INVALID_RESOLUTION_RETRIES 2 #define CAPTURE_BUF_NUMBER 3 /* using how many buffers */ #define VB_BUF_NO 0 /* there are 16 buffer, use which one */ +#define VB_BUF_LAST 15 /* Use the last one to identify no signal */ +#define HAVE_SIGNAL 0xCDDCDCCD /* VGA output signal */ +#define HOST_POWER_ON 0x0 /* Host is poweron */ +#define HOST_POWER_OFF 0xDEADBEEF /* Host is poweroff */ /* The below macros are defined for the JPEG header of the phytium JPEG Engine */ #define PHYTIUM_JPEG_HEADER_LEN (256 * 3) @@ -123,13 +127,14 @@ struct phytium_jpeg_dev { unsigned int sequence; unsigned int max_compressed_size; struct phytium_jpeg_addr src_addrs[OCM_BUF_NUM]; - struct phytium_jpeg_addr dst_addrs[16]; + struct phytium_jpeg_addr dst_addrs[VB_BUF_LAST + 1]; bool yuv420; unsigned int frame_rate; void __iomem *timer30_addr; void __iomem *timer31_addr; struct v4l2_ctrl_handler ctrl_handler; + bool once_poweroff; }; struct phytium_jpeg_config { From 2562037efd0654be50ca9cc7ead4bd82fe81f938 Mon Sep 17 00:00:00 2001 From: Wang Chenlu Date: Wed, 13 May 2026 17:52:12 +0800 Subject: [PATCH 2/3] media: phytium-jpeg: Restricted adaptation platform for jpeg driver This driver is exclusively for the PHYTIUM platform and is not compatible with other SoCs. This restriction prevents errors on unsupported platform. Mainline: Open-Source Signed-off-by: Wang Min Signed-off-by: Wang Yinfeng Signed-off-by:Wang Chenlu --- drivers/media/platform/phytium/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/phytium/Kconfig b/drivers/media/platform/phytium/Kconfig index 498314fbfc947..3ee2e288ffdaa 100644 --- a/drivers/media/platform/phytium/Kconfig +++ b/drivers/media/platform/phytium/Kconfig @@ -6,6 +6,7 @@ config VIDEO_PHYTIUM_JPEG tristate "Phytium JPEG Encoder Engine driver" depends on V4L_PLATFORM_DRIVERS depends on VIDEO_DEV + depends on ARCH_PHYTIUM select VIDEOBUF2_DMA_CONTIG help Support for the Phytium JPEG Encoder Engine embedded From d31c1494b3151c4f00dff17dcb62f9e7c7baf5ec Mon Sep 17 00:00:00 2001 From: Wang Chenlu Date: Wed, 13 May 2026 17:54:42 +0800 Subject: [PATCH 3/3] media: phytium-jpeg: Reduce switch resolution latency The previous delay is so long that it interferes with the proper operation of the switch resolution. This incorrect operation would occasionally cause the BMC to hang. Mainline: Open-Source Signed-off-by: Wang Min Signed-off-by: Wang Yinfeng Signed-off-by: Wang Chenlu --- drivers/media/platform/phytium/phytium_jpeg_core.c | 3 --- drivers/media/platform/phytium/phytium_jpeg_core.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.c b/drivers/media/platform/phytium/phytium_jpeg_core.c index a80f61310e91e..c6ca52a3ca398 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.c +++ b/drivers/media/platform/phytium/phytium_jpeg_core.c @@ -186,9 +186,6 @@ static void phytium_jpeg_off(struct phytium_jpeg_dev *jpeg_dev) } clear_bit(VIDEO_CLOCKS_ON, &jpeg_dev->status); - /* wait 50 ms */ - mdelay(50); - /* C08 bit7 1:busy */ } static inline void phytium_jpeg_enable_source_detecting(struct phytium_jpeg_dev *jpeg_dev) diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.h b/drivers/media/platform/phytium/phytium_jpeg_core.h index 927a215d3af23..6b291f23dd0fc 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.h +++ b/drivers/media/platform/phytium/phytium_jpeg_core.h @@ -46,7 +46,7 @@ #define MAX_PIXEL_CLOCK (1920 * 1080 * 60) /* 1920 x 1080 x 60Hz */ #define SOURCE_RESOLUTION_DETECT_TIMEOUT msecs_to_jiffies(500) -#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(250) +#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(150) #define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250) #define STOP_TIMEOUT msecs_to_jiffies(1000)