diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-23 13:28:57 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-23 13:28:57 -0700 |
| commit | 4352b8aee98005853aa63f57d6377282de17a33f (patch) | |
| tree | 27614d7a9ef05c32d089004e104364ce42324837 /drivers/video/fbdev/bt431.h | |
| download | linux-stable-4352b8aee98005853aa63f57d6377282de17a33f.tar.gz linux-stable-4352b8aee98005853aa63f57d6377282de17a33f.zip | |
Merge tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linuxgrafted
Pull I3C updates from Alexandre Belloni:
"A new driver this cycle, for the AMD AXI I3C controller.
There are also new features such as IBI wakeup support, SETAASA device
discovery and ACPI support for the the DAA methods, meaning we can now
communicate with the SPD devices on DDR5 modules.
New driver:
- AMD AXI I3C master controller
Subsystem:
- I3C Common Command Code (CCC) handling improvements, especially
around GET CCCs
- SETAASA device discovery support
- ACPI support for all existing DAA methods like SETDASA, SETNEWDA as
well as I2C devices on I3C bus
- IBI-based wakeup support
Drivers:
- dw: SETAASA support
- mipi-i3c-hci: advertise IBI wakeup capability, AMD_PT I3C
controller support, PIO queue management support for HCI v1.2
- renesas: improve suspend to RAM support, add runtime PM support"
* tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (70 commits)
i3c: dw: reduce do_daa time if there's no client
i3c: mipi-i3c-hci: Add support for AMD_PT I3C controller
i3c: mipi-i3c-hci: Add PIO queue management support for HCI v1.2
i3c: mipi-i3c-hci: Fix missing STAT_IBI_STATUS_THLD in PIO mode
i3c: dw: rename "pclk" to "apb" to match dt-binding
i3c: dw: make struct dw_i3c_cmd smaller
i3c: dw: use COMMAND_PORT_TRANSFER_ARG instead of hardcoding
i3c: renesas: Don't register devices when ENTDAA times out
i3c: master: dw-i3c-master: fix OD timing for first broadcast
i3c: mipi-i3c-hci: Advertise IBI wakeup capability
i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
i3c: master: Reject IBI requests from non-IBI-capable devices
i3c: master: Add helper to query bus wakeup requirements
i3c: master: Report wakeup events for IBIs
i3c: master: Support IBI-based wakeup capability
i3c: master: Fix potential UAF in i3c_device_match()
i3c: master: Fix potential UAF in i3c_device_uevent()
i3c: Make dev->desc locking assumptions explicit
i3c: master: Fix use-after-free of master->this
...
Diffstat (limited to 'drivers/video/fbdev/bt431.h')
| -rw-r--r-- | drivers/video/fbdev/bt431.h | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/drivers/video/fbdev/bt431.h b/drivers/video/fbdev/bt431.h new file mode 100644 index 000000000..3929602f5 --- /dev/null +++ b/drivers/video/fbdev/bt431.h @@ -0,0 +1,240 @@ +/* + * linux/drivers/video/bt431.h + * + * Copyright 2003 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> + * Copyright 2016 Maciej W. Rozycki <macro@linux-mips.org> + * + * 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. + */ +#include <linux/types.h> + +#define BT431_CURSOR_SIZE 64 + +/* + * Bt431 cursor generator registers, 32-bit aligned. + * Two twin Bt431 are used on the DECstation's PMAG-AA. + */ +struct bt431_regs { + volatile u16 addr_lo; + u16 pad0; + volatile u16 addr_hi; + u16 pad1; + volatile u16 addr_cmap; + u16 pad2; + volatile u16 addr_reg; + u16 pad3; +}; + +static inline u16 bt431_set_value(u8 val) +{ + return ((val << 8) | (val & 0xff)) & 0xffff; +} + +static inline u8 bt431_get_value(u16 val) +{ + return val & 0xff; +} + +/* + * Additional registers addressed indirectly. + */ +#define BT431_REG_CMD 0x0000 +#define BT431_REG_CXLO 0x0001 +#define BT431_REG_CXHI 0x0002 +#define BT431_REG_CYLO 0x0003 +#define BT431_REG_CYHI 0x0004 +#define BT431_REG_WXLO 0x0005 +#define BT431_REG_WXHI 0x0006 +#define BT431_REG_WYLO 0x0007 +#define BT431_REG_WYHI 0x0008 +#define BT431_REG_WWLO 0x0009 +#define BT431_REG_WWHI 0x000a +#define BT431_REG_WHLO 0x000b +#define BT431_REG_WHHI 0x000c + +#define BT431_REG_CRAM_BASE 0x0000 +#define BT431_REG_CRAM_END 0x01ff + +/* + * Command register. + */ +#define BT431_CMD_CURS_ENABLE 0x40 +#define BT431_CMD_XHAIR_ENABLE 0x20 +#define BT431_CMD_OR_CURSORS 0x10 +#define BT431_CMD_XOR_CURSORS 0x00 +#define BT431_CMD_1_1_MUX 0x00 +#define BT431_CMD_4_1_MUX 0x04 +#define BT431_CMD_5_1_MUX 0x08 +#define BT431_CMD_xxx_MUX 0x0c +#define BT431_CMD_THICK_1 0x00 +#define BT431_CMD_THICK_3 0x01 +#define BT431_CMD_THICK_5 0x02 +#define BT431_CMD_THICK_7 0x03 + +static inline void bt431_select_reg(struct bt431_regs *regs, int ir) +{ + /* + * The compiler splits the write in two bytes without these + * helper variables. + */ + volatile u16 *lo = &(regs->addr_lo); + volatile u16 *hi = &(regs->addr_hi); + + mb(); + *lo = bt431_set_value(ir & 0xff); + wmb(); + *hi = bt431_set_value((ir >> 8) & 0xff); +} + +/* Autoincrement read/write. */ +static inline u8 bt431_read_reg_inc(struct bt431_regs *regs) +{ + /* + * The compiler splits the write in two bytes without the + * helper variable. + */ + volatile u16 *r = &(regs->addr_reg); + + mb(); + return bt431_get_value(*r); +} + +static inline void bt431_write_reg_inc(struct bt431_regs *regs, u8 value) +{ + /* + * The compiler splits the write in two bytes without the + * helper variable. + */ + volatile u16 *r = &(regs->addr_reg); + + mb(); + *r = bt431_set_value(value); +} + +static inline u8 bt431_read_reg(struct bt431_regs *regs, int ir) +{ + bt431_select_reg(regs, ir); + return bt431_read_reg_inc(regs); +} + +static inline void bt431_write_reg(struct bt431_regs *regs, int ir, u8 value) +{ + bt431_select_reg(regs, ir); + bt431_write_reg_inc(regs, value); +} + +/* Autoincremented read/write for the cursor map. */ +static inline u16 bt431_read_cmap_inc(struct bt431_regs *regs) +{ + /* + * The compiler splits the write in two bytes without the + * helper variable. + */ + volatile u16 *r = &(regs->addr_cmap); + + mb(); + return *r; +} + +static inline void bt431_write_cmap_inc(struct bt431_regs *regs, u16 value) +{ + /* + * The compiler splits the write in two bytes without the + * helper variable. + */ + volatile u16 *r = &(regs->addr_cmap); + + mb(); + *r = value; +} + +static inline u16 bt431_read_cmap(struct bt431_regs *regs, int cr) +{ + bt431_select_reg(regs, cr); + return bt431_read_cmap_inc(regs); +} + +static inline void bt431_write_cmap(struct bt431_regs *regs, int cr, u16 value) +{ + bt431_select_reg(regs, cr); + bt431_write_cmap_inc(regs, value); +} + +static inline void bt431_enable_cursor(struct bt431_regs *regs) +{ + bt431_write_reg(regs, BT431_REG_CMD, + BT431_CMD_CURS_ENABLE | BT431_CMD_OR_CURSORS + | BT431_CMD_4_1_MUX | BT431_CMD_THICK_1); +} + +static inline void bt431_erase_cursor(struct bt431_regs *regs) +{ + bt431_write_reg(regs, BT431_REG_CMD, BT431_CMD_4_1_MUX); +} + +static inline void bt431_position_cursor(struct bt431_regs *regs, u16 x, u16 y) +{ + /* + * Magic from the MACH sources. + * + * Cx = x + D + H - P + * P = 37 if 1:1, 52 if 4:1, 57 if 5:1 + * D = pixel skew between outdata and external data + * H = pixels between HSYNCH falling and active video + * + * Cy = y + V - 32 + * V = scanlines between HSYNCH falling, two or more + * clocks after VSYNCH falling, and active video + */ + x += 412 - 52; + y += 68 - 32; + + /* Use autoincrement. */ + bt431_select_reg(regs, BT431_REG_CXLO); + bt431_write_reg_inc(regs, x & 0xff); /* BT431_REG_CXLO */ + bt431_write_reg_inc(regs, (x >> 8) & 0x0f); /* BT431_REG_CXHI */ + bt431_write_reg_inc(regs, y & 0xff); /* BT431_REG_CYLO */ + bt431_write_reg_inc(regs, (y >> 8) & 0x0f); /* BT431_REG_CYHI */ +} + +static inline void bt431_set_cursor(struct bt431_regs *regs, + const char *data, const char *mask, + u16 rop, u16 width, u16 height) +{ + u16 x, y; + int i; + + i = 0; + width = DIV_ROUND_UP(width, 8); + bt431_select_reg(regs, BT431_REG_CRAM_BASE); + for (y = 0; y < BT431_CURSOR_SIZE; y++) + for (x = 0; x < BT431_CURSOR_SIZE / 8; x++) { + u16 val = 0; + + if (y < height && x < width) { + val = mask[i]; + if (rop == ROP_XOR) + val = (val << 8) | (val ^ data[i]); + else + val = (val << 8) | (val & data[i]); + i++; + } + bt431_write_cmap_inc(regs, val); + } +} + +static inline void bt431_init_cursor(struct bt431_regs *regs) +{ + /* no crosshair window */ + bt431_select_reg(regs, BT431_REG_WXLO); + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXLO */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXHI */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYLO */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYHI */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWLO */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWHI */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHLO */ + bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHHI */ +} |
