diff --git a/drm_iface.c b/drm_iface.c index 8fa25fd..a276eee 100644 --- a/drm_iface.c +++ b/drm_iface.c @@ -268,10 +268,14 @@ static int sharp_memory_clip_mono_tagged(struct sharp_memory_panel* panel, size_ // End DMA area drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); - // Add indicators if in range - if ((clip->x1 < (fb->width - INDICATORS_WIDTH)) - && (clip->y1 < INDICATOR_HEIGHT)) { - draw_indicators(panel, buf, fb->width, clip); + // Add status indicators + if (g_param_indicators) { + + // Only redraw indicators if the dirty region would overwrite them + if ((clip->x1 < (fb->width - INDICATORS_WIDTH)) + && (clip->y1 < INDICATOR_HEIGHT)) { + draw_indicators(panel, buf, fb->width, clip); + } } // Convert in-place from 8-bit grayscale to mono diff --git a/ioctl_iface.c b/ioctl_iface.c index 7d3b7e5..1e0d058 100644 --- a/ioctl_iface.c +++ b/ioctl_iface.c @@ -1,13 +1,105 @@ #include +#include +#include +#include "params_iface.h" +#include "drm_iface.h" #include "ioctl_iface.h" +#define SHARP_IOC_MAGIC 0xd5 +#define SHARP_IOCTQ_SET_INVERT _IOW(SHARP_IOC_MAGIC, 1, uint32_t) +#define SHARP_IOCTQ_SET_INDICATOR _IOW(SHARP_IOC_MAGIC, 2, uint32_t) +#define SHARP_IOC_MAXNR 2 + +static int ioctl_set_invert(unsigned long arg) +{ + params_set_mono_invert((int)arg); + + return 0; +} + +static int ioctl_set_indicator(unsigned long arg) +{ + uint8_t idx, ch; + + idx = arg >> 8; + ch = arg & 0xff; + + return drm_set_indicator(idx, ch); +} + +static int sharp_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int sharp_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static long int sharp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + + case SHARP_IOCTQ_SET_INVERT: + (void)ioctl_set_invert((int)arg); + return 0; + + case SHARP_IOCTQ_SET_INDICATOR: + (void)ioctl_set_indicator((int)arg); + return 0; + + + default: + printk(KERN_INFO "Bad command: %d", cmd); + return -EINVAL; + } +} + +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = sharp_open, + .unlocked_ioctl = sharp_ioctl, + .release = sharp_release, +}; + +static struct cdev g_cdev; +static dev_t g_dev; +struct class *g_class; + int ioctl_probe(void) { + int rc; + + if ((rc = alloc_chrdev_region(&g_dev, 0, 1, "sharp"))) { + printk(KERN_ERR "Failed to allocate device numbers\n"); + return rc; + } + + g_class = class_create(THIS_MODULE, "sharp_class"); + device_create(g_class, NULL, g_dev, NULL, "sharp"); + + cdev_init(&g_cdev, &fops); + g_cdev.owner = THIS_MODULE; + + if ((rc = cdev_add(&g_cdev, g_dev, 1))) { + unregister_chrdev_region(g_dev, 1); + printk(KERN_ERR "Failed to add the character device\n"); + return rc; + } + + printk(KERN_INFO "Character device registered: major = %d, minor = %d\n", + MAJOR(g_dev), MINOR(g_dev)); + return 0; } void ioctl_remove(void) { - return; + cdev_del(&g_cdev); + device_destroy(g_class, g_dev); + class_destroy(g_class); + unregister_chrdev_region(g_dev, 1); + printk(KERN_INFO "Character device unregistered\n"); } diff --git a/params_iface.c b/params_iface.c index 04726de..5f93512 100644 --- a/params_iface.c +++ b/params_iface.c @@ -7,6 +7,7 @@ int g_param_mono_cutoff = 32; int g_param_mono_invert = 0; +int g_param_indicators = 1; static int set_param_u8(const char *val, const struct kernel_param *kp) { @@ -22,13 +23,6 @@ static int set_param_u8(const char *val, const struct kernel_param *kp) // Refresh framebuffer (void)drm_refresh(); - (void)drm_set_indicator(0, 's'); - (void)drm_set_indicator(1, 'p'); - (void)drm_set_indicator(2, 'c'); - (void)drm_set_indicator(3, 'a'); - (void)drm_set_indicator(4, 'g'); - (void)drm_set_indicator(5, 'm'); - return rc; } @@ -44,6 +38,9 @@ MODULE_PARM_DESC(mono_cutoff, module_param_cb(mono_invert, &u8_param_ops, &g_param_mono_invert, 0660); MODULE_PARM_DESC(mono_invert, "0 for no inversion, 1 for inversion"); +module_param_cb(indicators, &u8_param_ops, &g_param_indicators, 0660); +MODULE_PARM_DESC(mono_invert, "0 for no indicators, 1 for indicators"); + int params_probe(void) { return 0; @@ -53,3 +50,11 @@ void params_remove(void) { return; } + +void params_set_mono_invert(int setting) +{ + g_param_mono_invert = setting; + + // Refresh framebuffer + (void)drm_refresh(); +} diff --git a/params_iface.h b/params_iface.h index e62ec62..2d15730 100644 --- a/params_iface.h +++ b/params_iface.h @@ -3,8 +3,11 @@ extern int g_param_mono_cutoff; extern int g_param_mono_invert; +extern int g_param_indicators; int params_probe(void); void params_remove(void); +void params_set_mono_invert(int setting); + #endif