Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
758acc5
Kernel 6.11 support
rhgndf Oct 13, 2024
2b34181
Fix edid update
rhgndf Oct 13, 2024
b502d3f
Make it compile on 6.11
rhgndf Oct 23, 2024
091da7e
kernel-6.15
Jul 19, 2025
425860c
kernel-6.15
Jul 19, 2025
c3432d7
kernel-6.15
Jul 19, 2025
b216f9d
Optimized ms912x driver code without breaking functionality
Jul 19, 2025
ed01bba
Optimized transfer
Jul 19, 2025
6641931
Optimized driver
Jul 19, 2025
8c7723d
Fix driver features: add DRIVER_RENDER flag for better compatibility
Jul 20, 2025
dcb01a3
Limit frame rate to 60 fps to reduce CPU usage and improve USB HDMI p…
Jul 20, 2025
1bd7d3e
Optimización: calcular u y v con promedios de RGB
Jul 20, 2025
7077109
Optimize temp_buffer allocation: pre-allocate fixed buffer size for m…
Jul 20, 2025
6c2a59c
Fix on ms912x_free_request
Jul 20, 2025
37f09d6
Improve performance by removing blocking wait_for_completion_timeout …
Jul 20, 2025
f1fe2cc
fixes
Jul 21, 2025
2de8c78
fixed vsync
Jul 21, 2025
9b31292
Implement YUV422 LUT and framebuffer conversion for USB transfer
Jul 21, 2025
af14c15
Allow higher frame rate by lowering timeout to 1 ms
Jul 21, 2025
80864e3
Fixed timeout in fps limiter to 16ms = 60fps
Jul 21, 2025
2e85e19
ms912x_pipe_update optized
Jul 22, 2025
1e7662d
Make it compile on 6.12 (6.11)
Jul 22, 2025
1a12fa6
Restored screen modes previusly removed
Jul 22, 2025
7952e0d
Format code with clang-format and clean comments as requested
Jul 27, 2025
c385cd1
Format code with clang-format and clean comments as requested
Jul 27, 2025
3d65c05
Update ms912x_registers.c
tiirwaa Jul 27, 2025
24de617
Keep original indentation for ms912x_mode_list
Jul 27, 2025
a15f323
Merge branch 'kernel-6.15'
Jul 27, 2025
0426c19
restore original comments
Jul 27, 2025
94ad4b2
'yuv_lut_initialized' lacks synchronization fixed
Jul 27, 2025
84ce500
last_send_jiffies per device fixed
Jul 27, 2025
9a8444e
removed static enum drm_mode_status
Jul 27, 2025
7c5fab6
restored static enum drm_mode_status needed by ms912x_pipe_mode_valid
Jul 27, 2025
b4a51dd
removed HAS_BLOCK_READ never defined
Jul 27, 2025
03b8a8c
fixes from 6.15
Jul 27, 2025
2cab93a
Delete dmesg.log
tiirwaa Jul 27, 2025
4f758e4
Delete dmesg.log
tiirwaa Jul 27, 2025
5f89ff5
Update README.md
tiirwaa Jul 28, 2025
8f0154e
Update README.md
tiirwaa Jul 28, 2025
222f8fb
Update README.md
tiirwaa Jul 28, 2025
7b0576a
Update ms912x_drv.c
spin877 Jul 28, 2025
6402092
Merge pull request #1 from spin877/patch-1
tiirwaa Aug 13, 2025
d1a33aa
Enable runtime configuration of ms912x_mode_list[0].mode via module p…
Aug 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,29 @@ ms912x-y := \
ms912x_registers.o \
ms912x_connector.o \
ms912x_transfer.o \
ms912x_drv.o
ms912x_drv.o

obj-m := ms912x.o

KVER ?= $(shell uname -r)
KSRC ?= /lib/modules/$(KVER)/build
CURDIR := $(shell pwd)

USE_SSE2 ?= 0

ifeq ($(USE_SSE2),1)
CFLAGS_EXTRA += -msse2
endif

EXTRA_CFLAGS += $(CFLAGS_EXTRA)

all: modules

modules:
make CHECK="/usr/bin/sparse" -C $(KSRC) M=$(PWD) modules
$(MAKE) CHECK="/usr/bin/sparse" -C $(KSRC) M=$(CURDIR) modules

