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>
26 int saa7164_api_transition_port(struct saa7164_tsport
*port
, u8 mode
)
30 ret
= saa7164_cmd_send(port
->dev
, port
->hwcfg
.unitid
, SET_CUR
,
31 SAA_STATE_CONTROL
, sizeof(mode
), &mode
);
33 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
38 int saa7164_api_get_fw_version(struct saa7164_dev
*dev
, u32
*version
)
42 ret
= saa7164_cmd_send(dev
, 0, GET_CUR
,
43 GET_FW_VERSION_CONTROL
, sizeof(u32
), version
);
45 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
50 int saa7164_api_read_eeprom(struct saa7164_dev
*dev
, u8
*buf
, int buflen
)
52 u8 reg
[] = { 0x0f, 0x00 };
57 /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
58 /* TODO: Pull the details from the boards struct */
59 return saa7164_api_i2c_read(&dev
->i2c_bus
[0], 0xa0 >> 1, sizeof(reg
),
64 int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev
*dev
,
65 struct saa7164_tsport
*port
,
66 tmComResTSFormatDescrHeader_t
*tsfmt
)
68 dprintk(DBGLVL_API
, " bFormatIndex = 0x%x\n", tsfmt
->bFormatIndex
);
69 dprintk(DBGLVL_API
, " bDataOffset = 0x%x\n", tsfmt
->bDataOffset
);
70 dprintk(DBGLVL_API
, " bPacketLength= 0x%x\n", tsfmt
->bPacketLength
);
71 dprintk(DBGLVL_API
, " bStrideLength= 0x%x\n", tsfmt
->bStrideLength
);
72 dprintk(DBGLVL_API
, " bguid = (....)\n");
74 /* Cache the hardware configuration in the port */
76 port
->bufcounter
= port
->hwcfg
.BARLocation
;
77 port
->pitch
= port
->hwcfg
.BARLocation
+ (2 * sizeof(u32
));
78 port
->bufsize
= port
->hwcfg
.BARLocation
+ (3 * sizeof(u32
));
79 port
->bufoffset
= port
->hwcfg
.BARLocation
+ (4 * sizeof(u32
));
80 port
->bufptr32l
= port
->hwcfg
.BARLocation
+
82 (sizeof(u32
) * port
->hwcfg
.buffercount
) + sizeof(u32
);
83 port
->bufptr32h
= port
->hwcfg
.BARLocation
+
85 (sizeof(u32
) * port
->hwcfg
.buffercount
);
86 port
->bufptr64
= port
->hwcfg
.BARLocation
+
88 (sizeof(u32
) * port
->hwcfg
.buffercount
);
89 dprintk(DBGLVL_API
, " = port->hwcfg.BARLocation = 0x%x\n",
90 port
->hwcfg
.BARLocation
);
92 dprintk(DBGLVL_API
, " = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
98 int saa7164_api_dump_subdevs(struct saa7164_dev
*dev
, u8
*buf
, int len
)
100 struct saa7164_tsport
*port
= 0;
101 u32 idx
, next_offset
;
103 tmComResDescrHeader_t
*hdr
, *t
;
104 tmComResExtDevDescrHeader_t
*exthdr
;
105 tmComResPathDescrHeader_t
*pathhdr
;
106 tmComResAntTermDescrHeader_t
*anttermhdr
;
107 tmComResTunerDescrHeader_t
*tunerunithdr
;
108 tmComResDMATermDescrHeader_t
*vcoutputtermhdr
;
109 tmComResTSFormatDescrHeader_t
*tsfmt
;
113 "%s(?,?,%d) sizeof(tmComResDescrHeader_t) = %d bytes\n",
114 __func__
, len
, (u32
)sizeof(tmComResDescrHeader_t
));
116 for (idx
= 0; idx
< (len
- sizeof(tmComResDescrHeader_t
)); ) {
118 hdr
= (tmComResDescrHeader_t
*)(buf
+ idx
);
120 if (hdr
->type
!= CS_INTERFACE
)
121 return SAA_ERR_NOT_SUPPORTED
;
123 dprintk(DBGLVL_API
, "@ 0x%x = \n", idx
);
124 switch (hdr
->subtype
) {
125 case GENERAL_REQUEST
:
126 dprintk(DBGLVL_API
, " GENERAL_REQUEST\n");
129 dprintk(DBGLVL_API
, " VC_TUNER_PATH\n");
130 pathhdr
= (tmComResPathDescrHeader_t
*)(buf
+ idx
);
131 dprintk(DBGLVL_API
, " pathid = 0x%x\n",
133 currpath
= pathhdr
->pathid
;
135 case VC_INPUT_TERMINAL
:
136 dprintk(DBGLVL_API
, " VC_INPUT_TERMINAL\n");
138 (tmComResAntTermDescrHeader_t
*)(buf
+ idx
);
139 dprintk(DBGLVL_API
, " terminalid = 0x%x\n",
140 anttermhdr
->terminalid
);
141 dprintk(DBGLVL_API
, " terminaltype = 0x%x\n",
142 anttermhdr
->terminaltype
);
143 switch (anttermhdr
->terminaltype
) {
145 dprintk(DBGLVL_API
, " = ITT_ANTENNA\n");
148 dprintk(DBGLVL_API
, " = LINE_CONNECTOR\n");
150 case SPDIF_CONNECTOR
:
151 dprintk(DBGLVL_API
, " = SPDIF_CONNECTOR\n");
153 case COMPOSITE_CONNECTOR
:
155 " = COMPOSITE_CONNECTOR\n");
157 case SVIDEO_CONNECTOR
:
158 dprintk(DBGLVL_API
, " = SVIDEO_CONNECTOR\n");
160 case COMPONENT_CONNECTOR
:
162 " = COMPONENT_CONNECTOR\n");
165 dprintk(DBGLVL_API
, " = STANDARD_DMA\n");
168 dprintk(DBGLVL_API
, " = undefined (0x%x)\n",
169 anttermhdr
->terminaltype
);
171 dprintk(DBGLVL_API
, " assocterminal= 0x%x\n",
172 anttermhdr
->assocterminal
);
173 dprintk(DBGLVL_API
, " iterminal = 0x%x\n",
174 anttermhdr
->iterminal
);
175 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
176 anttermhdr
->controlsize
);
178 case VC_OUTPUT_TERMINAL
:
179 dprintk(DBGLVL_API
, " VC_OUTPUT_TERMINAL\n");
181 (tmComResDMATermDescrHeader_t
*)(buf
+ idx
);
182 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
183 vcoutputtermhdr
->unitid
);
184 dprintk(DBGLVL_API
, " terminaltype = 0x%x\n",
185 vcoutputtermhdr
->terminaltype
);
186 switch (vcoutputtermhdr
->terminaltype
) {
188 dprintk(DBGLVL_API
, " = ITT_ANTENNA\n");
191 dprintk(DBGLVL_API
, " = LINE_CONNECTOR\n");
193 case SPDIF_CONNECTOR
:
194 dprintk(DBGLVL_API
, " = SPDIF_CONNECTOR\n");
196 case COMPOSITE_CONNECTOR
:
198 " = COMPOSITE_CONNECTOR\n");
200 case SVIDEO_CONNECTOR
:
201 dprintk(DBGLVL_API
, " = SVIDEO_CONNECTOR\n");
203 case COMPONENT_CONNECTOR
:
205 " = COMPONENT_CONNECTOR\n");
208 dprintk(DBGLVL_API
, " = STANDARD_DMA\n");
211 dprintk(DBGLVL_API
, " = undefined (0x%x)\n",
212 vcoutputtermhdr
->terminaltype
);
214 dprintk(DBGLVL_API
, " assocterminal= 0x%x\n",
215 vcoutputtermhdr
->assocterminal
);
216 dprintk(DBGLVL_API
, " sourceid = 0x%x\n",
217 vcoutputtermhdr
->sourceid
);
218 dprintk(DBGLVL_API
, " iterminal = 0x%x\n",
219 vcoutputtermhdr
->iterminal
);
220 dprintk(DBGLVL_API
, " BARLocation = 0x%x\n",
221 vcoutputtermhdr
->BARLocation
);
222 dprintk(DBGLVL_API
, " flags = 0x%x\n",
223 vcoutputtermhdr
->flags
);
224 dprintk(DBGLVL_API
, " interruptid = 0x%x\n",
225 vcoutputtermhdr
->interruptid
);
226 dprintk(DBGLVL_API
, " buffercount = 0x%x\n",
227 vcoutputtermhdr
->buffercount
);
228 dprintk(DBGLVL_API
, " metadatasize = 0x%x\n",
229 vcoutputtermhdr
->metadatasize
);
230 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
231 vcoutputtermhdr
->controlsize
);
232 dprintk(DBGLVL_API
, " numformats = 0x%x\n",
233 vcoutputtermhdr
->numformats
);
235 t
= (tmComResDescrHeader_t
*)
236 ((tmComResDMATermDescrHeader_t
*)(buf
+ idx
));
237 next_offset
= idx
+ (vcoutputtermhdr
->len
);
238 for (i
= 0; i
< vcoutputtermhdr
->numformats
; i
++) {
239 t
= (tmComResDescrHeader_t
*)
241 switch (t
->subtype
) {
242 case VS_FORMAT_MPEG2TS
:
244 (tmComResTSFormatDescrHeader_t
*)t
;
249 memcpy(&port
->hwcfg
, vcoutputtermhdr
,
250 sizeof(*vcoutputtermhdr
));
251 saa7164_api_configure_port_mpeg2ts(dev
,
254 case VS_FORMAT_MPEG2PS
:
256 " = VS_FORMAT_MPEG2PS\n");
260 " = VS_FORMAT_VBI\n");
264 " = VS_FORMAT_RDS\n");
266 case VS_FORMAT_UNCOMPRESSED
:
268 " = VS_FORMAT_UNCOMPRESSED\n");
272 " = VS_FORMAT_TYPE\n");
276 " = undefined (0x%x)\n",
279 next_offset
+= t
->len
;
284 dprintk(DBGLVL_API
, " TUNER_UNIT\n");
286 (tmComResTunerDescrHeader_t
*)(buf
+ idx
);
287 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
288 tunerunithdr
->unitid
);
289 dprintk(DBGLVL_API
, " sourceid = 0x%x\n",
290 tunerunithdr
->sourceid
);
291 dprintk(DBGLVL_API
, " iunit = 0x%x\n",
292 tunerunithdr
->iunit
);
293 dprintk(DBGLVL_API
, " tuningstandards = 0x%x\n",
294 tunerunithdr
->tuningstandards
);
295 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
296 tunerunithdr
->controlsize
);
297 dprintk(DBGLVL_API
, " controls = 0x%x\n",
298 tunerunithdr
->controls
);
300 case VC_SELECTOR_UNIT
:
301 dprintk(DBGLVL_API
, " VC_SELECTOR_UNIT\n");
303 case VC_PROCESSING_UNIT
:
304 dprintk(DBGLVL_API
, " VC_PROCESSING_UNIT\n");
307 dprintk(DBGLVL_API
, " FEATURE_UNIT\n");
310 dprintk(DBGLVL_API
, " ENCODER_UNIT\n");
313 dprintk(DBGLVL_API
, " EXTENSION_UNIT\n");
314 exthdr
= (tmComResExtDevDescrHeader_t
*)(buf
+ idx
);
315 dprintk(DBGLVL_API
, " unitid = 0x%x\n",
317 dprintk(DBGLVL_API
, " deviceid = 0x%x\n",
319 dprintk(DBGLVL_API
, " devicetype = 0x%x\n",
321 if (exthdr
->devicetype
& 0x1)
322 dprintk(DBGLVL_API
, " = Decoder Device\n");
323 if (exthdr
->devicetype
& 0x2)
324 dprintk(DBGLVL_API
, " = GPIO Source\n");
325 if (exthdr
->devicetype
& 0x4)
326 dprintk(DBGLVL_API
, " = Video Decoder\n");
327 if (exthdr
->devicetype
& 0x8)
328 dprintk(DBGLVL_API
, " = Audio Decoder\n");
329 if (exthdr
->devicetype
& 0x20)
330 dprintk(DBGLVL_API
, " = Crossbar\n");
331 if (exthdr
->devicetype
& 0x40)
332 dprintk(DBGLVL_API
, " = Tuner\n");
333 if (exthdr
->devicetype
& 0x80)
334 dprintk(DBGLVL_API
, " = IF PLL\n");
335 if (exthdr
->devicetype
& 0x100)
336 dprintk(DBGLVL_API
, " = Demodulator\n");
337 if (exthdr
->devicetype
& 0x200)
338 dprintk(DBGLVL_API
, " = RDS Decoder\n");
339 if (exthdr
->devicetype
& 0x400)
340 dprintk(DBGLVL_API
, " = Encoder\n");
341 if (exthdr
->devicetype
& 0x800)
342 dprintk(DBGLVL_API
, " = IR Decoder\n");
343 if (exthdr
->devicetype
& 0x1000)
344 dprintk(DBGLVL_API
, " = EEPROM\n");
345 if (exthdr
->devicetype
& 0x2000)
348 if (exthdr
->devicetype
& 0x10000)
350 " = Streaming Device\n");
351 if (exthdr
->devicetype
& 0x20000)
354 if (exthdr
->devicetype
& 0x40000000)
356 " = Generic Device\n");
357 if (exthdr
->devicetype
& 0x80000000)
359 " = Config Space Device\n");
360 dprintk(DBGLVL_API
, " numgpiopins = 0x%x\n",
361 exthdr
->numgpiopins
);
362 dprintk(DBGLVL_API
, " numgpiogroups = 0x%x\n",
363 exthdr
->numgpiogroups
);
364 dprintk(DBGLVL_API
, " controlsize = 0x%x\n",
365 exthdr
->controlsize
);
367 case PVC_INFRARED_UNIT
:
368 dprintk(DBGLVL_API
, " PVC_INFRARED_UNIT\n");
371 dprintk(DBGLVL_API
, " DRM_UNIT\n");
374 dprintk(DBGLVL_API
, "default %d\n", hdr
->subtype
);
377 dprintk(DBGLVL_API
, " 1.%x\n", hdr
->len
);
378 dprintk(DBGLVL_API
, " 2.%x\n", hdr
->type
);
379 dprintk(DBGLVL_API
, " 3.%x\n", hdr
->subtype
);
380 dprintk(DBGLVL_API
, " 4.%x\n", hdr
->unitid
);
388 int saa7164_api_enum_subdevs(struct saa7164_dev
*dev
)
394 dprintk(DBGLVL_API
, "%s()\n", __func__
);
396 /* Get the total descriptor length */
397 ret
= saa7164_cmd_send(dev
, 0, GET_LEN
,
398 GET_DESCRIPTORS_CONTROL
, sizeof(buflen
), &buflen
);
400 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
402 dprintk(DBGLVL_API
, "%s() total descriptor size = %d bytes.\n",
405 /* Allocate enough storage for all of the descs */
406 buf
= kzalloc(buflen
, GFP_KERNEL
);
408 return SAA_ERR_NO_RESOURCES
;
411 ret
= saa7164_cmd_send(dev
, 0, GET_CUR
,
412 GET_DESCRIPTORS_CONTROL
, buflen
, buf
);
414 printk(KERN_ERR
"%s() error, ret = 0x%x\n", __func__
, ret
);
418 if (saa_debug
& DBGLVL_API
)
419 saa7164_dumphex16(dev
, buf
, (buflen
/16)*16);
421 saa7164_api_dump_subdevs(dev
, buf
, buflen
);
428 int saa7164_api_i2c_read(struct saa7164_i2c
*bus
, u8 addr
, u32 reglen
, u8
*reg
,
429 u32 datalen
, u8
*data
)
431 struct saa7164_dev
*dev
= bus
->dev
;
438 dprintk(DBGLVL_API
, "%s()\n", __func__
);
447 regval
= ((*(reg
) << 8) || *(reg
+1));
450 regval
= ((*(reg
) << 16) | (*(reg
+1) << 8) | *(reg
+2));
453 regval
= ((*(reg
) << 24) | (*(reg
+1) << 16) |
454 (*(reg
+2) << 8) | *(reg
+3));
456 /* Prepare the send buffer */
457 /* Bytes 00-03 source register length
458 * 04-07 source bytes to read
459 * 08... register address
461 memset(buf
, 0, sizeof(buf
));
462 memcpy((buf
+ 2 * sizeof(u32
) + 0), reg
, reglen
);
463 *((u32
*)(buf
+ 0 * sizeof(u32
))) = reglen
;
464 *((u32
*)(buf
+ 1 * sizeof(u32
))) = datalen
;
466 unitid
= saa7164_i2caddr_to_unitid(bus
, addr
);
469 "%s() error, cannot translate regaddr 0x%x to unitid\n",
474 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_LEN
,
475 EXU_REGISTER_ACCESS_CONTROL
, sizeof(len
), &len
);
477 printk(KERN_ERR
"%s() error, ret(1) = 0x%x\n", __func__
, ret
);
481 dprintk(DBGLVL_API
, "%s() len = %d bytes\n", __func__
, len
);
483 if (saa_debug
& DBGLVL_I2C
)
484 saa7164_dumphex16(dev
, buf
, 2 * 16);
486 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_CUR
,
487 EXU_REGISTER_ACCESS_CONTROL
, len
, &buf
);
489 printk(KERN_ERR
"%s() error, ret(2) = 0x%x\n", __func__
, ret
);
491 if (saa_debug
& DBGLVL_I2C
)
492 saa7164_dumphex16(dev
, buf
, sizeof(buf
));
493 memcpy(data
, (buf
+ 2 * sizeof(u32
) + reglen
), datalen
);
496 return ret
== SAA_OK
? 0 : -EIO
;
499 /* For a given 8 bit i2c address device, write the buffer */
500 int saa7164_api_i2c_write(struct saa7164_i2c
*bus
, u8 addr
, u32 datalen
,
503 struct saa7164_dev
*dev
= bus
->dev
;
510 dprintk(DBGLVL_API
, "%s()\n", __func__
);
512 if ((datalen
== 0) || (datalen
> 232))
515 memset(buf
, 0, sizeof(buf
));
517 unitid
= saa7164_i2caddr_to_unitid(bus
, addr
);
520 "%s() error, cannot translate regaddr 0x%x to unitid\n",
525 reglen
= saa7164_i2caddr_to_reglen(bus
, addr
);
528 "%s() error, cannot translate regaddr to reglen\n",
533 ret
= saa7164_cmd_send(bus
->dev
, unitid
, GET_LEN
,
534 EXU_REGISTER_ACCESS_CONTROL
, sizeof(len
), &len
);
536 printk(KERN_ERR
"%s() error, ret(1) = 0x%x\n", __func__
, ret
);
540 dprintk(DBGLVL_API
, "%s() len = %d bytes\n", __func__
, len
);
542 /* Prepare the send buffer */
543 /* Bytes 00-03 dest register length
544 * 04-07 dest bytes to write
545 * 08... register address
547 *((u32
*)(buf
+ 0 * sizeof(u32
))) = reglen
;
548 *((u32
*)(buf
+ 1 * sizeof(u32
))) = datalen
- reglen
;
549 memcpy((buf
+ 2 * sizeof(u32
)), data
, datalen
);
551 if (saa_debug
& DBGLVL_I2C
)
552 saa7164_dumphex16(dev
, buf
, sizeof(buf
));
554 ret
= saa7164_cmd_send(bus
->dev
, unitid
, SET_CUR
,
555 EXU_REGISTER_ACCESS_CONTROL
, len
, &buf
);
557 printk(KERN_ERR
"%s() error, ret(2) = 0x%x\n", __func__
, ret
);
559 return ret
== SAA_OK
? 0 : -EIO
;
563 int saa7164_api_modify_gpio(struct saa7164_dev
*dev
, u8 unitid
,
569 dprintk(DBGLVL_API
, "%s(0x%x, %d, %d)\n",
570 __func__
, unitid
, pin
, state
);
572 if ((pin
> 7) || (state
> 2))
573 return SAA_ERR_BAD_PARAMETER
;
578 ret
= saa7164_cmd_send(dev
, unitid
, SET_CUR
,
579 EXU_GPIO_CONTROL
, sizeof(t
), &t
);
581 printk(KERN_ERR
"%s() error, ret = 0x%x\n",
587 int saa7164_api_set_gpiobit(struct saa7164_dev
*dev
, u8 unitid
,
590 return saa7164_api_modify_gpio(dev
, unitid
, pin
, 1);
593 int saa7164_api_clear_gpiobit(struct saa7164_dev
*dev
, u8 unitid
,
596 return saa7164_api_modify_gpio(dev
, unitid
, pin
, 0);