diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-19 10:09:22 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-19 10:09:22 -0700 |
| commit | f4cdf7ca9a1fdcca413157df19753f388a5a224e (patch) | |
| tree | 60a31895b2446cd7fa27514e8c2843534a0de0da /drivers/video/fbdev/hecubafb.c | |
| download | linux-stable-f4cdf7ca9a1fdcca413157df19753f388a5a224e.tar.gz linux-stable-f4cdf7ca9a1fdcca413157df19753f388a5a224e.zip | |
Merge tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-mediagrafted
Pull media updates from Mauro Carvalho Chehab:
- v4l2-core: added ISP statistics support and per-block validation
- v4l2-core: Allow unknown HDR10 white point and luminance
- New camera sensors: Sony IMX678 and IMX471m, Himax HM1092 IR sensor
- New codec: Milos: VPU v2.0 codec support
- isp driver: gained support for Dreamchip RPPX1 ISP framework
- vsp1 driver: gained support for RZ/T2H and RZ/N2H
- Novalake driver: gained CVS support for new NVL hardware
- dvb-core: fix feed leak on failed DMX_ADD_PID
- several driver fixes, cleanups and minor improvements
* tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (308 commits)
media: ipu-bridge: check all DMI entries when overriding sensor rotation
media: v4l2-async: avoid deleting unlinked ASC entry on link error
media: rzg2l-cru: Align bytesperline to hardware DMA stride requirement
media: intel/ipu6: fix async notifier cleanup leak on parse error
media: staging/ipu7: fix async notifier UAF on probe error path
media: amd: isp4: fix self-deadlock in isp4sd_pwron_and_init() error path
media: amd: isp4: release partial allocations in isp4if_alloc_fw_gpumem()
media: rcar-isp: Fix VSPX reference leaks
media: rcar-isp: Release ISPCORE resources
media: i2c: imx415: Release runtime PM reference on VBLANK error
media: i2c: imx415: Return test pattern write errors
media: renesas: vsp1: Declare index variables in for loop statement
media: renesas: vsp1: Make reset control optional to support platforms without a reset line
media: dt-bindings: media: renesas,vsp1: Document RZ/T2H and RZ/N2H SoCs
media: dt-bindings: media: renesas,fcp: Document RZ/T2H and RZ/N2H SoCs
media: nxp: imx8-isi: Add additional 32-bit RGB format support
media: nxp: imx8-isi: Add 16-bit raw Bayer format support
media: nxp: imx8-isi: Implement per-stream reference counting for multiplexed streams
media: nxp: imx8-isi: Use BIT_ULL() for 64-bit stream masks
media: nxp: imx8-isi: Correct color map between V4L2 and ISI
...
Diffstat (limited to 'drivers/video/fbdev/hecubafb.c')
| -rw-r--r-- | drivers/video/fbdev/hecubafb.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/drivers/video/fbdev/hecubafb.c b/drivers/video/fbdev/hecubafb.c new file mode 100644 index 000000000..dd2af980f --- /dev/null +++ b/drivers/video/fbdev/hecubafb.c @@ -0,0 +1,251 @@ +/* + * linux/drivers/video/hecubafb.c -- FB driver for Hecuba/Apollo controller + * + * Copyright (C) 2006, Jaya Kumar + * This work was sponsored by CIS(M) Sdn Bhd + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. + * This work was possible because of apollo display code from E-Ink's website + * http://support.eink.com/community + * All information used to write this code is from public material made + * available by E-Ink on its support site. Some commands such as 0xA4 + * were found by looping through cmd=0x00 thru 0xFF and supplying random + * values. There are other commands that the display is capable of, + * beyond the 5 used here but they are more complex. + * + * This driver is written to be used with the Hecuba display architecture. + * The actual display chip is called Apollo and the interface electronics + * it needs is called Hecuba. + * + * It is intended to be architecture independent. A board specific driver + * must be used to perform all the physical IO interactions. An example + * is provided as n411.c + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <linux/uaccess.h> + +#include <video/hecubafb.h> + +/* Display specific information */ +#define DPY_W 600 +#define DPY_H 800 + +static const struct fb_fix_screeninfo hecubafb_fix = { + .id = "hecubafb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_MONO01, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .line_length = DPY_W, + .accel = FB_ACCEL_NONE, +}; + +static const struct fb_var_screeninfo hecubafb_var = { + .xres = DPY_W, + .yres = DPY_H, + .xres_virtual = DPY_W, + .yres_virtual = DPY_H, + .bits_per_pixel = 1, + .nonstd = 1, +}; + +/* main hecubafb functions */ + +static void apollo_send_data(struct hecubafb_par *par, unsigned char data) +{ + /* set data */ + par->board->set_data(par, data); + + /* set DS low */ + par->board->set_ctl(par, HCB_DS_BIT, 0); + + /* wait for ack */ + par->board->wait_for_ack(par, 0); + + /* set DS hi */ + par->board->set_ctl(par, HCB_DS_BIT, 1); + + /* wait for ack to clear */ + par->board->wait_for_ack(par, 1); +} + +static void apollo_send_command(struct hecubafb_par *par, unsigned char data) +{ + /* command so set CD to high */ + par->board->set_ctl(par, HCB_CD_BIT, 1); + + /* actually strobe with command */ + apollo_send_data(par, data); + + /* clear CD back to low */ + par->board->set_ctl(par, HCB_CD_BIT, 0); +} + +static void hecubafb_dpy_update(struct hecubafb_par *par) +{ + int i; + unsigned char *buf = par->info->screen_buffer; + + apollo_send_command(par, APOLLO_START_NEW_IMG); + + for (i=0; i < (DPY_W*DPY_H/8); i++) { + apollo_send_data(par, *(buf++)); + } + + apollo_send_command(par, APOLLO_STOP_IMG_DATA); + apollo_send_command(par, APOLLO_DISPLAY_IMG); +} + +/* this is called back from the deferred io workqueue */ +static void hecubafb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist) +{ + hecubafb_dpy_update(info->par); +} + +static void hecubafb_defio_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct hecubafb_par *par = info->par; + + hecubafb_dpy_update(par); +} + +static void hecubafb_defio_damage_area(struct fb_info *info, u32 x, u32 y, + u32 width, u32 height) +{ + struct hecubafb_par *par = info->par; + + hecubafb_dpy_update(par); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(hecubafb, + hecubafb_defio_damage_range, + hecubafb_defio_damage_area) + +static const struct fb_ops hecubafb_ops = { + .owner = THIS_MODULE, + FB_DEFAULT_DEFERRED_OPS(hecubafb), +}; + +static struct fb_deferred_io hecubafb_defio = { + .delay = HZ, + .deferred_io = hecubafb_dpy_deferred_io, +}; + +static int hecubafb_probe(struct platform_device *dev) +{ + struct fb_info *info; + struct hecuba_board *board; + int retval = -ENOMEM; + int videomemorysize; + unsigned char *videomemory; + struct hecubafb_par *par; + + /* pick up board specific routines */ + board = dev->dev.platform_data; + if (!board) + return -EINVAL; + + /* try to count device specific driver, if can't, platform recalls */ + if (!try_module_get(board->owner)) + return -ENODEV; + + videomemorysize = (DPY_W*DPY_H)/8; + + videomemory = vzalloc(videomemorysize); + if (!videomemory) + goto err_videomem_alloc; + + info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev); + if (!info) + goto err_fballoc; + + info->screen_buffer = videomemory; + info->fbops = &hecubafb_ops; + + info->var = hecubafb_var; + info->fix = hecubafb_fix; + info->fix.smem_len = videomemorysize; + par = info->par; + par->info = info; + par->board = board; + par->send_command = apollo_send_command; + par->send_data = apollo_send_data; + + info->flags = FBINFO_VIRTFB; + + info->fbdefio = &hecubafb_defio; + retval = fb_deferred_io_init(info); + if (retval) + goto err_fbdefio; + + retval = register_framebuffer(info); + if (retval < 0) + goto err_fbreg; + platform_set_drvdata(dev, info); + + fb_info(info, "Hecuba frame buffer device, using %dK of video memory\n", + videomemorysize >> 10); + + /* this inits the dpy */ + retval = par->board->init(par); + if (retval < 0) + goto err_fbreg; + + return 0; +err_fbreg: + fb_deferred_io_cleanup(info); +err_fbdefio: + framebuffer_release(info); +err_fballoc: + vfree(videomemory); +err_videomem_alloc: + module_put(board->owner); + return retval; +} + +static void hecubafb_remove(struct platform_device *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + + if (info) { + struct hecubafb_par *par = info->par; + fb_deferred_io_cleanup(info); + unregister_framebuffer(info); + vfree(info->screen_buffer); + if (par->board->remove) + par->board->remove(par); + module_put(par->board->owner); + framebuffer_release(info); + } +} + +static struct platform_driver hecubafb_driver = { + .probe = hecubafb_probe, + .remove = hecubafb_remove, + .driver = { + .name = "hecubafb", + }, +}; +module_platform_driver(hecubafb_driver); + +MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller"); +MODULE_AUTHOR("Jaya Kumar"); +MODULE_LICENSE("GPL"); |