clean:
make -C $(KSRC) M=$(PWD) clean
rm -f $(PWD)/Module.symvers $(PWD)/*.ur-safe
$(MAKE) -C $(KSRC) M=$(CURDIR) clean
rm -f $(CURDIR)/Module.symvers $(CURDIR)/*.ur-safe

.PHONY: all modules clean
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ There are two variants:
- VID/PID is 534d:6021. Device is USB 2
- VID/PID is 345f:9132. Device is USB 3

For kernel 6.1 checkout branch kernel-6.1

- Driver adapted for Linux kernel 6.12(6.10, 6.11). by Andrey Rodríguez Araya
- Improved performance.

For kernel 6.15 checkout branch kernel-6.15

TODOs:

Expand All @@ -23,3 +27,12 @@ Driver is written by analyzing wireshark captures of the device.

Run `sudo dkms install .`

- make clean
- make all -j
- sudo rmmod ms912x # It will not work if the device is in use.
- sudo modprobe drm_shmem_helper
- sudo insmod ms912x.ko

Forked From: https://github.com/rhgndf/ms912x


7 changes: 5 additions & 2 deletions ms912x.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

struct ms912x_usb_request {
void *transfer_buffer;
void *temp_buffer;
struct ms912x_device *ms912x;
size_t transfer_len;
size_t alloc_len;
Expand All @@ -40,14 +41,15 @@ struct ms912x_device {

struct drm_connector connector;
struct drm_simple_display_pipe display_pipe;

struct drm_rect update_rect;

/* Double buffer to allow memcpy and transfer
* to happen in parallel
*/
int current_request;
struct ms912x_usb_request requests[2];
unsigned long last_send_jiffies;
};

struct ms912x_request {
Expand Down Expand Up @@ -116,4 +118,5 @@ int ms912x_fb_send_rect(struct drm_framebuffer *fb, const struct iosys_map *map,
void ms912x_free_request(struct ms912x_usb_request *request);
int ms912x_init_request(struct ms912x_device *ms912x,
struct ms912x_usb_request *request, size_t len);
#endif
void ms912x_init_yuv_lut(void);
#endif
97 changes: 78 additions & 19 deletions ms912x_connector.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_connector.h>
#include <drm/drm_edid.h>
Expand All @@ -7,30 +6,79 @@

#include "ms912x.h"

static int ms912x_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
static int ms912x_read_edid_block(struct ms912x_device *ms912x, u8 *buf,
unsigned int offset, size_t len)
{
struct ms912x_device *ms912x = data;
int offset = block * EDID_LENGTH;
int i, ret;
for (i = 0; i < len; i++) {
u16 address = 0xc000 + offset + i;
ret = ms912x_read_byte(ms912x, address);
const u16 base = 0xc000 + offset;
for (size_t i = 0; i < len; i++) {
u16 address = base + i;
int ret = ms912x_read_byte(ms912x, address);
if (ret < 0)
return ret;
buf[i] = ret;
}
return 0;
}

static int ms912x_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
{
struct ms912x_device *ms912x = data;
const int offset = block * EDID_LENGTH;
int ret = ms912x_read_edid_block(ms912x, buf, offset, len);
if (ret < 0)
pr_err("ms912x: failed to read EDID block %u\n", block);
return ret;
}

static void ms912x_add_fallback_mode(struct drm_connector *connector)
{
struct drm_display_mode *mode;

mode = drm_mode_create(connector->dev);
if (!mode)
return;

drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;

mode->clock = 65000;
mode->hdisplay = 1024;
mode->hsync_start = 1048;
mode->hsync_end = 1184;
mode->htotal = 1344;
mode->vdisplay = 768;
mode->vsync_start = 771;
mode->vsync_end = 777;
mode->vtotal = 806;
mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC;

drm_mode_probed_add(connector, mode);
}

static int ms912x_connector_get_modes(struct drm_connector *connector)
{
int ret;
int ret = 0;
struct ms912x_device *ms912x = to_ms912x(connector->dev);
struct edid *edid;
edid = drm_do_get_edid(connector, ms912x_read_edid, ms912x);
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
const struct drm_edid *edid;

edid = drm_edid_read_custom(connector, ms912x_read_edid, ms912x);
if (!edid) {
pr_warn("ms912x: EDID not found, falling back to default mode\n");
ms912x_add_fallback_mode(connector);
return 1;
}

ret = drm_edid_connector_update(connector, edid);
if (ret < 0) {
pr_err("ms912x: failed to update EDID connector\n");
ret = 0;
goto edid_free;
}

ret = drm_edid_connector_add_modes(connector);

edid_free:
drm_edid_free(edid);
return ret;
}

Expand All @@ -40,12 +88,15 @@ static enum drm_connector_status ms912x_detect(struct drm_connector *connector,
struct ms912x_device *ms912x = to_ms912x(connector->dev);
int status = ms912x_read_byte(ms912x, 0x32);

if (status < 0)
if (status < 0) {
pr_err("ms912x: failed to detect HDMI status\n");
return connector_status_unknown;
}

return status == 1 ? connector_status_connected :
connector_status_disconnected;
return (status == 1) ? connector_status_connected :
connector_status_disconnected;
}

static const struct drm_connector_helper_funcs ms912x_connector_helper_funcs = {
.get_modes = ms912x_connector_get_modes,
};
Expand All @@ -62,12 +113,20 @@ static const struct drm_connector_funcs ms912x_connector_funcs = {
int ms912x_connector_init(struct ms912x_device *ms912x)
{
int ret;

drm_connector_helper_add(&ms912x->connector,
&ms912x_connector_helper_funcs);

ret = drm_connector_init(&ms912x->drm, &ms912x->connector,
&ms912x_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
if (ret) {
pr_err("ms912x: failed to initialize connector\n");
return ret;
}

ms912x->connector.polled =
DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
return ret;
}

return 0;
}
Loading