]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/pci/cobalt/cobalt-driver.c
Merge tag 'trace-v4.10-rc2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rosted...
[mirror_ubuntu-artful-kernel.git] / drivers / media / pci / cobalt / cobalt-driver.c
CommitLineData
85756a06
HV
1/*
2 * cobalt driver initialization and card probing
3 *
4 * Derived from cx18-driver.c
5 *
6 * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
7 * All rights reserved.
8 *
9 * This program is free software; you may redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
17 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <linux/delay.h>
b5dcee22
MCC
24#include <media/i2c/adv7604.h>
25#include <media/i2c/adv7842.h>
26#include <media/i2c/adv7511.h>
85756a06
HV
27#include <media/v4l2-event.h>
28#include <media/v4l2-ctrls.h>
29
30#include "cobalt-driver.h"
31#include "cobalt-irq.h"
32#include "cobalt-i2c.h"
33#include "cobalt-v4l2.h"
34#include "cobalt-flash.h"
35#include "cobalt-alsa.h"
36#include "cobalt-omnitek.h"
37
38/* add your revision and whatnot here */
39static struct pci_device_id cobalt_pci_tbl[] = {
40 {PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_COBALT,
41 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
42 {0,}
43};
44
45MODULE_DEVICE_TABLE(pci, cobalt_pci_tbl);
46
47static atomic_t cobalt_instance = ATOMIC_INIT(0);
48
49int cobalt_debug;
50module_param_named(debug, cobalt_debug, int, 0644);
51MODULE_PARM_DESC(debug, "Debug level. Default: 0\n");
52
53int cobalt_ignore_err;
54module_param_named(ignore_err, cobalt_ignore_err, int, 0644);
55MODULE_PARM_DESC(ignore_err,
56 "If set then ignore missing i2c adapters/receivers. Default: 0\n");
57
58MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com> & Morten Hestnes");
59MODULE_DESCRIPTION("cobalt driver");
60MODULE_LICENSE("GPL");
61
62static u8 edid[256] = {
036bbb82
HV
63 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
64 0x50, 0x21, 0x32, 0x27, 0x00, 0x00, 0x00, 0x00,
65 0x22, 0x1a, 0x01, 0x03, 0x80, 0x30, 0x1b, 0x78,
66 0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
67 0x0f, 0x50, 0x54, 0x2f, 0xcf, 0x00, 0x31, 0x59,
85756a06 68 0x45, 0x59, 0x61, 0x59, 0x81, 0x99, 0x01, 0x01,
036bbb82
HV
69 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
70 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
71 0x46, 0x00, 0xe0, 0x0e, 0x11, 0x00, 0x00, 0x1e,
72 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
73 0x5e, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
74 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x63,
75 0x6f, 0x62, 0x61, 0x6c, 0x74, 0x0a, 0x20, 0x20,
76 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x10,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9c,
79
80 0x02, 0x03, 0x1f, 0xf0, 0x4a, 0x90, 0x1f, 0x04,
81 0x13, 0x22, 0x21, 0x20, 0x02, 0x11, 0x01, 0x23,
82 0x09, 0x07, 0x07, 0x68, 0x03, 0x0c, 0x00, 0x10,
83 0x00, 0x00, 0x22, 0x0f, 0xe2, 0x00, 0xea, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85756a06 87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85756a06
HV
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
036bbb82 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7,
85756a06
HV
96};
97
98static void cobalt_set_interrupt(struct cobalt *cobalt, bool enable)
99{
100 if (enable) {
101 unsigned irqs = COBALT_SYSSTAT_VI0_INT1_MSK |
102 COBALT_SYSSTAT_VI1_INT1_MSK |
103 COBALT_SYSSTAT_VI2_INT1_MSK |
104 COBALT_SYSSTAT_VI3_INT1_MSK |
105 COBALT_SYSSTAT_VI0_INT2_MSK |
106 COBALT_SYSSTAT_VI1_INT2_MSK |
107 COBALT_SYSSTAT_VI2_INT2_MSK |
108 COBALT_SYSSTAT_VI3_INT2_MSK |
109 COBALT_SYSSTAT_VI0_LOST_DATA_MSK |
110 COBALT_SYSSTAT_VI1_LOST_DATA_MSK |
111 COBALT_SYSSTAT_VI2_LOST_DATA_MSK |
112 COBALT_SYSSTAT_VI3_LOST_DATA_MSK |
113 COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK;
114
115 if (cobalt->have_hsma_rx)
116 irqs |= COBALT_SYSSTAT_VIHSMA_INT1_MSK |
117 COBALT_SYSSTAT_VIHSMA_INT2_MSK |
118 COBALT_SYSSTAT_VIHSMA_LOST_DATA_MSK;
119
120 if (cobalt->have_hsma_tx)
121 irqs |= COBALT_SYSSTAT_VOHSMA_INT1_MSK |
122 COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK |
123 COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK;
124 /* Clear any existing interrupts */
125 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_EDGE, 0xffffffff);
126 /* PIO Core interrupt mask register.
127 Enable ADV7604 INT1 interrupts */
128 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, irqs);
129 } else {
130 /* Disable all ADV7604 interrupts */
131 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, 0);
132 }
133}
134
135static unsigned cobalt_get_sd_nr(struct v4l2_subdev *sd)
136{
137 struct cobalt *cobalt = to_cobalt(sd->v4l2_dev);
138 unsigned i;
139
140 for (i = 0; i < COBALT_NUM_NODES; i++)
141 if (sd == cobalt->streams[i].sd)
142 return i;
143 cobalt_err("Invalid adv7604 subdev pointer!\n");
144 return 0;
145}
146
147static void cobalt_notify(struct v4l2_subdev *sd,
148 unsigned int notification, void *arg)
149{
150 struct cobalt *cobalt = to_cobalt(sd->v4l2_dev);
151 unsigned sd_nr = cobalt_get_sd_nr(sd);
152 struct cobalt_stream *s = &cobalt->streams[sd_nr];
153 bool hotplug = arg ? *((int *)arg) : false;
154
155 if (s->is_output)
156 return;
157
158 switch (notification) {
159 case ADV76XX_HOTPLUG:
160 cobalt_s_bit_sysctrl(cobalt,
161 COBALT_SYS_CTRL_HPD_TO_CONNECTOR_BIT(sd_nr), hotplug);
162 cobalt_dbg(1, "Set hotplug for adv %d to %d\n", sd_nr, hotplug);
163 break;
164 case V4L2_DEVICE_NOTIFY_EVENT:
165 cobalt_dbg(1, "Format changed for adv %d\n", sd_nr);
166 v4l2_event_queue(&s->vdev, arg);
167 break;
168 default:
169 break;
170 }
171}
172
173static int get_payload_size(u16 code)
174{
175 switch (code) {
176 case 0: return 128;
177 case 1: return 256;
178 case 2: return 512;
179 case 3: return 1024;
180 case 4: return 2048;
181 case 5: return 4096;
182 default: return 0;
183 }
184 return 0;
185}
186
187static const char *get_link_speed(u16 stat)
188{
189 switch (stat & PCI_EXP_LNKSTA_CLS) {
190 case 1: return "2.5 Gbit/s";
191 case 2: return "5 Gbit/s";
192 case 3: return "10 Gbit/s";
193 }
194 return "Unknown speed";
195}
196
197void cobalt_pcie_status_show(struct cobalt *cobalt)
198{
199 struct pci_dev *pci_dev = cobalt->pci_dev;
200 struct pci_dev *pci_bus_dev = cobalt->pci_dev->bus->self;
201 int offset;
202 int bus_offset;
203 u32 capa;
204 u16 stat, ctrl;
205
206 offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
207 bus_offset = pci_find_capability(pci_bus_dev, PCI_CAP_ID_EXP);
208
209 /* Device */
210 pci_read_config_dword(pci_dev, offset + PCI_EXP_DEVCAP, &capa);
211 pci_read_config_word(pci_dev, offset + PCI_EXP_DEVCTL, &ctrl);
212 pci_read_config_word(pci_dev, offset + PCI_EXP_DEVSTA, &stat);
213 cobalt_info("PCIe device capability 0x%08x: Max payload %d\n",
214 capa, get_payload_size(capa & PCI_EXP_DEVCAP_PAYLOAD));
215 cobalt_info("PCIe device control 0x%04x: Max payload %d. Max read request %d\n",
216 ctrl,
217 get_payload_size((ctrl & PCI_EXP_DEVCTL_PAYLOAD) >> 5),
218 get_payload_size((ctrl & PCI_EXP_DEVCTL_READRQ) >> 12));
219 cobalt_info("PCIe device status 0x%04x\n", stat);
220
221 /* Link */
222 pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &capa);
223 pci_read_config_word(pci_dev, offset + PCI_EXP_LNKCTL, &ctrl);
224 pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &stat);
225 cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n",
226 capa, get_link_speed(capa),
227 (capa & PCI_EXP_LNKCAP_MLW) >> 4);
228 cobalt_info("PCIe link control 0x%04x\n", ctrl);
229 cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n",
230 stat, get_link_speed(stat),
231 (stat & PCI_EXP_LNKSTA_NLW) >> 4);
232
233 /* Bus */
234 pci_read_config_dword(pci_bus_dev, bus_offset + PCI_EXP_LNKCAP, &capa);
235 cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n",
236 capa, get_link_speed(capa),
237 (capa & PCI_EXP_LNKCAP_MLW) >> 4);
238
239 /* Slot */
240 pci_read_config_dword(pci_dev, offset + PCI_EXP_SLTCAP, &capa);
241 pci_read_config_word(pci_dev, offset + PCI_EXP_SLTCTL, &ctrl);
242 pci_read_config_word(pci_dev, offset + PCI_EXP_SLTSTA, &stat);
243 cobalt_info("PCIe slot capability 0x%08x\n", capa);
244 cobalt_info("PCIe slot control 0x%04x\n", ctrl);
245 cobalt_info("PCIe slot status 0x%04x\n", stat);
246}
247
248static unsigned pcie_link_get_lanes(struct cobalt *cobalt)
249{
250 struct pci_dev *pci_dev = cobalt->pci_dev;
251 unsigned offset;
252 u16 link;
253
254 offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
255 if (!offset)
256 return 0;
257 pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &link);
258 return (link & PCI_EXP_LNKSTA_NLW) >> 4;
259}
260
261static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt)
262{
263 struct pci_dev *pci_dev = cobalt->pci_dev->bus->self;
264 unsigned offset;
265 u32 link;
266
267 offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
268 if (!offset)
269 return 0;
270 pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &link);
271 return (link & PCI_EXP_LNKCAP_MLW) >> 4;
272}
273
274static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev)
275{
276 u16 ctrl, data;
277 u32 adrs_l, adrs_h;
278
279 pci_read_config_word(pci_dev, 0x52, &ctrl);
280 cobalt_info("MSI %s\n", ctrl & 1 ? "enable" : "disable");
281 cobalt_info("MSI multiple message: Capable %u. Enable %u\n",
282 (1 << ((ctrl >> 1) & 7)), (1 << ((ctrl >> 4) & 7)));
283 if (ctrl & 0x80)
284 cobalt_info("MSI: 64-bit address capable\n");
285 pci_read_config_dword(pci_dev, 0x54, &adrs_l);
286 pci_read_config_dword(pci_dev, 0x58, &adrs_h);
287 pci_read_config_word(pci_dev, 0x5c, &data);
288 if (ctrl & 0x80)
289 cobalt_info("MSI: Address 0x%08x%08x. Data 0x%04x\n",
290 adrs_h, adrs_l, data);
291 else
292 cobalt_info("MSI: Address 0x%08x. Data 0x%04x\n",
293 adrs_l, data);
294}
295
296static void cobalt_pci_iounmap(struct cobalt *cobalt, struct pci_dev *pci_dev)
297{
298 if (cobalt->bar0) {
299 pci_iounmap(pci_dev, cobalt->bar0);
4a561c4b 300 cobalt->bar0 = NULL;
85756a06
HV
301 }
302 if (cobalt->bar1) {
303 pci_iounmap(pci_dev, cobalt->bar1);
4a561c4b 304 cobalt->bar1 = NULL;
85756a06
HV
305 }
306}
307
308static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev)
309{
310 free_irq(pci_dev->irq, (void *)cobalt);
78ccbf9f 311 pci_free_irq_vectors(pci_dev);
85756a06
HV
312}
313
314static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
315 const struct pci_device_id *pci_id)
316{
317 u32 ctrl;
318 int ret;
319
320 cobalt_dbg(1, "enabling pci device\n");
321
322 ret = pci_enable_device(pci_dev);
323 if (ret) {
324 cobalt_err("can't enable device\n");
325 return ret;
326 }
327 pci_set_master(pci_dev);
328 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cobalt->card_rev);
329 pci_read_config_word(pci_dev, PCI_DEVICE_ID, &cobalt->device_id);
330
331 switch (cobalt->device_id) {
332 case PCI_DEVICE_ID_COBALT:
333 cobalt_info("PCI Express interface from Omnitek\n");
334 break;
335 default:
336 cobalt_info("PCI Express interface provider is unknown!\n");
337 break;
338 }
339
340 if (pcie_link_get_lanes(cobalt) != 8) {
55b858b4 341 cobalt_warn("PCI Express link width is %d lanes.\n",
85756a06
HV
342 pcie_link_get_lanes(cobalt));
343 if (pcie_bus_link_get_lanes(cobalt) < 8)
55b858b4 344 cobalt_warn("The current slot only supports %d lanes, for best performance 8 are needed\n",
85756a06 345 pcie_bus_link_get_lanes(cobalt));
55b858b4 346 if (pcie_link_get_lanes(cobalt) != pcie_bus_link_get_lanes(cobalt)) {
85756a06 347 cobalt_err("The card is most likely not seated correctly in the PCIe slot\n");
55b858b4
HV
348 ret = -EIO;
349 goto err_disable;
350 }
85756a06
HV
351 }
352
353 if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) {
354 ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
355 if (ret) {
356 cobalt_err("no suitable DMA available\n");
357 goto err_disable;
358 }
359 }
360
361 ret = pci_request_regions(pci_dev, "cobalt");
362 if (ret) {
363 cobalt_err("error requesting regions\n");
364 goto err_disable;
365 }
366
367 cobalt_pcie_status_show(cobalt);
368
369 cobalt->bar0 = pci_iomap(pci_dev, 0, 0);
370 cobalt->bar1 = pci_iomap(pci_dev, 1, 0);
371 if (cobalt->bar1 == NULL) {
372 cobalt->bar1 = pci_iomap(pci_dev, 2, 0);
373 cobalt_info("64-bit BAR\n");
374 }
375 if (!cobalt->bar0 || !cobalt->bar1) {
376 ret = -EIO;
377 goto err_release;
378 }
379
380 /* Reset the video inputs before enabling any interrupts */
381 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
382 cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE, ctrl & ~0xf00);
383
384 /* Disable interrupts to prevent any spurious interrupts
385 from being generated. */
386 cobalt_set_interrupt(cobalt, false);
387
78ccbf9f 388 if (pci_alloc_irq_vectors(pci_dev, 1, 1, PCI_IRQ_MSI) < 1) {
85756a06 389 cobalt_err("Could not enable MSI\n");
85756a06
HV
390 ret = -EIO;
391 goto err_release;
392 }
393 msi_config_show(cobalt, pci_dev);
85756a06
HV
394
395 /* Register IRQ */
396 if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
397 cobalt->v4l2_dev.name, (void *)cobalt)) {
398 cobalt_err("Failed to register irq %d\n", pci_dev->irq);
399 ret = -EIO;
400 goto err_msi;
401 }
402
403 omni_sg_dma_init(cobalt);
404 return 0;
405
406err_msi:
407 pci_disable_msi(pci_dev);
408
409err_release:
410 cobalt_pci_iounmap(cobalt, pci_dev);
411 pci_release_regions(pci_dev);
412
413err_disable:
414 pci_disable_device(cobalt->pci_dev);
415 return ret;
416}
417
418static int cobalt_hdl_info_get(struct cobalt *cobalt)
419{
420 int i;
421
422 for (i = 0; i < COBALT_HDL_INFO_SIZE; i++)
423 cobalt->hdl_info[i] =
424 ioread8(cobalt->bar1 + COBALT_HDL_INFO_BASE + i);
425 cobalt->hdl_info[COBALT_HDL_INFO_SIZE - 1] = '\0';
426 if (strstr(cobalt->hdl_info, COBALT_HDL_SEARCH_STR))
427 return 0;
428
429 return 1;
430}
431
432static void cobalt_stream_struct_init(struct cobalt *cobalt)
433{
434 int i;
435
436 for (i = 0; i < COBALT_NUM_STREAMS; i++) {
437 struct cobalt_stream *s = &cobalt->streams[i];
438
439 s->cobalt = cobalt;
440 s->flags = 0;
441 s->is_audio = false;
442 s->is_output = false;
443 s->is_dummy = true;
444
445 /* The Memory DMA channels will always get a lower channel
446 * number than the FIFO DMA. Video input should map to the
447 * stream 0-3. The other can use stream struct from 4 and
448 * higher */
449 if (i <= COBALT_HSMA_IN_NODE) {
450 s->dma_channel = i + cobalt->first_fifo_channel;
451 s->video_channel = i;
86bad00a
HV
452 s->dma_fifo_mask =
453 COBALT_SYSSTAT_VI0_LOST_DATA_MSK << (4 * i);
454 s->adv_irq_mask =
455 COBALT_SYSSTAT_VI0_INT1_MSK << (4 * i);
85756a06
HV
456 } else if (i >= COBALT_AUDIO_IN_STREAM &&
457 i <= COBALT_AUDIO_IN_STREAM + 4) {
86bad00a
HV
458 unsigned idx = i - COBALT_AUDIO_IN_STREAM;
459
460 s->dma_channel = 6 + idx;
85756a06 461 s->is_audio = true;
86bad00a
HV
462 s->video_channel = idx;
463 s->dma_fifo_mask = COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK;
85756a06
HV
464 } else if (i == COBALT_HSMA_OUT_NODE) {
465 s->dma_channel = 11;
466 s->is_output = true;
467 s->video_channel = 5;
86bad00a
HV
468 s->dma_fifo_mask = COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK;
469 s->adv_irq_mask = COBALT_SYSSTAT_VOHSMA_INT1_MSK;
85756a06
HV
470 } else if (i == COBALT_AUDIO_OUT_STREAM) {
471 s->dma_channel = 12;
472 s->is_audio = true;
473 s->is_output = true;
474 s->video_channel = 5;
86bad00a 475 s->dma_fifo_mask = COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK;
85756a06
HV
476 } else {
477 /* FIXME: Memory DMA for debug purpose */
478 s->dma_channel = i - COBALT_NUM_NODES;
479 }
480 cobalt_info("stream #%d -> dma channel #%d <- video channel %d\n",
481 i, s->dma_channel, s->video_channel);
482 }
483}
484
485static int cobalt_subdevs_init(struct cobalt *cobalt)
486{
487 static struct adv76xx_platform_data adv7604_pdata = {
488 .disable_pwrdnb = 1,
489 .ain_sel = ADV7604_AIN7_8_9_NC_SYNC_3_1,
490 .bus_order = ADV7604_BUS_ORDER_BRG,
491 .blank_data = 1,
85756a06
HV
492 .op_format_mode_sel = ADV7604_OP_FORMAT_MODE0,
493 .int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH,
494 .dr_str_data = ADV76XX_DR_STR_HIGH,
495 .dr_str_clk = ADV76XX_DR_STR_HIGH,
496 .dr_str_sync = ADV76XX_DR_STR_HIGH,
497 .hdmi_free_run_mode = 1,
498 .inv_vs_pol = 1,
499 .inv_hs_pol = 1,
500 };
501 static struct i2c_board_info adv7604_info = {
502 .type = "adv7604",
503 .addr = 0x20,
504 .platform_data = &adv7604_pdata,
505 };
506
507 struct cobalt_stream *s = cobalt->streams;
508 int i;
509
510 for (i = 0; i < COBALT_NUM_INPUTS; i++) {
511 struct v4l2_subdev_format sd_fmt = {
512 .pad = ADV7604_PAD_SOURCE,
513 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
514 .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
515 };
516 struct v4l2_subdev_edid cobalt_edid = {
517 .pad = ADV76XX_PAD_HDMI_PORT_A,
518 .start_block = 0,
519 .blocks = 2,
520 .edid = edid,
521 };
522 int err;
523
524 s[i].pad_source = ADV7604_PAD_SOURCE;
525 s[i].i2c_adap = &cobalt->i2c_adap[i];
526 if (s[i].i2c_adap->dev.parent == NULL)
527 continue;
528 cobalt_s_bit_sysctrl(cobalt,
529 COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(i), 1);
530 s[i].sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
531 s[i].i2c_adap, &adv7604_info, NULL);
532 if (!s[i].sd) {
533 if (cobalt_ignore_err)
534 continue;
535 return -ENODEV;
536 }
537 err = v4l2_subdev_call(s[i].sd, video, s_routing,
538 ADV76XX_PAD_HDMI_PORT_A, 0, 0);
539 if (err)
540 return err;
541 err = v4l2_subdev_call(s[i].sd, pad, set_edid,
542 &cobalt_edid);
543 if (err)
544 return err;
545 err = v4l2_subdev_call(s[i].sd, pad, set_fmt, NULL,
546 &sd_fmt);
547 if (err)
548 return err;
549 /* Reset channel video module */
550 cobalt_s_bit_sysctrl(cobalt,
551 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 0);
552 mdelay(2);
553 cobalt_s_bit_sysctrl(cobalt,
554 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 1);
555 mdelay(1);
556 s[i].is_dummy = false;
557 cobalt->streams[i + COBALT_AUDIO_IN_STREAM].is_dummy = false;
558 }
559 return 0;
560}
561
562static int cobalt_subdevs_hsma_init(struct cobalt *cobalt)
563{
564 static struct adv7842_platform_data adv7842_pdata = {
565 .disable_pwrdnb = 1,
566 .ain_sel = ADV7842_AIN1_2_3_NC_SYNC_1_2,
567 .bus_order = ADV7842_BUS_ORDER_RBG,
568 .op_format_mode_sel = ADV7842_OP_FORMAT_MODE0,
569 .blank_data = 1,
85756a06
HV
570 .dr_str_data = 3,
571 .dr_str_clk = 3,
572 .dr_str_sync = 3,
573 .mode = ADV7842_MODE_HDMI,
574 .hdmi_free_run_enable = 1,
575 .vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P,
576 .i2c_sdp_io = 0x4a,
577 .i2c_sdp = 0x48,
578 .i2c_cp = 0x22,
579 .i2c_vdp = 0x24,
580 .i2c_afe = 0x26,
581 .i2c_hdmi = 0x34,
582 .i2c_repeater = 0x32,
583 .i2c_edid = 0x36,
584 .i2c_infoframe = 0x3e,
585 .i2c_cec = 0x40,
586 .i2c_avlink = 0x42,
587 };
588 static struct i2c_board_info adv7842_info = {
589 .type = "adv7842",
590 .addr = 0x20,
591 .platform_data = &adv7842_pdata,
592 };
593 static struct v4l2_subdev_format sd_fmt = {
594 .pad = ADV7842_PAD_SOURCE,
595 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
596 .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
597 };
598 static struct adv7511_platform_data adv7511_pdata = {
599 .i2c_edid = 0x7e >> 1,
600 .i2c_cec = 0x7c >> 1,
b4dbad8f 601 .i2c_pktmem = 0x70 >> 1,
85756a06
HV
602 .cec_clk = 12000000,
603 };
604 static struct i2c_board_info adv7511_info = {
605 .type = "adv7511",
606 .addr = 0x39, /* 0x39 or 0x3d */
607 .platform_data = &adv7511_pdata,
608 };
609 struct v4l2_subdev_edid cobalt_edid = {
610 .pad = ADV7842_EDID_PORT_A,
611 .start_block = 0,
612 .blocks = 2,
613 .edid = edid,
614 };
615 struct cobalt_stream *s = &cobalt->streams[COBALT_HSMA_IN_NODE];
616
617 s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
618 if (s->i2c_adap->dev.parent == NULL)
619 return 0;
620 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 1);
621
622 s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
623 s->i2c_adap, &adv7842_info, NULL);
624 if (s->sd) {
625 int err = v4l2_subdev_call(s->sd, pad, set_edid, &cobalt_edid);
626
627 if (err)
628 return err;
629 err = v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
630 &sd_fmt);
631 if (err)
632 return err;
633 cobalt->have_hsma_rx = true;
634 s->pad_source = ADV7842_PAD_SOURCE;
635 s->is_dummy = false;
636 cobalt->streams[4 + COBALT_AUDIO_IN_STREAM].is_dummy = false;
637 /* Reset channel video module */
638 cobalt_s_bit_sysctrl(cobalt,
639 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
640 mdelay(2);
641 cobalt_s_bit_sysctrl(cobalt,
642 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 1);
643 mdelay(1);
644 return err;
645 }
646 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 0);
647 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_PWRDN0_TO_HSMA_TX_BIT, 0);
648 s++;
649 s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
650 s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
651 s->i2c_adap, &adv7511_info, NULL);
652 if (s->sd) {
653 /* A transmitter is hooked up, so we can set this bit */
654 cobalt_s_bit_sysctrl(cobalt,
655 COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 1);
656 cobalt_s_bit_sysctrl(cobalt,
657 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
658 cobalt_s_bit_sysctrl(cobalt,
659 COBALT_SYS_CTRL_VIDEO_TX_RESETN_BIT, 1);
660 cobalt->have_hsma_tx = true;
661 v4l2_subdev_call(s->sd, core, s_power, 1);
662 v4l2_subdev_call(s->sd, video, s_stream, 1);
663 v4l2_subdev_call(s->sd, audio, s_stream, 1);
664 v4l2_ctrl_s_ctrl(v4l2_ctrl_find(s->sd->ctrl_handler,
665 V4L2_CID_DV_TX_MODE), V4L2_DV_TX_MODE_HDMI);
666 s->is_dummy = false;
667 cobalt->streams[COBALT_AUDIO_OUT_STREAM].is_dummy = false;
668 return 0;
669 }
670 return -ENODEV;
671}
672
673static int cobalt_probe(struct pci_dev *pci_dev,
674 const struct pci_device_id *pci_id)
675{
676 struct cobalt *cobalt;
677 int retval = 0;
678 int i;
679
680 /* FIXME - module parameter arrays constrain max instances */
681 i = atomic_inc_return(&cobalt_instance) - 1;
682
683 cobalt = kzalloc(sizeof(struct cobalt), GFP_ATOMIC);
684 if (cobalt == NULL)
685 return -ENOMEM;
686 cobalt->pci_dev = pci_dev;
687 cobalt->instance = i;
688
85756a06
HV
689 retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
690 if (retval) {
691 pr_err("cobalt: v4l2_device_register of card %d failed\n",
692 cobalt->instance);
85756a06
HV
693 kfree(cobalt);
694 return retval;
695 }
696 snprintf(cobalt->v4l2_dev.name, sizeof(cobalt->v4l2_dev.name),
697 "cobalt-%d", cobalt->instance);
698 cobalt->v4l2_dev.notify = cobalt_notify;
699 cobalt_info("Initializing card %d\n", cobalt->instance);
700
701 cobalt->irq_work_queues =
702 create_singlethread_workqueue(cobalt->v4l2_dev.name);
703 if (cobalt->irq_work_queues == NULL) {
704 cobalt_err("Could not create workqueue\n");
705 retval = -ENOMEM;
706 goto err;
707 }
708
709 INIT_WORK(&cobalt->irq_work_queue, cobalt_irq_work_handler);
710
711 /* PCI Device Setup */
712 retval = cobalt_setup_pci(cobalt, pci_dev, pci_id);
713 if (retval != 0)
714 goto err_wq;
715
716 /* Show HDL version info */
717 if (cobalt_hdl_info_get(cobalt))
718 cobalt_info("Not able to read the HDL info\n");
719 else
720 cobalt_info("%s", cobalt->hdl_info);
721
722 retval = cobalt_i2c_init(cobalt);
723 if (retval)
724 goto err_pci;
725
726 cobalt_stream_struct_init(cobalt);
727
728 retval = cobalt_subdevs_init(cobalt);
729 if (retval)
730 goto err_i2c;
731
732 if (!(cobalt_read_bar1(cobalt, COBALT_SYS_STAT_BASE) &
733 COBALT_SYSSTAT_HSMA_PRSNTN_MSK)) {
734 retval = cobalt_subdevs_hsma_init(cobalt);
735 if (retval)
736 goto err_i2c;
737 }
738
739 retval = v4l2_device_register_subdev_nodes(&cobalt->v4l2_dev);
740 if (retval)
741 goto err_i2c;
742 retval = cobalt_nodes_register(cobalt);
743 if (retval) {
744 cobalt_err("Error %d registering device nodes\n", retval);
745 goto err_i2c;
746 }
747 cobalt_set_interrupt(cobalt, true);
748 v4l2_device_call_all(&cobalt->v4l2_dev, 0, core,
749 interrupt_service_routine, 0, NULL);
750
751 cobalt_info("Initialized cobalt card\n");
752
753 cobalt_flash_probe(cobalt);
754
755 return 0;
756
757err_i2c:
758 cobalt_i2c_exit(cobalt);
759 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
760err_pci:
761 cobalt_free_msi(cobalt, pci_dev);
762 cobalt_pci_iounmap(cobalt, pci_dev);
763 pci_release_regions(cobalt->pci_dev);
764 pci_disable_device(cobalt->pci_dev);
765err_wq:
766 destroy_workqueue(cobalt->irq_work_queues);
767err:
768 if (retval == 0)
769 retval = -ENODEV;
770 cobalt_err("error %d on initialization\n", retval);
771
772 v4l2_device_unregister(&cobalt->v4l2_dev);
85756a06
HV
773 kfree(cobalt);
774 return retval;
775}
776
777static void cobalt_remove(struct pci_dev *pci_dev)
778{
779 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
780 struct cobalt *cobalt = to_cobalt(v4l2_dev);
781 int i;
782
783 cobalt_flash_remove(cobalt);
784 cobalt_set_interrupt(cobalt, false);
785 flush_workqueue(cobalt->irq_work_queues);
786 cobalt_nodes_unregister(cobalt);
787 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
788 struct v4l2_subdev *sd = cobalt->streams[i].sd;
789 struct i2c_client *client;
790
791 if (sd == NULL)
792 continue;
793 client = v4l2_get_subdevdata(sd);
794 v4l2_device_unregister_subdev(sd);
795 i2c_unregister_device(client);
796 }
797 cobalt_i2c_exit(cobalt);
798 cobalt_free_msi(cobalt, pci_dev);
799 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
800 cobalt_pci_iounmap(cobalt, pci_dev);
801 pci_release_regions(cobalt->pci_dev);
802 pci_disable_device(cobalt->pci_dev);
803 destroy_workqueue(cobalt->irq_work_queues);
804
805 cobalt_info("removed cobalt card\n");
806
807 v4l2_device_unregister(v4l2_dev);
85756a06
HV
808 kfree(cobalt);
809}
810
811/* define a pci_driver for card detection */
812static struct pci_driver cobalt_pci_driver = {
813 .name = "cobalt",
814 .id_table = cobalt_pci_tbl,
815 .probe = cobalt_probe,
816 .remove = cobalt_remove,
817};
818
819module_pci_driver(cobalt_pci_driver);