1/* $NetBSD: cxdtv.c,v 1.22 2024/02/09 17:39:33 andvar Exp $ */
2
3/*
4 * Copyright (c) 2008, 2011 Jonathan A. Kollasch
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: cxdtv.c,v 1.22 2024/02/09 17:39:33 andvar Exp $");
31
32#include <sys/param.h>
33#include <sys/kernel.h>
34#include <sys/device.h>
35#include <sys/kmem.h>
36#include <sys/mutex.h>
37#include <sys/proc.h>
38#include <sys/module.h>
39#include <sys/bus.h>
40
41#include <dev/pci/pcivar.h>
42#include <dev/pci/pcireg.h>
43#include <dev/pci/pcidevs.h>
44#include <dev/i2c/i2cvar.h>
45#include <dev/i2c/i2c_bitbang.h>
46
47#include <dev/i2c/tvpllvar.h>
48#include <dev/i2c/tvpll_tuners.h>
49
50#include <dev/i2c/nxt2kvar.h>
51#include <dev/i2c/lg3303var.h>
52
53#include <dev/dtv/dtvif.h>
54
55#include <dev/pci/cxdtvreg.h>
56#include <dev/pci/cxdtvvar.h>
57#include <dev/pci/cxdtv_boards.h>
58
59#define CXDTV_MMBASE		0x10
60
61#define CXDTV_SRAM_CH_MPEG	0
62#define CXDTV_TS_PKTSIZE	(188 * 8)
63
64static int cxdtv_match(device_t, cfdata_t, void *);
65static void cxdtv_attach(device_t, device_t, void *);
66static int cxdtv_detach(device_t, int);
67static int cxdtv_rescan(device_t, const char *, const int *);
68static void cxdtv_childdet(device_t, device_t);
69static int cxdtv_intr(void *);
70
71static bool cxdtv_resume(device_t, const pmf_qual_t *);
72
73static int	cxdtv_iic_send_start(void *, int);
74static int	cxdtv_iic_send_stop(void *, int);
75static int	cxdtv_iic_initiate_xfer(void *, i2c_addr_t, int);
76static int	cxdtv_iic_read_byte(void *, uint8_t *, int);
77static int	cxdtv_iic_write_byte(void *, uint8_t, int);
78
79static void	cxdtv_i2cbb_set_bits(void *, uint32_t);
80static void	cxdtv_i2cbb_set_dir(void *, uint32_t);
81static uint32_t	cxdtv_i2cbb_read_bits(void *);
82
83static int	cxdtv_sram_ch_setup(struct cxdtv_softc *,
84				    struct cxdtv_sram_ch *, uint32_t);
85static int	cxdtv_allocmem(struct cxdtv_softc *, size_t, size_t,
86    struct cxdtv_dma *);
87static int	cxdtv_freemem(struct cxdtv_softc *, struct cxdtv_dma *);
88static int	cxdtv_risc_buffer(struct cxdtv_softc *, uint32_t, uint32_t);
89static int	cxdtv_risc_field(struct cxdtv_softc *, uint32_t *, uint32_t);
90
91static int     cxdtv_mpeg_attach(struct cxdtv_softc *);
92static void    cxdtv_mpeg_detach(struct cxdtv_softc *, int flags);
93static int     cxdtv_mpeg_intr(struct cxdtv_softc *);
94static int     cxdtv_mpeg_reset(struct cxdtv_softc *);
95
96static int     cxdtv_mpeg_trigger(struct cxdtv_softc *, void *);
97static int     cxdtv_mpeg_halt(struct cxdtv_softc *);
98static void *  cxdtv_mpeg_malloc(struct cxdtv_softc *, size_t);
99static void    cxdtv_mpeg_free(struct cxdtv_softc *, void *);
100
101static void cxdtv_card_init_hd5500(struct cxdtv_softc *);
102static void cxdtv_card_init_hdtvwonder(struct cxdtv_softc *);
103
104/* MPEG TS Port */
105static void cxdtv_dtv_get_devinfo(void *, struct dvb_frontend_info *);
106static int cxdtv_dtv_open(void *, int);
107static void cxdtv_dtv_close(void *);
108static int cxdtv_dtv_set_tuner(void *, const struct dvb_frontend_parameters *);
109static fe_status_t cxdtv_dtv_get_status(void *);
110static uint16_t cxdtv_dtv_get_signal_strength(void *);
111static uint16_t cxdtv_dtv_get_snr(void *);
112static int cxdtv_dtv_start_transfer(void *,
113    void (*)(void *, const struct dtv_payload *), void *);
114static int cxdtv_dtv_stop_transfer(void *);
115
116static const struct dtv_hw_if cxdtv_dtv_if = {
117	.get_devinfo = cxdtv_dtv_get_devinfo,
118	.open = cxdtv_dtv_open,
119	.close = cxdtv_dtv_close,
120	.set_tuner = cxdtv_dtv_set_tuner,
121	.get_status = cxdtv_dtv_get_status,
122	.get_signal_strength = cxdtv_dtv_get_signal_strength,
123	.get_snr = cxdtv_dtv_get_snr,
124	.start_transfer = cxdtv_dtv_start_transfer,
125	.stop_transfer = cxdtv_dtv_stop_transfer,
126};
127
128const struct i2c_bitbang_ops cxdtv_i2cbb_ops = {
129	cxdtv_i2cbb_set_bits,
130	cxdtv_i2cbb_set_dir,
131	cxdtv_i2cbb_read_bits,
132	{ CXDTV_I2C_C_DATACONTROL_SDA, CXDTV_I2C_C_DATACONTROL_SCL, 0, 0 }
133};
134
135/* Maybe make this dynamically allocated. */
136static struct cxdtv_sram_ch cxdtv_sram_chs[] = {
137	[CXDTV_SRAM_CH_MPEG] = {
138		.csc_cmds = 0x180200, /* CMDS for ch. 28 */
139		.csc_iq = 0x180340, /* after last CMDS */
140		.csc_iqsz = 0x40, /* 16 dwords */
141		.csc_cdt = 0x180380, /* after iq */
142		.csc_cdtsz = 0x40, /* cluster descriptor space */
143		.csc_fifo = 0x180400, /* after cdt */
144		.csc_fifosz = 0x001C00, /* let's just align this up */
145		.csc_risc = 0x182000, /* after fifo */
146		.csc_riscsz = 0x6000, /* room for dma programs */
147		.csc_ptr1 = CXDTV_DMA28_PTR1,
148		.csc_ptr2 = CXDTV_DMA28_PTR2,
149		.csc_cnt1 = CXDTV_DMA28_CNT1,
150		.csc_cnt2 = CXDTV_DMA28_CNT2,
151	},
152};
153
154CFATTACH_DECL2_NEW(cxdtv, sizeof(struct cxdtv_softc),
155    cxdtv_match, cxdtv_attach, cxdtv_detach, NULL,
156    cxdtv_rescan, cxdtv_childdet);
157
158static int
159cxdtv_match(device_t parent, cfdata_t match, void *aux)
160{
161	const struct pci_attach_args *pa;
162	pcireg_t reg;
163
164	pa = aux;
165
166	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CONEXANT)
167		return 0;
168
169	if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CONEXANT_CX2388XMPEG)
170		return 0;
171
172	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
173	if (cxdtv_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg)) == NULL)
174		return 0;
175
176	return 1;
177}
178
179static void
180cxdtv_attach(device_t parent, device_t self, void *aux)
181{
182	struct cxdtv_softc *sc;
183	const struct pci_attach_args *pa = aux;
184	pci_intr_handle_t ih;
185	pcireg_t reg;
186	const char *intrstr;
187	struct i2cbus_attach_args iba;
188	char intrbuf[PCI_INTRSTR_LEN];
189
190	sc = device_private(self);
191
192	sc->sc_dev = self;
193	sc->sc_pc = pa->pa_pc;
194
195	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
196
197	sc->sc_vendor = PCI_VENDOR(reg);
198	sc->sc_product = PCI_PRODUCT(reg);
199
200	sc->sc_board = cxdtv_board_lookup(sc->sc_vendor, sc->sc_product);
201	KASSERT(sc->sc_board != NULL);
202
203	pci_aprint_devinfo(pa, NULL);
204
205	if (pci_mapreg_map(pa, CXDTV_MMBASE, PCI_MAPREG_TYPE_MEM, 0,
206			   &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) {
207		aprint_error_dev(self, "couldn't map memory space\n");
208		return;
209	}
210
211	sc->sc_dmat = pa->pa_dmat;
212
213	if (pci_intr_map(pa, &ih)) {
214		aprint_error_dev(self, "couldn't map interrupt\n");
215		return;
216	}
217	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
218	sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_VM, cxdtv_intr,
219	    sc, device_xname(self));
220	if (sc->sc_ih == NULL) {
221		aprint_error_dev(self, "couldn't establish interrupt");
222		if (intrstr != NULL)
223			aprint_error(" at %s", intrstr);
224		aprint_error("\n");
225		return;
226	}
227	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
228
229	/* set master */
230	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
231	reg |= PCI_COMMAND_MASTER_ENABLE;
232	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
233
234	iic_tag_init(&sc->sc_i2c);
235	sc->sc_i2c.ic_cookie = sc;
236	sc->sc_i2c.ic_send_start = cxdtv_iic_send_start;
237	sc->sc_i2c.ic_send_stop = cxdtv_iic_send_stop;
238	sc->sc_i2c.ic_initiate_xfer = cxdtv_iic_initiate_xfer;
239	sc->sc_i2c.ic_read_byte = cxdtv_iic_read_byte;
240	sc->sc_i2c.ic_write_byte = cxdtv_iic_write_byte;
241
242#if notyet
243	/* enable i2c compatible software mode */
244	val = bus_space_read_4(sc->sc_memt, sc->sc_memh,
245	    CXDTV_I2C_C_DATACONTROL);
246	val = CXDTV_I2C_C_DATACONTROL_SCL | CXDTV_I2C_C_DATACONTROL_SDA;
247	bus_space_write_4(sc->sc_memt, sc->sc_memh,
248	    CXDTV_I2C_C_DATACONTROL, val);
249#endif
250
251	cxdtv_mpeg_attach(sc);
252
253	/* attach other devices to iic(4) */
254	memset(&iba, 0, sizeof(iba));
255	iba.iba_tag = &sc->sc_i2c;
256	config_found(self, &iba, iicbus_print,
257	    CFARGS(.iattr = "i2cbus"));
258
259	if (!pmf_device_register(self, NULL, cxdtv_resume))
260		aprint_error_dev(self, "couldn't establish power handler\n");
261
262	return;
263}
264
265static int
266cxdtv_detach(device_t self, int flags)
267{
268	struct cxdtv_softc *sc = device_private(self);
269	int error;
270
271	error = config_detach_children(self, flags);
272	if (error)
273		return error;
274
275	cxdtv_mpeg_detach(sc, flags);
276
277	if (sc->sc_ih)
278		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
279
280	if (sc->sc_mems)
281		bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
282
283	iic_tag_fini(&sc->sc_i2c);
284
285	return 0;
286}
287
288static int
289cxdtv_rescan(device_t self, const char *ifattr, const int *locs)
290{
291	struct cxdtv_softc *sc = device_private(self);
292	struct dtv_attach_args daa;
293
294	daa.hw = &cxdtv_dtv_if;
295	daa.priv = sc;
296
297	if (ifattr_match(ifattr, "dtvbus") && sc->sc_dtvdev == NULL)
298		sc->sc_dtvdev = config_found(sc->sc_dev, &daa, dtv_print,
299		    CFARGS(.iattr = "dtvbus"));
300
301	return 0;
302}
303
304static void
305cxdtv_childdet(device_t self, device_t child)
306{
307	struct cxdtv_softc *sc = device_private(self);
308
309	if (child == sc->sc_dtvdev)
310		sc->sc_dtvdev = NULL;
311}
312
313static bool
314cxdtv_resume(device_t dv, const pmf_qual_t *qual)
315{
316	/* XXX revisit */
317
318	aprint_debug_dev(dv, "%s\n", __func__);
319
320	return true;
321}
322
323static int
324cxdtv_intr(void *intarg)
325{
326	struct cxdtv_softc *sc = intarg;
327	uint32_t val;
328
329	val = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MSTAT);
330	if (val == 0) {
331		return 0; /* not ours */
332	}
333
334	if (val & CXT_PI_TS_INT) {
335		cxdtv_mpeg_intr(sc);
336	}
337
338	if (val & ~CXT_PI_TS_INT) {
339		device_printf(sc->sc_dev, "%s, %08x\n", __func__, val);
340	}
341
342	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_STAT, val);
343
344	return 1;
345}
346
347/* I2C interface */
348
349static void
350cxdtv_i2cbb_set_bits(void *cookie, uint32_t bits)
351{
352	struct cxdtv_softc *sc = cookie;
353
354	bus_space_write_4(sc->sc_memt, sc->sc_memh,
355	    CXDTV_I2C_C_DATACONTROL, bits);
356	(void)bus_space_read_4(sc->sc_memt, sc->sc_memh,
357	    CXDTV_I2C_C_DATACONTROL);
358
359	return;
360}
361
362static void
363cxdtv_i2cbb_set_dir(void *cookie, uint32_t bits)
364{
365	return;
366}
367
368static uint32_t
369cxdtv_i2cbb_read_bits(void *cookie)
370{
371	struct cxdtv_softc *sc = cookie;
372	uint32_t value;
373
374	value = bus_space_read_4(sc->sc_memt, sc->sc_memh,
375	    CXDTV_I2C_C_DATACONTROL);
376
377	return value;
378}
379
380static int
381cxdtv_iic_send_start(void *cookie, int flags)
382{
383	return i2c_bitbang_send_start(cookie, flags, &cxdtv_i2cbb_ops);
384}
385
386static int
387cxdtv_iic_send_stop(void *cookie, int flags)
388{
389	return i2c_bitbang_send_stop(cookie, flags, &cxdtv_i2cbb_ops);
390}
391
392static int
393cxdtv_iic_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
394{
395	return i2c_bitbang_initiate_xfer(cookie, addr, flags, &cxdtv_i2cbb_ops);
396}
397
398static int
399cxdtv_iic_read_byte(void *cookie, uint8_t *data, int flags)
400{
401	return i2c_bitbang_read_byte(cookie, data, flags, &cxdtv_i2cbb_ops);
402}
403
404static int
405cxdtv_iic_write_byte(void *cookie, uint8_t data, int flags)
406{
407	return i2c_bitbang_write_byte(cookie, data, flags, &cxdtv_i2cbb_ops);
408}
409
410int
411cxdtv_mpeg_attach(struct cxdtv_softc *sc)
412{
413	struct cxdtv_sram_ch *ch;
414
415	CX_DPRINTF(("cxdtv_mpeg_attach\n"));
416
417	ch = &cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG];
418
419	sc->sc_riscbufsz = ch->csc_riscsz;
420	sc->sc_riscbuf = kmem_alloc(ch->csc_riscsz, KM_SLEEP);
421
422	aprint_debug_dev(sc->sc_dev, "attaching frontend...\n");
423
424	switch(sc->sc_vendor) {
425	case PCI_VENDOR_ATI:
426		cxdtv_card_init_hdtvwonder(sc);
427		break;
428	case PCI_VENDOR_PCHDTV:
429		if (sc->sc_product == PCI_PRODUCT_PCHDTV_HD5500) {
430			cxdtv_card_init_hd5500(sc);
431		}
432		break;
433	}
434
435	KASSERT(sc->sc_tuner == NULL);
436	KASSERT(sc->sc_demod == NULL);
437
438	switch(sc->sc_board->cb_demod) {
439	case CXDTV_DEMOD_NXT2004:
440		sc->sc_demod = nxt2k_open(sc->sc_dev, &sc->sc_i2c, 0x0a, 0);
441		break;
442	case CXDTV_DEMOD_LG3303:
443		sc->sc_demod = lg3303_open(sc->sc_dev, &sc->sc_i2c, 0x59,
444		    LG3303_CFG_SERIAL_INPUT);
445		break;
446	default:
447		break;
448	}
449
450	switch(sc->sc_board->cb_tuner) {
451	case CXDTV_TUNER_PLL:
452		if (sc->sc_vendor == PCI_VENDOR_ATI)
453			sc->sc_tuner = tvpll_open(sc->sc_dev, &sc->sc_i2c, 0x61, &tvpll_tuv1236d_pll);
454		if (sc->sc_vendor == PCI_VENDOR_PCHDTV)
455			sc->sc_tuner = tvpll_open(sc->sc_dev, &sc->sc_i2c, 0x61, &tvpll_tdvs_h06xf_pll);
456		break;
457	default:
458		break;
459	}
460
461	KASSERT(sc->sc_tuner != NULL);
462	KASSERT(sc->sc_demod != NULL);
463
464	cxdtv_rescan(sc->sc_dev, NULL, NULL);
465
466	return (sc->sc_dtvdev != NULL);
467}
468
469void
470cxdtv_mpeg_detach(struct cxdtv_softc *sc, int flags)
471{
472
473	if (sc->sc_demod) {
474		switch (sc->sc_board->cb_demod) {
475		case CXDTV_DEMOD_NXT2004:
476			nxt2k_close(sc->sc_demod);
477			break;
478		case CXDTV_DEMOD_LG3303:
479			lg3303_close(sc->sc_demod);
480			break;
481		default:
482			break;
483		}
484		sc->sc_demod = NULL;
485	}
486	if (sc->sc_tuner) {
487		switch (sc->sc_board->cb_tuner) {
488		case CXDTV_TUNER_PLL:
489			tvpll_close(sc->sc_tuner);
490			break;
491		default:
492			break;
493		}
494		sc->sc_tuner = NULL;
495	}
496
497	if (sc->sc_riscbuf) {
498		kmem_free(sc->sc_riscbuf, sc->sc_riscbufsz);
499		sc->sc_riscbuf = NULL;
500		sc->sc_riscbufsz = 0;
501	}
502}
503
504static void
505cxdtv_dtv_get_devinfo(void *priv, struct dvb_frontend_info *info)
506{
507	memset(info, 0, sizeof(*info));
508	strlcpy(info->name, "CX23880", sizeof(info->name));
509	info->type = FE_ATSC;
510	info->frequency_min = 54000000;
511	info->frequency_max = 858000000;
512	info->frequency_stepsize = 62500;
513	info->caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB;
514}
515
516static int
517cxdtv_dtv_open(void *priv, int flags)
518{
519	struct cxdtv_softc *sc = priv;
520
521	KASSERT(sc->sc_tsbuf == NULL);
522
523	cxdtv_mpeg_reset(sc);
524
525	/* allocate two alternating DMA areas for MPEG TS packets */
526	sc->sc_tsbuf = cxdtv_mpeg_malloc(sc, CXDTV_TS_PKTSIZE * 2);
527
528	if (sc->sc_tsbuf == NULL)
529		return ENOMEM;
530
531	return 0;
532}
533
534static void
535cxdtv_dtv_close(void *priv)
536{
537	struct cxdtv_softc *sc = priv;
538
539	cxdtv_dtv_stop_transfer(sc);
540
541	if (sc->sc_tsbuf != NULL) {
542		cxdtv_mpeg_free(sc, sc->sc_tsbuf);
543		sc->sc_tsbuf = NULL;
544	}
545}
546
547static int
548cxdtv_dtv_set_tuner(void *priv, const struct dvb_frontend_parameters *params)
549{
550	struct cxdtv_softc *sc = priv;
551	int error = -1;
552
553	switch(sc->sc_board->cb_tuner) {
554	case CXDTV_TUNER_PLL:
555		error = tvpll_tune_dtv(sc->sc_tuner, params);
556	}
557	if (error)
558		goto bad;
559
560	switch(sc->sc_board->cb_demod) {
561	case CXDTV_DEMOD_NXT2004:
562		error = nxt2k_set_modulation(sc->sc_demod, params->u.vsb.modulation);
563		break;
564	case CXDTV_DEMOD_LG3303:
565		error = lg3303_set_modulation(sc->sc_demod, params->u.vsb.modulation);
566		break;
567	default:
568		break;
569	}
570
571bad:
572	return error;
573}
574
575static fe_status_t
576cxdtv_dtv_get_status(void *priv)
577{
578	struct cxdtv_softc *sc = priv;
579
580	switch(sc->sc_board->cb_demod) {
581	case CXDTV_DEMOD_NXT2004:
582		return nxt2k_get_dtv_status(sc->sc_demod);
583	case CXDTV_DEMOD_LG3303:
584		return lg3303_get_dtv_status(sc->sc_demod);
585	default:
586		return 0;
587	}
588}
589
590static uint16_t
591cxdtv_dtv_get_signal_strength(void *priv)
592{
593	struct cxdtv_softc *sc = priv;
594
595	switch(sc->sc_board->cb_demod) {
596	case CXDTV_DEMOD_NXT2004:
597		return 0;	/* TODO */
598	case CXDTV_DEMOD_LG3303:
599		return lg3303_get_signal_strength(sc->sc_demod);
600	}
601
602	return 0;
603}
604
605static uint16_t
606cxdtv_dtv_get_snr(void *priv)
607{
608	struct cxdtv_softc *sc = priv;
609
610	switch(sc->sc_board->cb_demod) {
611	case CXDTV_DEMOD_NXT2004:
612		return 0;	/* TODO */
613	case CXDTV_DEMOD_LG3303:
614		return lg3303_get_snr(sc->sc_demod);
615	}
616
617	return 0;
618}
619
620static int
621cxdtv_dtv_start_transfer(void *priv,
622    void (*cb)(void *, const struct dtv_payload *), void *arg)
623{
624	struct cxdtv_softc *sc = priv;
625
626	sc->sc_dtvsubmitcb = cb;
627	sc->sc_dtvsubmitarg = arg;
628
629	/* allocate two alternating DMA areas for MPEG TS packets */
630	sc->sc_tsbuf = cxdtv_mpeg_malloc(sc, CXDTV_TS_PKTSIZE * 2);
631
632	cxdtv_mpeg_trigger(sc, sc->sc_tsbuf);
633
634	return 0;
635}
636
637static int
638cxdtv_dtv_stop_transfer(void *priv)
639{
640	struct cxdtv_softc *sc = priv;
641
642	cxdtv_mpeg_halt(sc);
643	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 0);
644
645	sc->sc_dtvsubmitcb = NULL;
646	sc->sc_dtvsubmitarg = NULL;
647
648	return 0;
649}
650
651int
652cxdtv_mpeg_reset(struct cxdtv_softc *sc)
653{
654	uint32_t v;
655
656	CX_DPRINTF(("cxdtv_mpeg_reset\n"));
657
658	v = (uint32_t)-1;
659
660	/* shutdown */
661	/* hold RISC in reset */
662	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2, 0);
663	/* disable FIFO and RISC */
664	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL, 0);
665	/* mask off all interrupts */
666	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 0);
667	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK, 0);
668
669	/* clear interrupts */
670	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_STAT, v);
671	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT, v);
672
673	memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz);
674
675	/* XXX magic */
676	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PDMA_STHRSH, 0x0707);
677	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PDMA_DTHRSH, 0x0707);
678
679	/* reset external components*/
680	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_SRST_IO, 0);
681	kpause("cxdtvrst", false, MAX(1, mstohz(1)), NULL);
682	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_SRST_IO, 1);
683
684	/* let error interrupts happen */
685	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK);
686	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK,
687	    v | 0x00fc00); /* XXX magic */
688
689	return 0;
690}
691
692static int
693cxdtv_risc_buffer(struct cxdtv_softc *sc, uint32_t bpl, uint32_t lines)
694{
695	uint32_t *rm;
696	uint32_t size;
697
698	CX_DPRINTF(("cxdtv_risc_buffer: bpl=0x%x\n", bpl));
699
700	size = 1 + (bpl * lines) / PAGE_SIZE + lines;
701	size += 2;
702
703	device_printf(sc->sc_dev, "%s: est. inst. %d\n", __func__, size);
704
705	size *= 8;
706	device_printf(sc->sc_dev, "%s: est. qword %d\n", __func__, size);
707
708	if (sc->sc_riscbuf == NULL) {
709		device_printf(sc->sc_dev, "not enough memory for RISC\n");
710		return ENOMEM;
711	}
712
713	rm = (uint32_t *)sc->sc_riscbuf;
714	cxdtv_risc_field(sc, rm, bpl);
715
716	return 0;
717}
718
719static int
720cxdtv_risc_field(struct cxdtv_softc *sc, uint32_t *rm, uint32_t bpl)
721{
722	struct cxdtv_dma *p;
723
724	CX_DPRINTF(("cxdtv_risc_field: bpl=0x%x\n", bpl));
725
726	for (p = sc->sc_dma; p && KERNADDR(p) != sc->sc_tsbuf; p = p->next)
727		continue;
728	if (p == NULL) {
729		device_printf(sc->sc_dev, "cxdtv_risc_field: bad addr %p\n",
730		    sc->sc_tsbuf);
731		return ENOENT;
732	}
733
734	memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz);
735
736	rm = sc->sc_riscbuf;
737
738	/* htole32 will be done when program is copied to chip SRAM */
739
740	/* XXX */
741	*(rm++) = (CX_RISC_SYNC|0);
742
743	*(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ1|bpl);
744	*(rm++) = (DMAADDR(p) + 0 * bpl);
745
746	*(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ2|bpl);
747	*(rm++) = (DMAADDR(p) + 1 * bpl);
748
749	*(rm++) = (CX_RISC_JUMP|1);
750	*(rm++) = (cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG].csc_risc + 4);
751
752	return 0;
753}
754
755static int
756cxdtv_sram_ch_setup(struct cxdtv_softc *sc, struct cxdtv_sram_ch *csc,
757    uint32_t bpl)
758{
759	unsigned int i, lines;
760	uint32_t cdt;
761
762	CX_DPRINTF(("cxdtv_sram_ch_setup: bpl=0x%x\n", bpl));
763
764	/* XXX why round? */
765	bpl = (bpl + 7) & ~7;
766	CX_DPRINTF(("cxdtv_sram_ch_setup: bpl=0x%x\n", bpl));
767	cdt = csc->csc_cdt;
768	lines = csc->csc_fifosz / bpl;
769	device_printf(sc->sc_dev, "%s %d lines\n", __func__, lines);
770
771	/* fill in CDT */
772	for (i = 0; i < lines; i++) {
773		CX_DPRINTF(("CDT ent %08x, %08x\n", cdt + (16 * i),
774		    csc->csc_fifo + (bpl * i)));
775		bus_space_write_4(sc->sc_memt, sc->sc_memh,
776		    cdt + (16 * i),
777		    csc->csc_fifo + (bpl * i));
778	}
779
780	/* copy DMA program */
781
782	/* converts program to little endian as it goes into SRAM */
783	bus_space_write_region_4(sc->sc_memt, sc->sc_memh,
784	     csc->csc_risc, (void *)sc->sc_riscbuf, sc->sc_riscbufsz >> 2);
785
786	/* fill in CMDS */
787	bus_space_write_4(sc->sc_memt, sc->sc_memh,
788	    csc->csc_cmds + CX_CMDS_O_IRPC, csc->csc_risc);
789
790	bus_space_write_4(sc->sc_memt, sc->sc_memh,
791	    csc->csc_cmds + CX_CMDS_O_CDTB, csc->csc_cdt);
792	bus_space_write_4(sc->sc_memt, sc->sc_memh,
793	    csc->csc_cmds + CX_CMDS_O_CDTS, (lines * 16) >> 3); /* XXX magic */
794
795	bus_space_write_4(sc->sc_memt, sc->sc_memh,
796	    csc->csc_cmds + CX_CMDS_O_IQB, csc->csc_iq);
797	bus_space_write_4(sc->sc_memt, sc->sc_memh,
798	    csc->csc_cmds + CX_CMDS_O_IQS,
799	    CX_CMDS_IQS_ISRP | (csc->csc_iqsz >> 2) );
800
801	/* zero rest of CMDS */
802	bus_space_set_region_4(sc->sc_memt, sc->sc_memh, 0x14, 0, 0x2c/4);
803
804	bus_space_write_4(sc->sc_memt, sc->sc_memh,
805	    csc->csc_cnt1, (bpl >> 3) - 1);
806
807	bus_space_write_4(sc->sc_memt, sc->sc_memh,
808	    csc->csc_ptr2, cdt);
809	bus_space_write_4(sc->sc_memt, sc->sc_memh,
810	    csc->csc_cnt2, (lines * 16) >> 3);
811
812	return 0;
813}
814
815int
816cxdtv_mpeg_trigger(struct cxdtv_softc *sc, void *buf)
817{
818	struct cxdtv_dma *p;
819	struct cxdtv_sram_ch *ch;
820	uint32_t v;
821
822	ch = &cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG];
823
824	for (p = sc->sc_dma; p && KERNADDR(p) != buf; p = p->next)
825		continue;
826	if (p == NULL) {
827		device_printf(sc->sc_dev, "cxdtv_mpeg_trigger: bad addr %p\n",
828		    buf);
829		return ENOENT;
830	}
831
832	CX_DPRINTF(("cxdtv_mpeg_trigger: buf=%p\n", buf));
833
834	cxdtv_risc_buffer(sc, CXDTV_TS_PKTSIZE, 1);
835	cxdtv_sram_ch_setup(sc, ch, CXDTV_TS_PKTSIZE);
836
837	/* software reset */
838
839	switch(sc->sc_vendor) {
840	case PCI_VENDOR_ATI:
841		/* both ATI boards with DTV are the same */
842		bus_space_write_4(sc->sc_memt, sc->sc_memh,
843		    CXDTV_TS_GEN_CONTROL, IPB_SW_RST);
844		delay(100);
845		/* parallel MPEG port */
846		bus_space_write_4(sc->sc_memt, sc->sc_memh,
847		    CXDTV_PINMUX_IO, MPEG_PAR_EN);
848		break;
849	case PCI_VENDOR_PCHDTV:
850		if (sc->sc_product == PCI_PRODUCT_PCHDTV_HD5500) {
851			bus_space_write_4(sc->sc_memt, sc->sc_memh,
852			    CXDTV_TS_GEN_CONTROL, IPB_SW_RST|IPB_SMODE);
853			delay(100);
854			bus_space_write_4(sc->sc_memt, sc->sc_memh,
855			    CXDTV_PINMUX_IO, 0x00); /* serial MPEG port */
856			/* byte-width start-of-packet */
857			bus_space_write_4(sc->sc_memt, sc->sc_memh,
858			    CXDTV_HW_SOP_CONTROL,
859			    0x47 << 16 | 188 << 4 | 1);
860			bus_space_write_4(sc->sc_memt, sc->sc_memh,
861			    CXDTV_TS_SOP_STATUS, IPB_SOP_BYTEWIDE);
862			/* serial MPEG port on HD5500 */
863			bus_space_write_4(sc->sc_memt, sc->sc_memh,
864			    CXDTV_TS_GEN_CONTROL, IPB_SMODE);
865		}
866		break;
867	default:
868		break;
869	}
870
871	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_LNGTH,
872	    CXDTV_TS_PKTSIZE);
873
874	/* Configure for standard MPEG TS, 1 good packet to sync  */
875	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_HW_SOP_CONTROL,
876	    0x47 << 16 | 188 << 4 | 1);
877
878	/* zero counter */
879	bus_space_write_4(sc->sc_memt, sc->sc_memh,
880	    CXDTV_TS_GP_CNT_CNTRL, 0x03);
881
882	/* enable bad packet interrupt */
883	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_BD_PKT_STATUS,
884	0x1000);
885
886	/* enable overflow counter */
887	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_FIFO_OVFL_STAT,
888	0x1000);
889
890	/* unmask TS interrupt */
891	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK);
892	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK,
893	    v | CXT_PI_TS_INT);
894
895	/* unmask all TS interrupts */
896	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK);
897	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK,
898	    v | 0x1f1011);
899
900	/* enable RISC DMA engine */
901	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2);
902	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2,
903	    v | CXDTV_DEV_CNTRL2_RUN_RISC);
904
905	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL);
906	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL,
907	    v | CXDTV_TS_RISC_EN | CXDTV_TS_FIFO_EN);
908
909	return 0;
910}
911
912int
913cxdtv_mpeg_halt(struct cxdtv_softc *sc)
914{
915	uint32_t v;
916
917	CX_DPRINTF(("cxdtv_mpeg_halt\n"));
918
919	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL);
920	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL,
921	    v & ~(CXDTV_TS_RISC_EN|CXDTV_TS_FIFO_EN));
922
923	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK);
924	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK,
925	    v & ~CXT_PI_TS_INT);
926
927	v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK);
928	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK,
929	    v & ~0x1f1011);
930
931	return 0;
932}
933
934int
935cxdtv_mpeg_intr(struct cxdtv_softc *sc)
936{
937	struct dtv_payload payload;
938	uint32_t s, m;
939
940	s = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT);
941	m = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK);
942	if ((s & m) == 0)
943		return 0;
944
945	if ( (s & ~CXDTV_TS_RISCI) != 0 )
946		device_printf(sc->sc_dev, "unexpected TS IS %08x\n", s);
947
948	if (sc->sc_dtvsubmitcb == NULL)
949		goto done;
950
951	if ((s & CXDTV_TS_RISCI1) == CXDTV_TS_RISCI1) {
952		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map,
953			0, CXDTV_TS_PKTSIZE,
954			BUS_DMASYNC_POSTREAD);
955		payload.data = KERNADDR(sc->sc_dma);
956		payload.size = CXDTV_TS_PKTSIZE;
957		sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload);
958	}
959
960	if ((s & CXDTV_TS_RISCI2) == CXDTV_TS_RISCI2) {
961		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map,
962			CXDTV_TS_PKTSIZE, CXDTV_TS_PKTSIZE,
963			BUS_DMASYNC_POSTREAD);
964		payload.data = (char *)(KERNADDR(sc->sc_dma)) + (uintptr_t)CXDTV_TS_PKTSIZE;
965		payload.size = CXDTV_TS_PKTSIZE;
966		sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload);
967	}
968
969done:
970	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT, s);
971
972	return 1;
973}
974
975static int
976cxdtv_allocmem(struct cxdtv_softc *sc, size_t size, size_t align,
977    struct cxdtv_dma *p)
978{
979	int err;
980
981	p->size = size;
982	err = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0,
983	    p->segs, __arraycount(p->segs),
984	    &p->nsegs, BUS_DMA_NOWAIT);
985	if (err)
986		return err;
987	err = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size,
988	    &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
989	if (err)
990		goto free;
991	err = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0,
992	    BUS_DMA_NOWAIT, &p->map);
993	if (err)
994		goto unmap;
995	err = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL,
996	    BUS_DMA_NOWAIT);
997	if (err)
998		goto destroy;
999
1000	return 0;
1001
1002destroy:
1003	bus_dmamap_destroy(sc->sc_dmat, p->map);
1004unmap:
1005	bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
1006free:
1007	bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
1008
1009	return err;
1010}
1011
1012static int
1013cxdtv_freemem(struct cxdtv_softc *sc, struct cxdtv_dma *p)
1014{
1015
1016	bus_dmamap_unload(sc->sc_dmat, p->map);
1017	bus_dmamap_destroy(sc->sc_dmat, p->map);
1018	bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
1019	bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
1020
1021	return 0;
1022}
1023
1024void *
1025cxdtv_mpeg_malloc(struct cxdtv_softc *sc, size_t size)
1026{
1027	struct cxdtv_dma *p;
1028	int err;
1029
1030	p = kmem_alloc(sizeof(*p), KM_SLEEP);
1031	err = cxdtv_allocmem(sc, size, 16, p);
1032	if (err) {
1033		kmem_free(p, sizeof(*p));
1034		device_printf(sc->sc_dev, "not enough memory\n");
1035		return NULL;
1036	}
1037
1038	p->next = sc->sc_dma;
1039	sc->sc_dma = p;
1040
1041	return KERNADDR(p);
1042}
1043
1044static void
1045cxdtv_mpeg_free(struct cxdtv_softc *sc, void *addr)
1046{
1047	struct cxdtv_dma *p;
1048	struct cxdtv_dma **pp;
1049
1050	for (pp = &sc->sc_dma; (p = *pp) != NULL; pp = &p->next) {
1051		if (KERNADDR(p) == addr) {
1052			cxdtv_freemem(sc, p);
1053			*pp = p->next;
1054			kmem_free(p, sizeof(*p));
1055			return;
1056		}
1057	}
1058
1059	device_printf(sc->sc_dev, "%p is already free\n", addr);
1060
1061	return;
1062}
1063
1064
1065/* ATI HDTV Wonder */
1066static void
1067cxdtv_card_init_hdtvwonder(struct cxdtv_softc *sc)
1068{
1069	int i, x;
1070	i2c_addr_t na;
1071	uint8_t nb[5][2] = {
1072	    {0x10, 0x12}, {0x13, 0x04}, {0x16, 0x00},
1073	    {0x14, 0x04}, {0x17, 0x00}
1074	};
1075
1076	/* prepare TUV1236D/TU1236F NIM */
1077
1078	na = 0x0a; /* Nxt2004 address */
1079 	x = 0;
1080
1081	iic_acquire_bus(&sc->sc_i2c, 0);
1082
1083	for(i = 0; i < 5; i++)
1084		x |= iic_exec(&sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, na,
1085		    nb[i], 2, NULL, 0, 0);
1086
1087	iic_release_bus(&sc->sc_i2c, 0);
1088
1089	if (x)
1090		aprint_error_dev(sc->sc_dev, "HDTV Wonder tuner init failed");
1091}
1092
1093/* pcHDTV HD5500 */
1094#define	cxdtv_write_field(_mask, _shift, _value)	\
1095	(((_value) & (_mask)) << (_shift))
1096
1097static void
1098cxdtv_write_gpio(struct cxdtv_softc *sc, uint32_t mask, uint32_t value)
1099{
1100	uint32_t v = 0;
1101	v |= cxdtv_write_field(0xff, 16, mask);
1102	v |= cxdtv_write_field(0xff, 8, mask);
1103	v |= cxdtv_write_field(0xff, 0, (mask & value));
1104	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_GP0_IO, v);
1105}
1106
1107static void
1108cxdtv_card_init_hd5500(struct cxdtv_softc *sc)
1109{
1110	/* hardware (demod) reset */
1111	cxdtv_write_gpio(sc, 1, 0);
1112	delay(100000);
1113	cxdtv_write_gpio(sc, 1, 1);
1114	delay(200000);
1115}
1116
1117MODULE(MODULE_CLASS_DRIVER, cxdtv, "tvpll,nxt2k,lg3303,pci");
1118
1119#ifdef _MODULE
1120#include "ioconf.c"
1121#endif
1122
1123static int
1124cxdtv_modcmd(modcmd_t cmd, void *opaque)
1125{
1126	switch (cmd) {
1127	case MODULE_CMD_INIT:
1128#ifdef _MODULE
1129		return config_init_component(cfdriver_ioconf_cxdtv,
1130		    cfattach_ioconf_cxdtv, cfdata_ioconf_cxdtv);
1131#else
1132		return 0;
1133#endif
1134	case MODULE_CMD_FINI:
1135#ifdef _MODULE
1136		return config_fini_component(cfdriver_ioconf_cxdtv,
1137		    cfattach_ioconf_cxdtv, cfdata_ioconf_cxdtv);
1138#else
1139		return 0;
1140#endif
1141	default:
1142		return ENOTTY;
1143	}
1144}
1145