2 * Driver for the NXP SAA7164 PCIe bridge
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/wait.h>
23 #include <linux/slab.h>
27 int saa7164_api_transition_port(struct saa7164_tsport
*port
, u8 mode
)
31 ret
= saa7164_cmd_send(port
->dev
, port
->hwcfg
.unitid
, SET_CUR
,
32 SAA_STATE_CONTROL
, sizeof(mode
), &mode
);
34 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
39 int saa7164_api_get_fw_version(struct saa7164_dev
*dev
, u32
*version
)
43 ret
= saa7164_cmd_send(dev
, 0, GET_CUR
,
44 GET_FW_VERSION_CONTROL
, sizeof(u32
), version
);
46 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
51 int saa7164_api_read_eeprom(struct saa7164_dev
*dev
, u8
*buf
, int buflen
)
53 u8 reg
[] = { 0x0f, 0x00 };
58 /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
59 /* TODO: Pull the details from the boards struct */
60 return saa7164_api_i2c_read(&dev
->i2c_bus
[0], 0xa0 >> 1, sizeof(reg
),
65 int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev
*dev
,
66 struct saa7164_tsport
*port
,
67 tmComResTSFormatDescrHeader_t
*tsfmt
)
69 dprintk(DBGLVL_API
, " bFormatIndex = 0x%x\n", tsfmt
->bFormatIndex
);
70 dprintk(DBGLVL_API
, " bDataOffset = 0x%x\n", tsfmt
->bDataOffset
);
71 dprintk(DBGLVL_API
, " bPacketLength= 0x%x\n", tsfmt
->bPacketLength
);
72 dprintk(DBGLVL_API
, " bStrideLength= 0x%x\n", tsfmt
->bStrideLength
);
73 dprintk(DBGLVL_API
, " bguid = (....)\n");
75 /* Cache the hardware configuration in the port */
77 port
->bufcounter
= port
->hwcfg
.BARLocation
;
78 port
->pitch
= port
->hwcfg
.BARLocation
+ (2 * sizeof(u32
));
79 port
->bufsize
= port
->hwcfg
.BARLocation
+ (3 * sizeof(u32
));
80 port
->bufoffset
= port
->hwcfg
.BARLocation
+ (4 * sizeof(u32
));
81 port
->bufptr32l
= port
->hwcfg
.BARLocation
+
83 (sizeof(u32
) * port
->hwcfg
.buffercount
) + sizeof(u32
);
84 port
->bufptr32h
= port
->hwcfg
.BARLocation
+
86 (sizeof(u32
) * port
->hwcfg
.buffercount
);
87 port
->bufptr64
= port
->hwcfg
.BARLocation
+
89 (sizeof(u32
) * port
->hwcfg
.buffercount
);
90 dprintk(DBGLVL_API
, " = port->hwcfg.BARLocation = 0x%x\n",
91 port
->hwcfg
.BARLocation
);
93 dprintk(DBGLVL_API
, " = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
99 int saa7164_api_dump_subdevs(struct saa7164_dev
*dev
, u8
*buf
, int len
)
101 struct saa7164_tsport
*port
= 0;
102 u32 idx
, next_offset
;
104 tmComResDescrHeader_t
*hdr
, *t
;
105 tmComResExtDevDescrHeader_t
*exthdr
;
106 tmComResPathDescrHeader_t
*pathhdr
;
107 tmComResAntTermDescrHeader_t
*anttermhdr
;
108 tmComResTunerDescrHeader_t
*tunerunithdr
;
109 tmComResDMATermDescrHeader_t
*vcoutputtermhdr
;
110 tmComResTSFormatDescrHeader_t
*tsfmt
;
114 "%s(?,?,%d) sizeof(tmComResDescrHeader_t) = %d bytes\n",
115 __func__
, len
, (u32
)sizeof(tmComResDescrHeader_t
));
117 for (idx
= 0; idx
< (len
- sizeof(tmComResDescrHeader_t
)); ) {
119 hdr
= (tmComResDescrHeader_t
*)(buf
+ idx
);
121 if (hdr
->type
!= CS_INTERFACE
)
122 return SAA_ERR_NOT_SUPPORTED
;
124 dprintk(DBGLVL_API
, "@ 0x%x = \n", idx
);
125 switch (hdr
->subtype
) {
126 case GENERAL_REQUEST
:
127 dprintk(DBGLVL_API
, " GENERAL_REQUEST\n");
130 dprintk(DBGLVL_API
, " VC_TUNER_PATH\n");
131 pathhdr
= (tmComResPathDescrHeader_t
*)(buf
+ idx
);
132 dprintk(DBGLVL_API
, " pathid = 0x%x\n",
134 currpath
= pathhdr
->pathid
;
136 case VC_INPUT_TERMINAL
:
137 dprintk(DBGLVL_API
, " VC_INPUT_TERMINAL\n");
139 (tmComResAntTermDescrHeader_t
*)(buf
+ idx
);
140 dprintk(DBGLVL_API
, " terminalid = 0x%x\n",
141 anttermhdr
->terminalid
);
142 dprintk(DBGLVL_API
, " terminaltype = 0x%x\n",
143 anttermhdr
->terminaltype
);
144 switch (anttermhdr
->terminaltype
) {
146 dprintk(DBGLVL_API
, " = ITT_ANTENNA\n");
149 dprintk(DBGLVL_API
, " = LINE_CONNECTOR\n");
151 case SPDIF_CONNECTOR
:
152 dprintk(DBGLVL_API
, " = SPDIF_CONNECTOR\n");
154 case COMPOSITE_CONNECTOR
:
156 " = COMPOSITE_CONNECTOR\n");
158 case SVIDEO_CONNECTOR
:
159 dprintk(DBGLVL_API
, " = SVIDEO_CONNECTOR\n");
161 case COMPONENT_CONNECTOR
:
163 " = COMPONENT_CONNECTOR\n");
166 dprintk(DBGLVL_API
, " = STANDARD_DMA\n");
169 dprintk(DBGLVL_API
, " = undefined (0x%x)\n",
170 anttermhdr
->terminaltype
);
172 dprintk(DBGLVL_API
, " assocterminal= 0x%x\n",
173 anttermhdr
->assocterminal
);
174 dprintk(DBGLVL_API
, " iterminal = 0x%x\n",
175 anttermhdr
->iterminal
);
176 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
177 anttermhdr
->controlsize
);
179 case VC_OUTPUT_TERMINAL
:
180 dprintk(DBGLVL_API
, " VC_OUTPUT_TERMINAL\n");
182 (tmComResDMATermDescrHeader_t
*)(buf
+ idx
);
183 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
184 vcoutputtermhdr
->unitid
);
185 dprintk(DBGLVL_API
, " terminaltype = 0x%x\n",
186 vcoutputtermhdr
->terminaltype
);
187 switch (vcoutputtermhdr
->terminaltype
) {
189 dprintk(DBGLVL_API
, " = ITT_ANTENNA\n");
192 dprintk(DBGLVL_API
, " = LINE_CONNECTOR\n");
194 case SPDIF_CONNECTOR
:
195 dprintk(DBGLVL_API
, " = SPDIF_CONNECTOR\n");
197 case COMPOSITE_CONNECTOR
:
199 " = COMPOSITE_CONNECTOR\n");
201 case SVIDEO_CONNECTOR
:
202 dprintk(DBGLVL_API
, " = SVIDEO_CONNECTOR\n");
204 case COMPONENT_CONNECTOR
:
206 " = COMPONENT_CONNECTOR\n");
209 dprintk(DBGLVL_API
, " = STANDARD_DMA\n");
212 dprintk(DBGLVL_API
, " = undefined (0x%x)\n",
213 vcoutputtermhdr
->terminaltype
);
215 dprintk(DBGLVL_API
, " assocterminal= 0x%x\n",
216 vcoutputtermhdr
->assocterminal
);
217 dprintk(DBGLVL_API
, " sourceid = 0x%x\n",
218 vcoutputtermhdr
->sourceid
);
219 dprintk(DBGLVL_API
, " iterminal = 0x%x\n",
220 vcoutputtermhdr
->iterminal
);
221 dprintk(DBGLVL_API
, " BARLocation = 0x%x\n",
222 vcoutputtermhdr
->BARLocation
);
223 dprintk(DBGLVL_API
, " flags = 0x%x\n",
224 vcoutputtermhdr
->flags
);
225 dprintk(DBGLVL_API
, " interruptid = 0x%x\n",
226 vcoutputtermhdr
->interruptid
);
227 dprintk(DBGLVL_API
, " buffercount = 0x%x\n",
228 vcoutputtermhdr
->buffercount
);
229 dprintk(DBGLVL_API
, " metadatasize = 0x%x\n",
230 vcoutputtermhdr
->metadatasize
);
231 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
232 vcoutputtermhdr
->controlsize
);
233 dprintk(DBGLVL_API
, " numformats = 0x%x\n",
234 vcoutputtermhdr
->numformats
);
236 t
= (tmComResDescrHeader_t
*)
237 ((tmComResDMATermDescrHeader_t
*)(buf
+ idx
));
238 next_offset
= idx
+ (vcoutputtermhdr
->len
);
239 for (i
= 0; i
< vcoutputtermhdr
->numformats
; i
++) {
240 t
= (tmComResDescrHeader_t
*)
242 switch (t
->subtype
) {
243 case VS_FORMAT_MPEG2TS
:
245 (tmComResTSFormatDescrHeader_t
*)t
;
250 memcpy(&port
->hwcfg
, vcoutputtermhdr
,
251 sizeof(*vcoutputtermhdr
));
252 saa7164_api_configure_port_mpeg2ts(dev
,
255 case VS_FORMAT_MPEG2PS
:
257 " = VS_FORMAT_MPEG2PS\n");
261 " = VS_FORMAT_VBI\n");
265 " = VS_FORMAT_RDS\n");
267 case VS_FORMAT_UNCOMPRESSED
:
269 " = VS_FORMAT_UNCOMPRESSED\n");
273 " = VS_FORMAT_TYPE\n");
277 " = undefined (0x%x)\n",
280 next_offset
+= t
->len
;
285 dprintk(DBGLVL_API
, " TUNER_UNIT\n");
287 (tmComResTunerDescrHeader_t
*)(buf
+ idx
);
288 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
289 tunerunithdr
->unitid
);
290 dprintk(DBGLVL_API
, " sourceid = 0x%x\n",
291 tunerunithdr
->sourceid
);
292 dprintk(DBGLVL_API
, " iunit = 0x%x\n",
293 tunerunithdr
->iunit
);
294 dprintk(DBGLVL_API
, " tuningstandards = 0x%x\n",
295 tunerunithdr
->tuningstandards
);
296 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
297 tunerunithdr
->controlsize
);
298 dprintk(DBGLVL_API
, " controls = 0x%x\n",
299 tunerunithdr
->controls
);
301 case VC_SELECTOR_UNIT
:
302 dprintk(DBGLVL_API
, " VC_SELECTOR_UNIT\n");
304 case VC_PROCESSING_UNIT
:
305 dprintk(DBGLVL_API
, " VC_PROCESSING_UNIT\n");
308 dprintk(DBGLVL_API
, " FEATURE_UNIT\n");
311 dprintk(DBGLVL_API
, " ENCODER_UNIT\n");
314 dprintk(DBGLVL_API
, " EXTENSION_UNIT\n");
315 exthdr
= (tmComResExtDevDescrHeader_t
*)(buf
+ idx
);
316 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
318 dprintk(DBGLVL_API
, " deviceid = 0x%x\n",
320 dprintk(DBGLVL_API
, " devicetype = 0x%x\n",
322 if (exthdr
->devicetype
& 0x1)
323 dprintk(DBGLVL_API
, " = Decoder Device\n");
324 if (exthdr
->devicetype
& 0x2)
325 dprintk(DBGLVL_API
, " = GPIO Source\n");
326 if (exthdr
->devicetype
& 0x4)
327 dprintk(DBGLVL_API
, " = Video Decoder\n");
328 if (exthdr
->devicetype
& 0x8)
329 dprintk(DBGLVL_API
, " = Audio Decoder\n");
330 if (exthdr
->devicetype
& 0x20)
331 dprintk(DBGLVL_API
, " = Crossbar\n");
332 if (exthdr
->devicetype
& 0x40)
333 dprintk(DBGLVL_API
, " = Tuner\n");
334 if (exthdr
->devicetype
& 0x80)
335 dprintk(DBGLVL_API
, " = IF PLL\n");
336 if (exthdr
->devicetype
& 0x100)
337 dprintk(DBGLVL_API
, " = Demodulator\n");
338 if (exthdr
->devicetype
& 0x200)
339 dprintk(DBGLVL_API
, " = RDS Decoder\n");
340 if (exthdr
->devicetype
& 0x400)
341 dprintk(DBGLVL_API
, " = Encoder\n");
342 if (exthdr
->devicetype
& 0x800)
343 dprintk(DBGLVL_API
, " = IR Decoder\n");
344 if (exthdr
->devicetype
& 0x1000)
345 dprintk(DBGLVL_API
, " = EEPROM\n");
346 if (exthdr
->devicetype
& 0x2000)
349 if (exthdr
->devicetype
& 0x10000)
351 " = Streaming Device\n");
352 if (exthdr
->devicetype
& 0x20000)
355 if (exthdr
->devicetype
& 0x40000000)
357 " = Generic Device\n");
358 if (exthdr
->devicetype
& 0x80000000)
360 " = Config Space Device\n");
361 dprintk(DBGLVL_API
, " numgpiopins = 0x%x\n",
362 exthdr
->numgpiopins
);
363 dprintk(DBGLVL_API
, " numgpiogroups = 0x%x\n",
364 exthdr
->numgpiogroups
);
365 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
366 exthdr
->controlsize
);
368 case PVC_INFRARED_UNIT
:
369 dprintk(DBGLVL_API
, " PVC_INFRARED_UNIT\n");
372 dprintk(DBGLVL_API
, " DRM_UNIT\n");
375 dprintk(DBGLVL_API
, "default %d\n", hdr
->subtype
);
378 dprintk(DBGLVL_API
, " 1.%x\n", hdr
->len
);
379 dprintk(DBGLVL_API
, " 2.%x\n", hdr
->type
);
380 dprintk(DBGLVL_API
, " 3.%x\n", hdr
->subtype
);
381 dprintk(DBGLVL_API
, " 4.%x\n", hdr
->unitid
);
389 int saa7164_api_enum_subdevs(struct saa7164_dev
*dev
)
395 dprintk(DBGLVL_API
, "%s()\n", __func__
);
397 /* Get the total descriptor length */
398 ret
= saa7164_cmd_send(dev
, 0, GET_LEN
,
399 GET_DESCRIPTORS_CONTROL
, sizeof(buflen
), &buflen
);
401 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
403 dprintk(DBGLVL_API
, "%s() total descriptor size = %d bytes.\n",
406 /* Allocate enough storage for all of the descs */
407 buf
= kzalloc(buflen
, GFP_KERNEL
);
409 return SAA_ERR_NO_RESOURCES
;
412 ret
= saa7164_cmd_send(dev
, 0, GET_CUR
,
413 GET_DESCRIPTORS_CONTROL
, buflen
, buf
);
415 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
419 if (saa_debug
& DBGLVL_API
)
420 saa7164_dumphex16(dev
, buf
, (buflen
/16)*16);
422 saa7164_api_dump_subdevs(dev
, buf
, buflen
);
429 int saa7164_api_i2c_read(struct saa7164_i2c
*bus
, u8 addr
, u32 reglen
, u8
*reg
,
430 u32 datalen
, u8
*data
)
432 struct saa7164_dev
*dev
= bus
->dev
;
439 dprintk(DBGLVL_API
, "%s()\n", __func__
);
448 regval
= ((*(reg
) << 8) || *(reg
+1));
451 regval
= ((*(reg
) << 16) | (*(reg
+1) << 8) | *(reg
+2));
454 regval
= ((*(reg
) << 24) | (*(reg
+1) << 16) |
455 (*(reg
+2) << 8) | *(reg
+3));
457 /* Prepare the send buffer */
458 /* Bytes 00-03 source register length
459 * 04-07 source bytes to read
460 * 08... register address
462 memset(buf
, 0, sizeof(buf
));
463 memcpy((buf
+ 2 * sizeof(u32
) + 0), reg
, reglen
);
464 *((u32
*)(buf
+ 0 * sizeof(u32
))) = reglen
;
465 *((u32
*)(buf
+ 1 * sizeof(u32
))) = datalen
;
467 unitid
= saa7164_i2caddr_to_unitid(bus
, addr
);
470 "%s() error, cannot translate regaddr 0x%x to unitid\n",
475 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_LEN
,
476 EXU_REGISTER_ACCESS_CONTROL
, sizeof(len
), &len
);
478 printk(KERN_ERR
"%s() error, ret(1) = 0x%x\n", __func__
, ret
);
482 dprintk(DBGLVL_API
, "%s() len = %d bytes\n", __func__
, len
);
484 if (saa_debug
& DBGLVL_I2C
)
485 saa7164_dumphex16(dev
, buf
, 2 * 16);
487 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_CUR
,
488 EXU_REGISTER_ACCESS_CONTROL
, len
, &buf
);
490 printk(KERN_ERR
"%s() error, ret(2) = 0x%x\n", __func__
, ret
);
492 if (saa_debug
& DBGLVL_I2C
)
493 saa7164_dumphex16(dev
, buf
, sizeof(buf
));
494 memcpy(data
, (buf
+ 2 * sizeof(u32
) + reglen
), datalen
);
497 return ret
== SAA_OK
? 0 : -EIO
;
500 /* For a given 8 bit i2c address device, write the buffer */
501 int saa7164_api_i2c_write(struct saa7164_i2c
*bus
, u8 addr
, u32 datalen
,
504 struct saa7164_dev
*dev
= bus
->dev
;
511 dprintk(DBGLVL_API
, "%s()\n", __func__
);
513 if ((datalen
== 0) || (datalen
> 232))
516 memset(buf
, 0, sizeof(buf
));
518 unitid
= saa7164_i2caddr_to_unitid(bus
, addr
);
521 "%s() error, cannot translate regaddr 0x%x to unitid\n",
526 reglen
= saa7164_i2caddr_to_reglen(bus
, addr
);
529 "%s() error, cannot translate regaddr to reglen\n",
534 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_LEN
,
535 EXU_REGISTER_ACCESS_CONTROL
, sizeof(len
), &len
);
537 printk(KERN_ERR
"%s() error, ret(1) = 0x%x\n", __func__
, ret
);
541 dprintk(DBGLVL_API
, "%s() len = %d bytes\n", __func__
, len
);
543 /* Prepare the send buffer */
544 /* Bytes 00-03 dest register length
545 * 04-07 dest bytes to write
546 * 08... register address
548 *((u32
*)(buf
+ 0 * sizeof(u32
))) = reglen
;
549 *((u32
*)(buf
+ 1 * sizeof(u32
))) = datalen
- reglen
;
550 memcpy((buf
+ 2 * sizeof(u32
)), data
, datalen
);
552 if (saa_debug
& DBGLVL_I2C
)
553 saa7164_dumphex16(dev
, buf
, sizeof(buf
));
555 ret
= saa7164_cmd_send(bus
->dev
, unitid
, SET_CUR
,
556 EXU_REGISTER_ACCESS_CONTROL
, len
, &buf
);
558 printk(KERN_ERR
"%s() error, ret(2) = 0x%x\n", __func__
, ret
);
560 return ret
== SAA_OK
? 0 : -EIO
;
564 int saa7164_api_modify_gpio(struct saa7164_dev
*dev
, u8 unitid
,
570 dprintk(DBGLVL_API
, "%s(0x%x, %d, %d)\n",
571 __func__
, unitid
, pin
, state
);
573 if ((pin
> 7) || (state
> 2))
574 return SAA_ERR_BAD_PARAMETER
;
579 ret
= saa7164_cmd_send(dev
, unitid
, SET_CUR
,
580 EXU_GPIO_CONTROL
, sizeof(t
), &t
);
582 printk(KERN_ERR
"%s() error, ret = 0x%x\n",
588 int saa7164_api_set_gpiobit(struct saa7164_dev
*dev
, u8 unitid
,
591 return saa7164_api_modify_gpio(dev
, unitid
, pin
, 1);
594 int saa7164_api_clear_gpiobit(struct saa7164_dev
*dev
, u8 unitid
,
597 return saa7164_api_modify_gpio(dev
, unitid
, pin
, 0);