Merge remote-tracking branch 'iommu/next'
[deliverable/linux.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);
311
312 if (cobalt->msi_enabled)
313 pci_disable_msi(pci_dev);
314}
315
316static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
317 const struct pci_device_id *pci_id)
318{
319 u32 ctrl;
320 int ret;
321
322 cobalt_dbg(1, "enabling pci device\n");
323
324 ret = pci_enable_device(pci_dev);
325 if (ret) {
326 cobalt_err("can't enable device\n");
327 return ret;
328 }
329 pci_set_master(pci_dev);
330 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cobalt->card_rev);
331 pci_read_config_word(pci_dev, PCI_DEVICE_ID, &cobalt->device_id);
332
333 switch (cobalt->device_id) {
334 case PCI_DEVICE_ID_COBALT:
335 cobalt_info("PCI Express interface from Omnitek\n");
336 break;
337 default:
338 cobalt_info("PCI Express interface provider is unknown!\n");
339 break;
340 }
341
342 if (pcie_link_get_lanes(cobalt) != 8) {
55b858b4 343 cobalt_warn("PCI Express link width is %d lanes.\n",
85756a06
HV
344 pcie_link_get_lanes(cobalt));
345 if (pcie_bus_link_get_lanes(cobalt) < 8)
55b858b4 346 cobalt_warn("The current slot only supports %d lanes, for best performance 8 are needed\n",
85756a06 347 pcie_bus_link_get_lanes(cobalt));
55b858b4 348 if (pcie_link_get_lanes(cobalt) != pcie_bus_link_get_lanes(cobalt)) {
85756a06 349 cobalt_err("The card is most likely not seated correctly in the PCIe slot\n");
55b858b4
HV
350 ret = -EIO;
351 goto err_disable;
352 }
85756a06
HV
353 }
354
355 if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) {
356 ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
357 if (ret) {
358 cobalt_err("no suitable DMA available\n");
359 goto err_disable;
360 }
361 }
362
363 ret = pci_request_regions(pci_dev, "cobalt");
364 if (ret) {
365 cobalt_err("error requesting regions\n");
366 goto err_disable;
367 }
368
369 cobalt_pcie_status_show(cobalt);
370
371 cobalt->bar0 = pci_iomap(pci_dev, 0, 0);
372 cobalt->bar1 = pci_iomap(pci_dev, 1, 0);
373 if (cobalt->bar1 == NULL) {
374 cobalt->bar1 = pci_iomap(pci_dev, 2, 0);
375 cobalt_info("64-bit BAR\n");
376 }
377 if (!cobalt->bar0 || !cobalt->bar1) {
378 ret = -EIO;
379 goto err_release;
380 }
381
382 /* Reset the video inputs before enabling any interrupts */
383 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
384 cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE, ctrl & ~0xf00);
385
386 /* Disable interrupts to prevent any spurious interrupts
387 from being generated. */
388 cobalt_set_interrupt(cobalt, false);
389
390 if (pci_enable_msi_range(pci_dev, 1, 1) < 1) {
391 cobalt_err("Could not enable MSI\n");
392 cobalt->msi_enabled = false;
393 ret = -EIO;
394 goto err_release;
395 }
396 msi_config_show(cobalt, pci_dev);
397 cobalt->msi_enabled = true;
398
399 /* Register IRQ */
400 if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
401 cobalt->v4l2_dev.name, (void *)cobalt)) {
402 cobalt_err("Failed to register irq %d\n", pci_dev->irq);
403 ret = -EIO;
404 goto err_msi;
405 }
406
407 omni_sg_dma_init(cobalt);
408 return 0;
409
410err_msi:
411 pci_disable_msi(pci_dev);
412
413err_release:
414 cobalt_pci_iounmap(cobalt, pci_dev);
415 pci_release_regions(pci_dev);
416
417err_disable:
418 pci_disable_device(cobalt->pci_dev);
419 return ret;
420}
421
422static int cobalt_hdl_info_get(struct cobalt *cobalt)
423{
424 int i;
425
426 for (i = 0; i < COBALT_HDL_INFO_SIZE; i++)
427 cobalt->hdl_info[i] =
428 ioread8(cobalt->bar1 + COBALT_HDL_INFO_BASE + i);
429 cobalt->hdl_info[COBALT_HDL_INFO_SIZE - 1] = '\0';
430 if (strstr(cobalt->hdl_info, COBALT_HDL_SEARCH_STR))
431 return 0;
432
433 return 1;
434}
435
436static void cobalt_stream_struct_init(struct cobalt *cobalt)
437{
438 int i;
439
440 for (i = 0; i < COBALT_NUM_STREAMS; i++) {
441 struct cobalt_stream *s = &cobalt->streams[i];
442
443 s->cobalt = cobalt;
444 s->flags = 0;
445 s->is_audio = false;
446 s->is_output = false;
447 s->is_dummy = true;
448
449 /* The Memory DMA channels will always get a lower channel
450 * number than the FIFO DMA. Video input should map to the
451 * stream 0-3. The other can use stream struct from 4 and
452 * higher */
453 if (i <= COBALT_HSMA_IN_NODE) {
454 s->dma_channel = i + cobalt->first_fifo_channel;
455 s->video_channel = i;
86bad00a
HV
456 s->dma_fifo_mask =
457 COBALT_SYSSTAT_VI0_LOST_DATA_MSK << (4 * i);
458 s->adv_irq_mask =
459 COBALT_SYSSTAT_VI0_INT1_MSK << (4 * i);
85756a06
HV
460 } else if (i >= COBALT_AUDIO_IN_STREAM &&
461 i <= COBALT_AUDIO_IN_STREAM + 4) {
86bad00a
HV
462 unsigned idx = i - COBALT_AUDIO_IN_STREAM;
463
464 s->dma_channel = 6 + idx;
85756a06 465 s->is_audio = true;
86bad00a
HV
466 s->video_channel = idx;
467 s->dma_fifo_mask = COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK;
85756a06
HV
468 } else if (i == COBALT_HSMA_OUT_NODE) {
469 s->dma_channel = 11;
470 s->is_output = true;
471 s->video_channel = 5;
86bad00a
HV
472 s->dma_fifo_mask = COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK;
473 s->adv_irq_mask = COBALT_SYSSTAT_VOHSMA_INT1_MSK;
85756a06
HV
474 } else if (i == COBALT_AUDIO_OUT_STREAM) {
475 s->dma_channel = 12;
476 s->is_audio = true;
477 s->is_output = true;
478 s->video_channel = 5;
86bad00a 479 s->dma_fifo_mask = COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK;
85756a06
HV
480 } else {
481 /* FIXME: Memory DMA for debug purpose */
482 s->dma_channel = i - COBALT_NUM_NODES;
483 }
484 cobalt_info("stream #%d -> dma channel #%d <- video channel %d\n",
485 i, s->dma_channel, s->video_channel);
486 }
487}
488
489static int cobalt_subdevs_init(struct cobalt *cobalt)
490{
491 static struct adv76xx_platform_data adv7604_pdata = {
492 .disable_pwrdnb = 1,
493 .ain_sel = ADV7604_AIN7_8_9_NC_SYNC_3_1,
494 .bus_order = ADV7604_BUS_ORDER_BRG,
495 .blank_data = 1,
85756a06
HV
496 .op_format_mode_sel = ADV7604_OP_FORMAT_MODE0,
497 .int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH,
498 .dr_str_data = ADV76XX_DR_STR_HIGH,
499 .dr_str_clk = ADV76XX_DR_STR_HIGH,
500 .dr_str_sync = ADV76XX_DR_STR_HIGH,
501 .hdmi_free_run_mode = 1,
502 .inv_vs_pol = 1,
503 .inv_hs_pol = 1,
504 };
505 static struct i2c_board_info adv7604_info = {
506 .type = "adv7604",
507 .addr = 0x20,
508 .platform_data = &adv7604_pdata,
509 };
510
511 struct cobalt_stream *s = cobalt->streams;
512 int i;
513
514 for (i = 0; i < COBALT_NUM_INPUTS; i++) {
515 struct v4l2_subdev_format sd_fmt = {
516 .pad = ADV7604_PAD_SOURCE,
517 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
518 .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
519 };
520 struct v4l2_subdev_edid cobalt_edid = {
521 .pad = ADV76XX_PAD_HDMI_PORT_A,
522 .start_block = 0,
523 .blocks = 2,
524 .edid = edid,
525 };
526 int err;
527
528 s[i].pad_source = ADV7604_PAD_SOURCE;
529 s[i].i2c_adap = &cobalt->i2c_adap[i];
530 if (s[i].i2c_adap->dev.parent == NULL)
531 continue;
532 cobalt_s_bit_sysctrl(cobalt,
533 COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(i), 1);
534 s[i].sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
535 s[i].i2c_adap, &adv7604_info, NULL);
536 if (!s[i].sd) {
537 if (cobalt_ignore_err)
538 continue;
539 return -ENODEV;
540 }
541 err = v4l2_subdev_call(s[i].sd, video, s_routing,
542 ADV76XX_PAD_HDMI_PORT_A, 0, 0);
543 if (err)
544 return err;
545 err = v4l2_subdev_call(s[i].sd, pad, set_edid,
546 &cobalt_edid);
547 if (err)
548 return err;
549 err = v4l2_subdev_call(s[i].sd, pad, set_fmt, NULL,
550 &sd_fmt);
551 if (err)
552 return err;
553 /* Reset channel video module */
554 cobalt_s_bit_sysctrl(cobalt,
555 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 0);
556 mdelay(2);
557 cobalt_s_bit_sysctrl(cobalt,
558 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 1);
559 mdelay(1);
560 s[i].is_dummy = false;
561 cobalt->streams[i + COBALT_AUDIO_IN_STREAM].is_dummy = false;
562 }
563 return 0;
564}
565
566static int cobalt_subdevs_hsma_init(struct cobalt *cobalt)
567{
568 static struct adv7842_platform_data adv7842_pdata = {
569 .disable_pwrdnb = 1,
570 .ain_sel = ADV7842_AIN1_2_3_NC_SYNC_1_2,
571 .bus_order = ADV7842_BUS_ORDER_RBG,
572 .op_format_mode_sel = ADV7842_OP_FORMAT_MODE0,
573 .blank_data = 1,
85756a06
HV
574 .dr_str_data = 3,
575 .dr_str_clk = 3,
576 .dr_str_sync = 3,
577 .mode = ADV7842_MODE_HDMI,
578 .hdmi_free_run_enable = 1,
579 .vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P,
580 .i2c_sdp_io = 0x4a,
581 .i2c_sdp = 0x48,
582 .i2c_cp = 0x22,
583 .i2c_vdp = 0x24,
584 .i2c_afe = 0x26,
585 .i2c_hdmi = 0x34,
586 .i2c_repeater = 0x32,
587 .i2c_edid = 0x36,
588 .i2c_infoframe = 0x3e,
589 .i2c_cec = 0x40,
590 .i2c_avlink = 0x42,
591 };
592 static struct i2c_board_info adv7842_info = {
593 .type = "adv7842",
594 .addr = 0x20,
595 .platform_data = &adv7842_pdata,
596 };
597 static struct v4l2_subdev_format sd_fmt = {
598 .pad = ADV7842_PAD_SOURCE,
599 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
600 .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
601 };
602 static struct adv7511_platform_data adv7511_pdata = {
603 .i2c_edid = 0x7e >> 1,
604 .i2c_cec = 0x7c >> 1,
b4dbad8f 605 .i2c_pktmem = 0x70 >> 1,
85756a06
HV
606 .cec_clk = 12000000,
607 };
608 static struct i2c_board_info adv7511_info = {
609 .type = "adv7511",
610 .addr = 0x39, /* 0x39 or 0x3d */
611 .platform_data = &adv7511_pdata,
612 };
613 struct v4l2_subdev_edid cobalt_edid = {
614 .pad = ADV7842_EDID_PORT_A,
615 .start_block = 0,
616 .blocks = 2,
617 .edid = edid,
618 };
619 struct cobalt_stream *s = &cobalt->streams[COBALT_HSMA_IN_NODE];
620
621 s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
622 if (s->i2c_adap->dev.parent == NULL)
623 return 0;
624 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 1);
625
626 s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
627 s->i2c_adap, &adv7842_info, NULL);
628 if (s->sd) {
629 int err = v4l2_subdev_call(s->sd, pad, set_edid, &cobalt_edid);
630
631 if (err)
632 return err;
633 err = v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
634 &sd_fmt);
635 if (err)
636 return err;
637 cobalt->have_hsma_rx = true;
638 s->pad_source = ADV7842_PAD_SOURCE;
639 s->is_dummy = false;
640 cobalt->streams[4 + COBALT_AUDIO_IN_STREAM].is_dummy = false;
641 /* Reset channel video module */
642 cobalt_s_bit_sysctrl(cobalt,
643 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
644 mdelay(2);
645 cobalt_s_bit_sysctrl(cobalt,
646 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 1);
647 mdelay(1);
648 return err;
649 }
650 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 0);
651 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_PWRDN0_TO_HSMA_TX_BIT, 0);
652 s++;
653 s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
654 s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
655 s->i2c_adap, &adv7511_info, NULL);
656 if (s->sd) {
657 /* A transmitter is hooked up, so we can set this bit */
658 cobalt_s_bit_sysctrl(cobalt,
659 COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 1);
660 cobalt_s_bit_sysctrl(cobalt,
661 COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
662 cobalt_s_bit_sysctrl(cobalt,
663 COBALT_SYS_CTRL_VIDEO_TX_RESETN_BIT, 1);
664 cobalt->have_hsma_tx = true;
665 v4l2_subdev_call(s->sd, core, s_power, 1);
666 v4l2_subdev_call(s->sd, video, s_stream, 1);
667 v4l2_subdev_call(s->sd, audio, s_stream, 1);
668 v4l2_ctrl_s_ctrl(v4l2_ctrl_find(s->sd->ctrl_handler,
669 V4L2_CID_DV_TX_MODE), V4L2_DV_TX_MODE_HDMI);
670 s->is_dummy = false;
671 cobalt->streams[COBALT_AUDIO_OUT_STREAM].is_dummy = false;
672 return 0;
673 }
674 return -ENODEV;
675}
676
677static int cobalt_probe(struct pci_dev *pci_dev,
678 const struct pci_device_id *pci_id)
679{
680 struct cobalt *cobalt;
681 int retval = 0;
682 int i;
683
684 /* FIXME - module parameter arrays constrain max instances */
685 i = atomic_inc_return(&cobalt_instance) - 1;
686
687 cobalt = kzalloc(sizeof(struct cobalt), GFP_ATOMIC);
688 if (cobalt == NULL)
689 return -ENOMEM;
690 cobalt->pci_dev = pci_dev;
691 cobalt->instance = i;
692
85756a06
HV
693 retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
694 if (retval) {
695 pr_err("cobalt: v4l2_device_register of card %d failed\n",
696 cobalt->instance);
85756a06
HV
697 kfree(cobalt);
698 return retval;
699 }
700 snprintf(cobalt->v4l2_dev.name, sizeof(cobalt->v4l2_dev.name),
701 "cobalt-%d", cobalt->instance);
702 cobalt->v4l2_dev.notify = cobalt_notify;
703 cobalt_info("Initializing card %d\n", cobalt->instance);
704
705 cobalt->irq_work_queues =
706 create_singlethread_workqueue(cobalt->v4l2_dev.name);
707 if (cobalt->irq_work_queues == NULL) {
708 cobalt_err("Could not create workqueue\n");
709 retval = -ENOMEM;
710 goto err;
711 }
712
713 INIT_WORK(&cobalt->irq_work_queue, cobalt_irq_work_handler);
714
715 /* PCI Device Setup */
716 retval = cobalt_setup_pci(cobalt, pci_dev, pci_id);
717 if (retval != 0)
718 goto err_wq;
719
720 /* Show HDL version info */
721 if (cobalt_hdl_info_get(cobalt))
722 cobalt_info("Not able to read the HDL info\n");
723 else
724 cobalt_info("%s", cobalt->hdl_info);
725
726 retval = cobalt_i2c_init(cobalt);
727 if (retval)
728 goto err_pci;
729
730 cobalt_stream_struct_init(cobalt);
731
732 retval = cobalt_subdevs_init(cobalt);
733 if (retval)
734 goto err_i2c;
735
736 if (!(cobalt_read_bar1(cobalt, COBALT_SYS_STAT_BASE) &
737 COBALT_SYSSTAT_HSMA_PRSNTN_MSK)) {
738 retval = cobalt_subdevs_hsma_init(cobalt);
739 if (retval)
740 goto err_i2c;
741 }
742
743 retval = v4l2_device_register_subdev_nodes(&cobalt->v4l2_dev);
744 if (retval)
745 goto err_i2c;
746 retval = cobalt_nodes_register(cobalt);
747 if (retval) {
748 cobalt_err("Error %d registering device nodes\n", retval);
749 goto err_i2c;
750 }
751 cobalt_set_interrupt(cobalt, true);
752 v4l2_device_call_all(&cobalt->v4l2_dev, 0, core,
753 interrupt_service_routine, 0, NULL);
754
755 cobalt_info("Initialized cobalt card\n");
756
757 cobalt_flash_probe(cobalt);
758
759 return 0;
760
761err_i2c:
762 cobalt_i2c_exit(cobalt);
763 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
764err_pci:
765 cobalt_free_msi(cobalt, pci_dev);
766 cobalt_pci_iounmap(cobalt, pci_dev);
767 pci_release_regions(cobalt->pci_dev);
768 pci_disable_device(cobalt->pci_dev);
769err_wq:
770 destroy_workqueue(cobalt->irq_work_queues);
771err:
772 if (retval == 0)
773 retval = -ENODEV;
774 cobalt_err("error %d on initialization\n", retval);
775
776 v4l2_device_unregister(&cobalt->v4l2_dev);
85756a06
HV
777 kfree(cobalt);
778 return retval;
779}
780
781static void cobalt_remove(struct pci_dev *pci_dev)
782{
783 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
784 struct cobalt *cobalt = to_cobalt(v4l2_dev);
785 int i;
786
787 cobalt_flash_remove(cobalt);
788 cobalt_set_interrupt(cobalt, false);
789 flush_workqueue(cobalt->irq_work_queues);
790 cobalt_nodes_unregister(cobalt);
791 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
792 struct v4l2_subdev *sd = cobalt->streams[i].sd;
793 struct i2c_client *client;
794
795 if (sd == NULL)
796 continue;
797 client = v4l2_get_subdevdata(sd);
798 v4l2_device_unregister_subdev(sd);
799 i2c_unregister_device(client);
800 }
801 cobalt_i2c_exit(cobalt);
802 cobalt_free_msi(cobalt, pci_dev);
803 cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
804 cobalt_pci_iounmap(cobalt, pci_dev);
805 pci_release_regions(cobalt->pci_dev);
806 pci_disable_device(cobalt->pci_dev);
807 destroy_workqueue(cobalt->irq_work_queues);
808
809 cobalt_info("removed cobalt card\n");
810
811 v4l2_device_unregister(v4l2_dev);
85756a06
HV
812 kfree(cobalt);
813}
814
815/* define a pci_driver for card detection */
816static struct pci_driver cobalt_pci_driver = {
817 .name = "cobalt",
818 .id_table = cobalt_pci_tbl,
819 .probe = cobalt_probe,
820 .remove = cobalt_remove,
821};
822
823module_pci_driver(cobalt_pci_driver);
This page took 0.110248 seconds and 5 git commands to generate.