diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/cx23885/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-cards.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-core.c | 20 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-ioctl.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885.h | 8 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23888-ir.c | 233 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23888-ir.h | 28 |
7 files changed, 310 insertions, 3 deletions
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 93a954c23f42..3832a1cb768d 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ | 1 | cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ |
2 | cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ | 2 | cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ |
3 | cx23885-ioctl.o \ | 3 | cx23885-ioctl.o cx23888-ir.o \ |
4 | netup-init.o cimax2.o netup-eeprom.o | 4 | netup-init.o cimax2.o netup-eeprom.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o | 6 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index bfdf79f1033c..4b5aa08036fa 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "cx23885.h" | 28 | #include "cx23885.h" |
29 | #include "tuner-xc2028.h" | 29 | #include "tuner-xc2028.h" |
30 | #include "netup-init.h" | 30 | #include "netup-init.h" |
31 | #include "cx23888-ir.h" | ||
31 | 32 | ||
32 | /* ------------------------------------------------------------------ */ | 33 | /* ------------------------------------------------------------------ */ |
33 | /* board config info */ | 34 | /* board config info */ |
@@ -801,6 +802,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
801 | 802 | ||
802 | int cx23885_ir_init(struct cx23885_dev *dev) | 803 | int cx23885_ir_init(struct cx23885_dev *dev) |
803 | { | 804 | { |
805 | int ret = 0; | ||
804 | switch (dev->board) { | 806 | switch (dev->board) { |
805 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | 807 | case CX23885_BOARD_HAUPPAUGE_HVR1250: |
806 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 808 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
@@ -812,15 +814,20 @@ int cx23885_ir_init(struct cx23885_dev *dev) | |||
812 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | 814 | case CX23885_BOARD_HAUPPAUGE_HVR1275: |
813 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 815 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
814 | case CX23885_BOARD_HAUPPAUGE_HVR1210: | 816 | case CX23885_BOARD_HAUPPAUGE_HVR1210: |
815 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
816 | /* FIXME: Implement me */ | 817 | /* FIXME: Implement me */ |
817 | break; | 818 | break; |
819 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
820 | ret = cx23888_ir_probe(dev); | ||
821 | if (ret) | ||
822 | break; | ||
823 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); | ||
824 | break; | ||
818 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | 825 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: |
819 | request_module("ir-kbd-i2c"); | 826 | request_module("ir-kbd-i2c"); |
820 | break; | 827 | break; |
821 | } | 828 | } |
822 | 829 | ||
823 | return 0; | 830 | return ret; |
824 | } | 831 | } |
825 | 832 | ||
826 | void cx23885_card_setup(struct cx23885_dev *dev) | 833 | void cx23885_card_setup(struct cx23885_dev *dev) |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index c31284ba19dd..73be16b0d2a0 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include "cx23885.h" | 33 | #include "cx23885.h" |
34 | #include "cimax2.h" | 34 | #include "cimax2.h" |
35 | #include "cx23888-ir.h" | ||
35 | 36 | ||
36 | MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); | 37 | MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); |
37 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 38 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
@@ -753,6 +754,23 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) | |||
753 | __func__, dev->hwrevision); | 754 | __func__, dev->hwrevision); |
754 | } | 755 | } |
755 | 756 | ||
757 | /* Find the first v4l2_subdev member of the group id in hw */ | ||
758 | struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw) | ||
759 | { | ||
760 | struct v4l2_subdev *result = NULL; | ||
761 | struct v4l2_subdev *sd; | ||
762 | |||
763 | spin_lock(&dev->v4l2_dev.lock); | ||
764 | v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) { | ||
765 | if (sd->grp_id == hw) { | ||
766 | result = sd; | ||
767 | break; | ||
768 | } | ||
769 | } | ||
770 | spin_unlock(&dev->v4l2_dev.lock); | ||
771 | return result; | ||
772 | } | ||
773 | |||
756 | static int cx23885_dev_setup(struct cx23885_dev *dev) | 774 | static int cx23885_dev_setup(struct cx23885_dev *dev) |
757 | { | 775 | { |
758 | int i; | 776 | int i; |
@@ -1914,6 +1932,8 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) | |||
1914 | 1932 | ||
1915 | cx23885_shutdown(dev); | 1933 | cx23885_shutdown(dev); |
1916 | 1934 | ||
1935 | cx23888_ir_remove(dev); | ||
1936 | |||
1917 | pci_disable_device(pci_dev); | 1937 | pci_disable_device(pci_dev); |
1918 | 1938 | ||
1919 | /* unregister stuff */ | 1939 | /* unregister stuff */ |
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c index 3a497b6c4fd7..dfb4627fb340 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.c +++ b/drivers/media/video/cx23885/cx23885-ioctl.c | |||
@@ -65,6 +65,17 @@ int cx23885_g_chip_ident(struct file *file, void *fh, | |||
65 | chip->revision = 0; | 65 | chip->revision = 0; |
66 | } | 66 | } |
67 | break; | 67 | break; |
68 | case 2: | ||
69 | /* | ||
70 | * The integrated IR controller on the CX23888 is | ||
71 | * host chip 2. It may not be used/initialized or sd_ir | ||
72 | * may be pointing at the cx25840 subdevice for the | ||
73 | * IR controller on the CX23885. Thus we find it | ||
74 | * without using the dev->sd_ir pointer. | ||
75 | */ | ||
76 | call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident, | ||
77 | chip); | ||
78 | break; | ||
68 | default: | 79 | default: |
69 | err = -EINVAL; /* per V4L2 spec */ | 80 | err = -EINVAL; /* per V4L2 spec */ |
70 | break; | 81 | break; |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index f4c4108f23f3..f7ed146566d9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -355,6 +355,7 @@ struct cx23885_dev { | |||
355 | unsigned char radio_addr; | 355 | unsigned char radio_addr; |
356 | unsigned int has_radio; | 356 | unsigned int has_radio; |
357 | struct v4l2_subdev *sd_cx25840; | 357 | struct v4l2_subdev *sd_cx25840; |
358 | struct v4l2_subdev *sd_ir; | ||
358 | 359 | ||
359 | /* V4l */ | 360 | /* V4l */ |
360 | u32 freq; | 361 | u32 freq; |
@@ -383,6 +384,13 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) | |||
383 | #define call_all(dev, o, f, args...) \ | 384 | #define call_all(dev, o, f, args...) \ |
384 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) | 385 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) |
385 | 386 | ||
387 | #define CX23885_HW_888_IR (1 << 0) | ||
388 | |||
389 | #define call_hw(dev, grpid, o, f, args...) \ | ||
390 | v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args) | ||
391 | |||
392 | extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); | ||
393 | |||
386 | extern struct list_head cx23885_devlist; | 394 | extern struct list_head cx23885_devlist; |
387 | 395 | ||
388 | #define SRAM_CH01 0 /* Video A */ | 396 | #define SRAM_CH01 0 /* Video A */ |
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c new file mode 100644 index 000000000000..12df0e3a2354 --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * CX23888 Integrated Consumer Infrared Controller | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #include <media/v4l2-device.h> | ||
25 | #include <media/v4l2-chip-ident.h> | ||
26 | |||
27 | #include "cx23885.h" | ||
28 | |||
29 | #define CX23888_IR_REG_BASE 0x170000 | ||
30 | /* | ||
31 | * These CX23888 register offsets have a straightforward one to one mapping | ||
32 | * to the CX23885 register offsets of 0x200 through 0x218 | ||
33 | */ | ||
34 | #define CX23888_IR_CNTRL_REG 0x170000 | ||
35 | #define CX23888_IR_TXCLK_REG 0x170004 | ||
36 | #define CX23888_IR_RXCLK_REG 0x170008 | ||
37 | #define CX23888_IR_CDUTY_REG 0x17000C | ||
38 | #define CX23888_IR_STATS_REG 0x170010 | ||
39 | #define CX23888_IR_IRQEN_REG 0x170014 | ||
40 | #define CX23888_IR_FILTR_REG 0x170018 | ||
41 | /* This register doesn't follow the pattern; it's 0x23C on a CX23885 */ | ||
42 | #define CX23888_IR_FIFO_REG 0x170040 | ||
43 | |||
44 | /* CX23888 unique registers */ | ||
45 | #define CX23888_IR_SEEDP_REG 0x17001C | ||
46 | #define CX23888_IR_TIMOL_REG 0x170020 | ||
47 | #define CX23888_IR_WAKE0_REG 0x170024 | ||
48 | #define CX23888_IR_WAKE1_REG 0x170028 | ||
49 | #define CX23888_IR_WAKE2_REG 0x17002C | ||
50 | #define CX23888_IR_MASK0_REG 0x170030 | ||
51 | #define CX23888_IR_MASK1_REG 0x170034 | ||
52 | #define CX23888_IR_MAKS2_REG 0x170038 | ||
53 | #define CX23888_IR_DPIPG_REG 0x17003C | ||
54 | #define CX23888_IR_LEARN_REG 0x170044 | ||
55 | |||
56 | |||
57 | struct cx23888_ir_state { | ||
58 | struct v4l2_subdev sd; | ||
59 | struct cx23885_dev *dev; | ||
60 | u32 id; | ||
61 | u32 rev; | ||
62 | }; | ||
63 | |||
64 | static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) | ||
65 | { | ||
66 | return v4l2_get_subdevdata(sd); | ||
67 | } | ||
68 | |||
69 | static int cx23888_ir_write(struct cx23885_dev *dev, u32 addr, u8 value) | ||
70 | { | ||
71 | u32 reg = (addr & ~3); | ||
72 | int shift = (addr & 3) * 8; | ||
73 | u32 x = cx_read(reg); | ||
74 | |||
75 | x = (x & ~(0xff << shift)) | ((u32)value << shift); | ||
76 | cx_write(reg, x); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static | ||
81 | inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) | ||
82 | { | ||
83 | cx_write(addr, value); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static u8 cx23888_ir_read(struct cx23885_dev *dev, u32 addr) | ||
88 | { | ||
89 | u32 x = cx_read((addr & ~3)); | ||
90 | int shift = (addr & 3) * 8; | ||
91 | |||
92 | return (x >> shift) & 0xff; | ||
93 | } | ||
94 | |||
95 | static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr) | ||
96 | { | ||
97 | return cx_read(addr); | ||
98 | } | ||
99 | |||
100 | static int cx23888_ir_and_or(struct cx23885_dev *dev, u32 addr, | ||
101 | unsigned and_mask, u8 or_value) | ||
102 | { | ||
103 | return cx23888_ir_write(dev, addr, | ||
104 | (cx23888_ir_read(dev, addr) & and_mask) | | ||
105 | or_value); | ||
106 | } | ||
107 | |||
108 | static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, | ||
109 | u32 and_mask, u32 or_value) | ||
110 | { | ||
111 | cx_andor(addr, and_mask, or_value); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int cx23888_ir_log_status(struct v4l2_subdev *sd) | ||
116 | { | ||
117 | struct cx23888_ir_state *state = to_state(sd); | ||
118 | struct cx23885_dev *dev = state->dev; | ||
119 | u8 cntrl = cx23888_ir_read(dev, CX23888_IR_CNTRL_REG+1); | ||
120 | v4l2_info(sd, "receiver %sabled\n", cntrl & 0x1 ? "en" : "dis"); | ||
121 | v4l2_info(sd, "transmitter %sabled\n", cntrl & 0x2 ? "en" : "dis"); | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match) | ||
126 | { | ||
127 | return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2; | ||
128 | } | ||
129 | |||
130 | static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd, | ||
131 | struct v4l2_dbg_chip_ident *chip) | ||
132 | { | ||
133 | struct cx23888_ir_state *state = to_state(sd); | ||
134 | |||
135 | if (cx23888_ir_dbg_match(&chip->match)) { | ||
136 | chip->ident = state->id; | ||
137 | chip->revision = state->rev; | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
143 | static int cx23888_ir_g_register(struct v4l2_subdev *sd, | ||
144 | struct v4l2_dbg_register *reg) | ||
145 | { | ||
146 | struct cx23888_ir_state *state = to_state(sd); | ||
147 | u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; | ||
148 | |||
149 | if (!cx23888_ir_dbg_match(®->match)) | ||
150 | return -EINVAL; | ||
151 | if ((addr & 0x3) != 0) | ||
152 | return -EINVAL; | ||
153 | if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) | ||
154 | return -EINVAL; | ||
155 | if (!capable(CAP_SYS_ADMIN)) | ||
156 | return -EPERM; | ||
157 | reg->size = 4; | ||
158 | reg->val = cx23888_ir_read4(state->dev, addr); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int cx23888_ir_s_register(struct v4l2_subdev *sd, | ||
163 | struct v4l2_dbg_register *reg) | ||
164 | { | ||
165 | struct cx23888_ir_state *state = to_state(sd); | ||
166 | u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; | ||
167 | |||
168 | if (!cx23888_ir_dbg_match(®->match)) | ||
169 | return -EINVAL; | ||
170 | if ((addr & 0x3) != 0) | ||
171 | return -EINVAL; | ||
172 | if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) | ||
173 | return -EINVAL; | ||
174 | if (!capable(CAP_SYS_ADMIN)) | ||
175 | return -EPERM; | ||
176 | cx23888_ir_write4(state->dev, addr, reg->val); | ||
177 | return 0; | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { | ||
182 | .g_chip_ident = cx23888_ir_g_chip_ident, | ||
183 | .log_status = cx23888_ir_log_status, | ||
184 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
185 | .g_register = cx23888_ir_g_register, | ||
186 | .s_register = cx23888_ir_s_register, | ||
187 | #endif | ||
188 | }; | ||
189 | |||
190 | static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { | ||
191 | .core = &cx23888_ir_core_ops, | ||
192 | }; | ||
193 | |||
194 | int cx23888_ir_probe(struct cx23885_dev *dev) | ||
195 | { | ||
196 | struct cx23888_ir_state *state; | ||
197 | struct v4l2_subdev *sd; | ||
198 | |||
199 | state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL); | ||
200 | if (state == NULL) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | state->dev = dev; | ||
204 | state->id = V4L2_IDENT_CX23888_IR; | ||
205 | state->rev = 0; | ||
206 | sd = &state->sd; | ||
207 | |||
208 | v4l2_subdev_init(sd, &cx23888_ir_controller_ops); | ||
209 | v4l2_set_subdevdata(sd, state); | ||
210 | /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */ | ||
211 | snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name); | ||
212 | sd->grp_id = CX23885_HW_888_IR; | ||
213 | return v4l2_device_register_subdev(&dev->v4l2_dev, sd); | ||
214 | } | ||
215 | |||
216 | int cx23888_ir_remove(struct cx23885_dev *dev) | ||
217 | { | ||
218 | struct v4l2_subdev *sd; | ||
219 | struct cx23888_ir_state *state; | ||
220 | |||
221 | sd = cx23885_find_hw(dev, CX23885_HW_888_IR); | ||
222 | if (sd == NULL) | ||
223 | return -ENODEV; | ||
224 | |||
225 | /* Disable receiver and transmitter */ | ||
226 | cx23888_ir_and_or(dev, CX23888_IR_CNTRL_REG+1, 0xfc, 0); | ||
227 | |||
228 | state = to_state(sd); | ||
229 | v4l2_device_unregister_subdev(sd); | ||
230 | kfree(state); | ||
231 | /* Nothing more to free() as state held the actual v4l2_subdev object */ | ||
232 | return 0; | ||
233 | } | ||
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h new file mode 100644 index 000000000000..3d446f9eb94b --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * CX23888 Integrated Consumer Infrared Controller | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef _CX23888_IR_H_ | ||
25 | #define _CX23888_IR_H_ | ||
26 | int cx23888_ir_probe(struct cx23885_dev *dev); | ||
27 | int cx23888_ir_remove(struct cx23885_dev *dev); | ||
28 | #endif | ||