FILE
av7110_ir.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/av7110/av7110_ir.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Driver for the remote control of SAA7146 based AV7110 cards 4 * 5 * Copyright (C) 1999-2003 Holger Waechtler <holger@convergence.de> 6 * Copyright (C) 2003-2007 Oliver Endriss <o.endriss@gmx.de> 7 * Copyright (C) 2019 Sean Young <sean@mess.org> 8 */ 9 10#include <linux/kernel.h> 11#include <media/rc-core.h> 12 13#include "av7110.h" 14#include "av7110_hw.h" 15 16#define IR_RC5 0 17#define IR_RCMM 1 18#define IR_RC5_EXT 2 /* internal only */ 19 20/* interrupt handler */ 21void av7110_ir_handler(struct av7110 *av7110, u32 ircom) 22{ 23 struct rc_dev *rcdev = av7110->ir.rcdev; 24 enum rc_proto proto; 25 u32 command, addr, scancode; 26 u32 toggle; 27 28 dprintk(4, "ir command = %08x\n", ircom); 29 30 if (rcdev) { 31 switch (av7110->ir.ir_config) { 32 case IR_RC5: /* RC5: 5 bits device address, 6 bits command */ 33 command = ircom & 0x3f; 34 addr = (ircom >> 6) & 0x1f; 35 scancode = RC_SCANCODE_RC5(addr, command); 36 toggle = ircom & 0x0800; 37 proto = RC_PROTO_RC5; 38 break; 39 40 case IR_RCMM: /* RCMM: 32 bits scancode */ 41 scancode = ircom & ~0x8000; 42 toggle = ircom & 0x8000; 43 proto = RC_PROTO_RCMM32; 44 break; 45 46 case IR_RC5_EXT: 47 /* 48 * extended RC5: 5 bits device address, 7 bits command 49 * 50 * Extended RC5 uses only one start bit. The second 51 * start bit is re-assigned bit 6 of the command bit. 52 */ 53 command = ircom & 0x3f; 54 addr = (ircom >> 6) & 0x1f; 55 if (!(ircom & 0x1000)) 56 command |= 0x40; 57 scancode = RC_SCANCODE_RC5(addr, command); 58 toggle = ircom & 0x0800; 59 proto = RC_PROTO_RC5; 60 break; 61 default: 62 dprintk(2, "unknown ir config %d\n", av7110->ir.ir_config); 63 return; 64 } 65 66 rc_keydown(rcdev, proto, scancode, toggle != 0); 67 } 68} 69 70int av7110_set_ir_config(struct av7110 *av7110) 71{ 72 dprintk(4, "ir config = %08x\n", av7110->ir.ir_config); 73 74 return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, 75 av7110->ir.ir_config); 76} 77 78static int change_protocol(struct rc_dev *rcdev, u64 *rc_type) 79{ 80 struct av7110 *av7110 = rcdev->priv; 81 u32 ir_config; 82 83 if (*rc_type & RC_PROTO_BIT_RCMM32) { 84 ir_config = IR_RCMM; 85 *rc_type = RC_PROTO_BIT_RCMM32; 86 } else if (*rc_type & RC_PROTO_BIT_RC5) { 87 if (FW_VERSION(av7110->arm_app) >= 0x2620) 88 ir_config = IR_RC5_EXT; 89 else 90 ir_config = IR_RC5; 91 *rc_type = RC_PROTO_BIT_RC5; 92 } else { 93 return -EINVAL; 94 } 95 96 if (ir_config == av7110->ir.ir_config) 97 return 0; 98 99 av7110->ir.ir_config = ir_config; 100 101 return av7110_set_ir_config(av7110); 102} 103 104int av7110_ir_init(struct av7110 *av7110) 105{ 106 struct rc_dev *rcdev; 107 struct pci_dev *pci; 108 int ret; 109 110 rcdev = rc_allocate_device(RC_DRIVER_SCANCODE); 111 if (!rcdev) 112 return -ENOMEM; 113 114 pci = av7110->dev->pci; 115 116 snprintf(av7110->ir.input_phys, sizeof(av7110->ir.input_phys), 117 "pci-%s/ir0", pci_name(pci)); 118 119 rcdev->device_name = av7110->card_name; 120 rcdev->driver_name = KBUILD_MODNAME; 121 rcdev->input_phys = av7110->ir.input_phys; 122 rcdev->input_id.bustype = BUS_PCI; 123 rcdev->input_id.version = 2; 124 if (pci->subsystem_vendor) { 125 rcdev->input_id.vendor = pci->subsystem_vendor; 126 rcdev->input_id.product = pci->subsystem_device; 127 } else { 128 rcdev->input_id.vendor = pci->vendor; 129 rcdev->input_id.product = pci->device; 130 } 131 132 rcdev->dev.parent = &pci->dev; 133 rcdev->allowed_protocols = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RCMM32; 134 rcdev->change_protocol = change_protocol; 135 rcdev->map_name = RC_MAP_HAUPPAUGE; 136 rcdev->priv = av7110; 137 138 av7110->ir.rcdev = rcdev; 139 av7110->ir.ir_config = IR_RC5; 140 av7110_set_ir_config(av7110); 141 142 ret = rc_register_device(rcdev); 143 if (ret) { 144 av7110->ir.rcdev = NULL; 145 rc_free_device(rcdev); 146 } 147 148 return ret; 149} 150 151void av7110_ir_exit(struct av7110 *av7110) 152{ 153 rc_unregister_device(av7110->ir.rcdev); 154} 155 156//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>"); 157//MODULE_LICENSE("GPL");
~/
Read-only file preview.